Makes mutations clean up after themselves (#80107)

## About The Pull Request

They weren't doing this before. This was an issue because they hold refs
to a `mob/living/carbon/owner` as well as a `datum/dna`, making it a
potential source of hard dels.

As far as I can tell, I do not see this causing any issues as
`remove_mutation(mutation)` takes a type path as an arg rather than a
reference, same thing with `get_mutation(mutation)`. I couldn't find any
examples of a reference to a mutation being reused by anything after
being removed.

---

When I was investigating potential reasons for why it might have been
like this I found more problem code. Timed dna injectors were setting
`target` to the return value of `add_mutation()`/`remove_mutation()`
which is a bool. This made no sense and would cause runtimes as well as
mislead people into thinking that the return value of those procs was a
`mob/living/carbon`.

## Why It's Good For The Game

Fixes an oversight, and headache further down the line.

## Changelog

🆑
fix: fixed mutations holding onto refs after removal
fix: fixes timed dna injectors
/🆑
This commit is contained in:
Bloop
2023-12-06 21:59:32 -05:00
committed by GitHub
parent e9d484a6c3
commit 3294d7bb2d
4 changed files with 11 additions and 8 deletions
+1
View File
@@ -86,6 +86,7 @@ GLOBAL_LIST_INIT(total_uf_len_by_block, populate_total_uf_len_by_block())
/datum/dna/Destroy()
if(iscarbon(holder))
var/mob/living/carbon/cholder = holder
remove_all_mutations() // mutations hold a reference to the dna
if(cholder.dna == src)
cholder.dna = null
holder = null
+7 -5
View File
@@ -86,6 +86,12 @@
copy_mutation(copymut)
update_valid_chromosome_list()
/datum/mutation/human/Destroy()
power_path = null
dna = null
owner = null
return ..()
/datum/mutation/human/proc/on_acquiring(mob/living/carbon/human/acquirer)
if(!acquirer || !istype(acquirer) || acquirer.stat == DEAD || (src in acquirer.dna.mutations))
return TRUE
@@ -137,11 +143,7 @@
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)
qdel(src)
/mob/living/carbon/proc/update_mutations_overlay()
return
+1 -1
View File
@@ -208,7 +208,7 @@
. = owner.monkeyize()
/datum/mutation/human/race/on_losing(mob/living/carbon/human/owner)
if(owner && owner.stat != DEAD && (owner.dna.mutations.Remove(src)) && ismonkey(owner))
if(!QDELETED(owner) && owner.stat != DEAD && (owner.dna.mutations.Remove(src)) && ismonkey(owner))
owner.fully_replace_character_name(null, original_name)
. = owner.humanize(original_species)
+2 -2
View File
@@ -112,7 +112,7 @@
if(mutation == /datum/mutation/human/race)
if(!ismonkey(target))
continue
target = target.dna.remove_mutation(mutation)
target.dna.remove_mutation(mutation)
else
target.dna.remove_mutation(mutation)
for(var/mutation in add_mutations)
@@ -120,7 +120,7 @@
continue //Skip permanent mutations we already have.
if(mutation == /datum/mutation/human/race && !ismonkey(target))
message_admins("[ADMIN_LOOKUPFLW(user)] injected [key_name_admin(target)] with the [name] [span_danger("(MONKEY)")]")
target = target.dna.add_mutation(mutation, MUT_OTHER, endtime)
target.dna.add_mutation(mutation, MUT_OTHER, endtime)
else
target.dna.add_mutation(mutation, MUT_OTHER, endtime)
if(fields)