-
-
Notifications
You must be signed in to change notification settings - Fork 444
/
Copy pathmutations.dm
224 lines (198 loc) · 8.8 KB
/
mutations.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
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
/datum/mutation
var/name
/datum/mutation/human
name = "mutation"
var/desc = "A mutation."
///Whether the mutation is locked, and therefore will not show up in
///people's genes randomly.
var/locked
var/quality
var/get_chance = 100
var/lowest_value = 256 * 8
var/text_gain_indication = ""
var/text_lose_indication = ""
var/static/list/list/mutable_appearance/visual_indicators = list()
/// The path of action we grant to our user on mutation gain
var/datum/action/cooldown/spell/power_path
var/layer_used = MUTATIONS_LAYER //which mutation layer to use
var/list/species_allowed = list() //to restrict mutation to only certain species
var/health_req //minimum health required to acquire the mutation
var/limb_req //required limbs to acquire this mutation
var/time_coeff = 1 //coefficient for timed mutations
var/datum/dna/dna
var/mob/living/carbon/human/owner
var/instability = 0 //instability the holder gets when the mutation is not native
var/blocks = 4 //Amount of those big blocks with gene sequences
var/difficulty = 8 //Amount of missing sequences. Sometimes it removes an entire pair for 2 points
var/timed = FALSE //Boolean to easily check if we're going to self destruct
var/alias //'Mutation #49', decided every round to get some form of distinction between undiscovered mutations
var/scrambled = FALSE //Wheter we can read it if it's active. To avoid cheesing with mutagen
var/class //Decides player accesibility, sorta
var/list/conflicts //any mutations that might conflict. put mutation typepath defines in here. make sure to enter it both ways (so that A conflicts with B, and B with A)
///Boolean on whether the mutation can be transferred through cloning
var/allow_transfer = FALSE
///Boolean on whether the mutation can be downloaded onto a DNA console and cloned.
var/allow_cloning = TRUE
//MUT_NORMAL - A mutation that can be activated and deactived by completing a sequence
//MUT_EXTRA - A mutation that is in the mutations tab, and can be given and taken away through though the DNA console. Has a 0 before it's name in the mutation section of the dna console
//MUT_OTHER Cannot be interacted with by players through normal means. I.E. wizards mutate
var/can_chromosome = CHROMOSOME_NONE //can we take chromosomes? 0: CHROMOSOME_NEVER never, 1:CHROMOSOME_NONE yeah, 2: CHROMOSOME_USED no, already have one
var/chromosome_name //purely cosmetic
var/modified = FALSE //ugly but we really don't want chromosomes and on_acquiring to overlap and apply double the powers
var/mutadone_proof = FALSE
//Chromosome stuff - set to -1 to prevent people from changing it. Example: It'd be a waste to decrease cooldown on mutism
var/stabilizer_coeff = 1 //genetic stability coeff
var/synchronizer_coeff = -1 //makes the mutation hurt the user less
var/power_coeff = -1 //boosts mutation strength
var/energy_coeff = -1 //lowers mutation cooldown
var/list/valid_chrom_list = list() //List of strings of valid chromosomes this mutation can accept.
/datum/mutation/human/New(class_ = MUT_OTHER, timer, datum/mutation/human/copymut)
. = ..()
class = class_
if(timer)
addtimer(CALLBACK(src, PROC_REF(remove)), timer)
timed = TRUE
if(copymut && istype(copymut, /datum/mutation/human))
copy_mutation(copymut)
update_valid_chromosome_list()
/datum/mutation/human/proc/on_acquiring(mob/living/carbon/human/H)
if(!H || !istype(H) || H.stat == DEAD || (src in H.dna.mutations))
return TRUE
for(var/i in H.dna.mutations)
if(is_type_in_list(i, conflicts))
return TRUE
if(species_allowed.len && !species_allowed.Find(H.dna.species.id))
return TRUE
if(health_req && H.health < health_req)
return TRUE
if(limb_req && !H.get_bodypart(limb_req))
return TRUE
owner = H
dna = H.dna
dna.mutations += src
if(text_gain_indication)
to_chat(owner, text_gain_indication)
if(visual_indicators.len)
var/list/mut_overlay = list(get_visual_indicator())
if(owner.overlays_standing[layer_used])
mut_overlay = owner.overlays_standing[layer_used]
mut_overlay |= get_visual_indicator()
owner.remove_overlay(layer_used)
owner.overlays_standing[layer_used] = mut_overlay
owner.apply_overlay(layer_used)
grant_power() //we do checks here so nothing about hulk getting magic
if(!modified)
addtimer(CALLBACK(src, PROC_REF(modify), 0.5 SECONDS)) //gonna want children calling ..() to run first
/datum/mutation/human/proc/get_visual_indicator()
return
/datum/mutation/human/proc/on_attack_hand( atom/target, proximity)
return
/datum/mutation/human/proc/on_ranged_attack(atom/target)
return
/datum/mutation/human/proc/on_life()
return
/datum/mutation/human/proc/on_losing(mob/living/carbon/human/owner)
if(owner && istype(owner) && (owner.dna.mutations.Remove(src)))
if(text_lose_indication && owner.stat != DEAD)
to_chat(owner, text_lose_indication)
if(visual_indicators.len)
var/list/mut_overlay = list()
if(owner.overlays_standing[layer_used])
mut_overlay = owner.overlays_standing[layer_used]
owner.remove_overlay(layer_used)
mut_overlay.Remove(get_visual_indicator())
owner.overlays_standing[layer_used] = mut_overlay
owner.apply_overlay(layer_used)
if(power_path)
// Any powers we made are linked to our mutation datum,
// so deleting ourself will also delete it and remove it
// ...Why don't all mutations delete on loss? Not sure.
qdel(src)
return 0
return 1
/mob/living/carbon/proc/update_mutations_overlay()
return
/mob/living/carbon/human/update_mutations_overlay()
for(var/datum/mutation/human/CM in dna.mutations)
if(CM.species_allowed.len && !CM.species_allowed.Find(dna.species.id))
dna.force_lose(CM) //shouldn't have that mutation at all
continue
if(CM.visual_indicators.len)
var/list/mut_overlay = list()
if(overlays_standing[CM.layer_used])
mut_overlay = overlays_standing[CM.layer_used]
var/mutable_appearance/V = CM.get_visual_indicator()
if(!mut_overlay.Find(V)) //either we lack the visual indicator or we have the wrong one
remove_overlay(CM.layer_used)
for(var/mutable_appearance/MA in CM.visual_indicators[CM.type])
mut_overlay.Remove(MA)
mut_overlay |= V
overlays_standing[CM.layer_used] = mut_overlay
apply_overlay(CM.layer_used)
/**
* Called when a chromosome is applied so we can properly update some stats
* without having to remove and reapply the mutation from someone
*
* Returns `null` if no modification was done, and
* returns an instance of a power if modification was complete
*/
/datum/mutation/human/proc/modify() //called when a genome is applied so we can properly update some stats without having to remove and reapply the mutation from someone
if(modified || !power_path || !owner)
return
var/datum/action/cooldown/spell/modified_power = locate(power_path) in owner.actions
if(!modified_power)
CRASH("Genetic mutation [type] called modify(), but could not find a action to modify!")
modified_power.cooldown_time *= GET_MUTATION_ENERGY(src) // Doesn't do anything for mutations with energy_coeff unset
return modified_power
/datum/mutation/human/proc/copy_mutation(datum/mutation/human/HM)
if(!HM)
return
chromosome_name = HM.chromosome_name
stabilizer_coeff = HM.stabilizer_coeff
synchronizer_coeff = HM.synchronizer_coeff
power_coeff = HM.power_coeff
energy_coeff = HM.energy_coeff
mutadone_proof = HM.mutadone_proof
can_chromosome = HM.can_chromosome
valid_chrom_list = HM.valid_chrom_list
/datum/mutation/human/proc/remove_chromosome()
stabilizer_coeff = initial(stabilizer_coeff)
synchronizer_coeff = initial(synchronizer_coeff)
power_coeff = initial(power_coeff)
energy_coeff = initial(energy_coeff)
mutadone_proof = initial(mutadone_proof)
can_chromosome = initial(can_chromosome)
chromosome_name = null
/datum/mutation/human/proc/remove()
if(dna)
dna.force_lose(src)
else
qdel(src)
/datum/mutation/human/proc/grant_power()
if(!ispath(power_path) || !owner)
return FALSE
var/datum/action/cooldown/new_power = new power_path(src)
new_power.background_icon_state = "bg_tech_blue"
new_power.base_background_icon_state = new_power.background_icon_state
new_power.active_background_icon_state = "[new_power.base_background_icon_state]_on"
new_power.overlay_icon_state = "bg_tech_blue_border"
new_power.active_overlay_icon_state = null
new_power.panel = "Genetic"
new_power.Grant(owner)
return new_power
// Runs through all the coefficients and uses this to determine which chromosomes the
// mutation can take. Stores these as text strings in a list.
/datum/mutation/human/proc/update_valid_chromosome_list()
valid_chrom_list.Cut()
if(can_chromosome == CHROMOSOME_NEVER)
valid_chrom_list += "none"
return
valid_chrom_list += "Reinforcement"
if(stabilizer_coeff != -1)
valid_chrom_list += "Stabilizer"
if(synchronizer_coeff != -1)
valid_chrom_list += "Synchronizer"
if(power_coeff != -1)
valid_chrom_list += "Power"
if(energy_coeff != -1)
valid_chrom_list += "Energetic"