forked from tgstation/tgstation
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathplant_backfire.dm
125 lines (105 loc) · 4.36 KB
/
plant_backfire.dm
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
/// -- Plant backfire element --
/// Certain high-danger plants, like death-nettles, will backfire and harm the holder if they're not properly protected.
/// If a user is protected with something like leather gloves, they can handle them normally.
/// If they're not protected properly, we invoke a callback on the user, harming or inconveniencing them.
/datum/element/plant_backfire
element_flags = ELEMENT_BESPOKE
argument_hash_start_idx = 2
/// Whether we stop the current action if backfire is triggered (EX: returning CANCEL_ATTACK_CHAIN)
var/cancel_action = FALSE
/// Any extra traits we want to check in addition to TRAIT_PLANT_SAFE. Mobs with a trait in this list will be considered safe. List of traits.
var/extra_traits
/// Any plant genes we want to check that are required for our plant to be dangerous. Plants without a gene in this list will be considered safe. List of typepaths.
var/extra_genes
/datum/element/plant_backfire/Attach(datum/target, cancel_action = FALSE, extra_traits, extra_genes)
. = ..()
if(!isitem(target))
return ELEMENT_INCOMPATIBLE
src.cancel_action = cancel_action
src.extra_traits = extra_traits
src.extra_genes = extra_genes
RegisterSignal(target, COMSIG_ITEM_PRE_ATTACK, PROC_REF(attack_safety_check))
RegisterSignal(target, COMSIG_ITEM_PICKUP, PROC_REF(pickup_safety_check))
RegisterSignal(target, COMSIG_MOVABLE_PRE_THROW, PROC_REF(throw_safety_check))
/datum/element/plant_backfire/Detach(datum/target)
. = ..()
UnregisterSignal(target, list(COMSIG_ITEM_PRE_ATTACK, COMSIG_ITEM_PICKUP, COMSIG_MOVABLE_PRE_THROW))
/**
* Checks before we attack if we're okay to continue.
*
* source - our plant
* user - the mob wielding our [source]
*/
/datum/element/plant_backfire/proc/attack_safety_check(obj/item/source, atom/target, mob/user)
SIGNAL_HANDLER
// Covers stuff like tk, since we aren't actually touching the plant.
if(!user.is_holding(source))
return
if(!backfire(source, user))
return
return cancel_action ? COMPONENT_CANCEL_ATTACK_CHAIN : NONE
/**
* Checks before we pick up the plant if we're okay to continue.
*
* source - our plant
* user - the mob picking our [source]
*/
/datum/element/plant_backfire/proc/pickup_safety_check(obj/item/source, mob/user)
SIGNAL_HANDLER
backfire(source, user)
/**
* Checks before we throw the plant if we're okay to continue.
*
* source - our plant
* thrower - the mob throwing our [source]
*/
/datum/element/plant_backfire/proc/throw_safety_check(obj/item/source, list/arguments)
SIGNAL_HANDLER
var/mob/living/thrower = arguments[4] // the 4th arg = the mob throwing our item
if(!istype(thrower) || !thrower.is_holding(source))
return
if(!backfire(source, thrower))
return
return cancel_action ? COMPONENT_CANCEL_ATTACK_CHAIN : NONE
/**
* The actual backfire occurs here.
* Checks if the user is able to safely handle the plant.
* If not, sends the backfire signal (meaning backfire will occur and be handled by one or multiple genes).
*
* Returns FALSE if the user was safe and no backfire occured.
* Returns TRUE if the user was not safe and a backfire actually happened.
*/
/datum/element/plant_backfire/proc/backfire(obj/item/plant, mob/user)
if(plant_safety_check(plant, user))
return FALSE
SEND_SIGNAL(plant, COMSIG_PLANT_ON_BACKFIRE, user)
return TRUE
/**
* Actually checks if our user is safely handling our plant.
*
* Checks for TRAIT_PLANT_SAFE, and returns TRUE if we have it.
* Then, any extra traits we need to check (Like TRAIT_PIERCEIMMUNE for nettles) and returns TRUE if we have one of them.
* Then, any extra genes we need to check (Like liquid contents for bluespace tomatos) and returns TRUE if we don't have the gene.
*
* source - our plant
* user - the carbon handling our [source]
*
* returns FALSE if none of the checks are successful.
*/
/datum/element/plant_backfire/proc/plant_safety_check(obj/item/plant, mob/living/carbon/user)
if(!istype(user))
return TRUE
if(HAS_TRAIT(user, TRAIT_PLANT_SAFE))
return TRUE
for(var/checked_trait in extra_traits)
if(HAS_TRAIT(user, checked_trait))
return TRUE
var/obj/item/seeds/our_seed = plant.get_plant_seed()
if(our_seed)
for(var/checked_gene in extra_genes)
if(!our_seed.get_gene(checked_gene))
return TRUE
for(var/obj/item/clothing/worn_item in user.get_equipped_items())
if((worn_item.body_parts_covered & HANDS) && (worn_item.clothing_flags & THICKMATERIAL))
return TRUE
return FALSE