mirror of
https://github.com/yogstation13/Yogstation.git
synced 2025-02-26 09:04:50 +00:00
one of three things.
1. They don't use RegisterWithParent or UnregisterFromParent to unregister
and register signals
2. They use callbacks which refer to a source object, which is usually deleted
on transfer, or lost in some manner, or simply makes no sense at all to be
transferred
3. the component was never designed to be transferred at all
TransferComponents gave no shits about any of this and just blindly transferred
all components, if they were actually capable of it or not.
I only noticed this because it was causing chairs to break as they would not register signals
and verbs correctly for rotation after being picked up and then placed down, and a player
reported that issue via ahelp.
Luckily we caught it before the rot got anywhere, only chairs and the shuttle subystem
tend to use this proc (Shuttle uses it on turfs), can you imagine if everything was using
this LMAO
Which is good because it's more dangerous than a loaded gun
I have added a can_transfer var, that is true when a component is valid to
actually transfer, which means the dev has actually thought about what happens when
you take the parent object away and swap it for another and all the crazy that is entailed
by this
I have done my best to audit what components are actually
transferable, but things are basically a hot mess (Thanks @Cyberboss )
The following components required edits:
Forensics:
did not register/deregister the clean_act signal properly, did not checkblood on new parent
Rotation:
did not use RegisterWithParent or UnregisterFromParent, turned out
to not be transferable anyway due to having callbacks that can be
passed in to the parent with unknown sources that we can't feasibly
reuse (i.e if you're transferred from a chair to a bed, your old rotation
call backs are no longer valid). Turns out the use case it was for (just chairs)
didn't need it anyway, so I just made it non valid for transfer.
Wet Floor:
Honestly this one is just a hot mess, it should be a subtype of the slippery
component with the extra wet turf handling.
As it is it basically manages a slippery component on top of it's own extra
functionality, so that's a major code smell.
I added registration/unregistration of the signals, and made it's pretransfer
remove the slippery component and the posttransfer add it back (via update_flags)
Components that seem transferable without issues
mirage_border
orbiter
decal
spill
storage (I hope to earth)
185 lines
6.2 KiB
Plaintext
185 lines
6.2 KiB
Plaintext
/datum/component/forensics
|
|
dupe_mode = COMPONENT_DUPE_UNIQUE
|
|
can_transfer = TRUE
|
|
var/list/fingerprints //assoc print = print
|
|
var/list/hiddenprints //assoc ckey = realname/gloves/ckey
|
|
var/list/blood_DNA //assoc dna = bloodtype
|
|
var/list/fibers //assoc print = print
|
|
|
|
/datum/component/forensics/InheritComponent(datum/component/forensics/F, original) //Use of | and |= being different here is INTENTIONAL.
|
|
fingerprints = fingerprints | F.fingerprints
|
|
hiddenprints = hiddenprints | F.hiddenprints
|
|
blood_DNA = blood_DNA | F.blood_DNA
|
|
fibers = fibers | F.fibers
|
|
check_blood()
|
|
return ..()
|
|
|
|
/datum/component/forensics/Initialize(new_fingerprints, new_hiddenprints, new_blood_DNA, new_fibers)
|
|
if(!isatom(parent))
|
|
return COMPONENT_INCOMPATIBLE
|
|
fingerprints = new_fingerprints
|
|
hiddenprints = new_hiddenprints
|
|
blood_DNA = new_blood_DNA
|
|
fibers = new_fibers
|
|
check_blood()
|
|
|
|
/datum/component/forensics/RegisterWithParent()
|
|
check_blood()
|
|
RegisterSignal(parent, COMSIG_COMPONENT_CLEAN_ACT, .proc/clean_act)
|
|
|
|
/datum/component/forensics/UnregisterFromParent()
|
|
UnregisterSignal(parent, list(COMSIG_COMPONENT_CLEAN_ACT))
|
|
|
|
/datum/component/forensics/PostTransfer()
|
|
if(!isatom(parent))
|
|
return COMPONENT_INCOMPATIBLE
|
|
|
|
/datum/component/forensics/proc/wipe_fingerprints()
|
|
fingerprints = null
|
|
return TRUE
|
|
|
|
/datum/component/forensics/proc/wipe_hiddenprints()
|
|
return //no.
|
|
|
|
/datum/component/forensics/proc/wipe_blood_DNA()
|
|
blood_DNA = null
|
|
if(isitem(parent))
|
|
qdel(parent.GetComponent(/datum/component/decal/blood))
|
|
return TRUE
|
|
|
|
/datum/component/forensics/proc/wipe_fibers()
|
|
fibers = null
|
|
return TRUE
|
|
|
|
/datum/component/forensics/proc/clean_act(datum/source, strength)
|
|
if(strength >= CLEAN_STRENGTH_FINGERPRINTS)
|
|
wipe_fingerprints()
|
|
if(strength >= CLEAN_STRENGTH_BLOOD)
|
|
wipe_blood_DNA()
|
|
if(strength >= CLEAN_STRENGTH_FIBERS)
|
|
wipe_fibers()
|
|
|
|
/datum/component/forensics/proc/add_fingerprint_list(list/_fingerprints) //list(text)
|
|
if(!length(_fingerprints))
|
|
return
|
|
LAZYINITLIST(fingerprints)
|
|
for(var/i in _fingerprints) //We use an associative list, make sure we don't just merge a non-associative list into ours.
|
|
fingerprints[i] = i
|
|
return TRUE
|
|
|
|
/datum/component/forensics/proc/add_fingerprint(mob/living/M, ignoregloves = FALSE)
|
|
if(!isliving(M))
|
|
if(!iscameramob(M))
|
|
return
|
|
if(isaicamera(M))
|
|
var/mob/camera/aiEye/ai_camera = M
|
|
if(!ai_camera.ai)
|
|
return
|
|
M = ai_camera.ai
|
|
add_hiddenprint(M)
|
|
if(ishuman(M))
|
|
var/mob/living/carbon/human/H = M
|
|
add_fibers(H)
|
|
if(H.gloves) //Check if the gloves (if any) hide fingerprints
|
|
var/obj/item/clothing/gloves/G = H.gloves
|
|
if(G.transfer_prints)
|
|
ignoregloves = TRUE
|
|
if(!ignoregloves)
|
|
H.gloves.add_fingerprint(H, TRUE) //ignoregloves = 1 to avoid infinite loop.
|
|
return
|
|
var/full_print = md5(H.dna.uni_identity)
|
|
LAZYSET(fingerprints, full_print, full_print)
|
|
return TRUE
|
|
|
|
/datum/component/forensics/proc/add_fiber_list(list/_fibertext) //list(text)
|
|
if(!length(_fibertext))
|
|
return
|
|
LAZYINITLIST(fibers)
|
|
for(var/i in _fibertext) //We use an associative list, make sure we don't just merge a non-associative list into ours.
|
|
fibers[i] = i
|
|
return TRUE
|
|
|
|
/datum/component/forensics/proc/add_fibers(mob/living/carbon/human/M)
|
|
var/fibertext
|
|
var/item_multiplier = isitem(src)?1.2:1
|
|
if(M.wear_suit)
|
|
fibertext = "Material from \a [M.wear_suit]."
|
|
if(prob(10*item_multiplier) && !LAZYACCESS(fibers, fibertext))
|
|
LAZYSET(fibers, fibertext, fibertext)
|
|
if(!(M.wear_suit.body_parts_covered & CHEST))
|
|
if(M.w_uniform)
|
|
fibertext = "Fibers from \a [M.w_uniform]."
|
|
if(prob(12*item_multiplier) && !LAZYACCESS(fibers, fibertext)) //Wearing a suit means less of the uniform exposed.
|
|
LAZYSET(fibers, fibertext, fibertext)
|
|
if(!(M.wear_suit.body_parts_covered & HANDS))
|
|
if(M.gloves)
|
|
fibertext = "Material from a pair of [M.gloves.name]."
|
|
if(prob(20*item_multiplier) && !LAZYACCESS(fibers, fibertext))
|
|
LAZYSET(fibers, fibertext, fibertext)
|
|
else if(M.w_uniform)
|
|
fibertext = "Fibers from \a [M.w_uniform]."
|
|
if(prob(15*item_multiplier) && !LAZYACCESS(fibers, fibertext))
|
|
// "Added fibertext: [fibertext]"
|
|
LAZYSET(fibers, fibertext, fibertext)
|
|
if(M.gloves)
|
|
fibertext = "Material from a pair of [M.gloves.name]."
|
|
if(prob(20*item_multiplier) && !LAZYACCESS(fibers, fibertext))
|
|
LAZYSET(fibers, fibertext, fibertext)
|
|
else if(M.gloves)
|
|
fibertext = "Material from a pair of [M.gloves.name]."
|
|
if(prob(20*item_multiplier) && !LAZYACCESS(fibers, fibertext))
|
|
LAZYSET(fibers, fibertext, fibertext)
|
|
return TRUE
|
|
|
|
/datum/component/forensics/proc/add_hiddenprint_list(list/_hiddenprints) //list(ckey = text)
|
|
if(!length(_hiddenprints))
|
|
return
|
|
LAZYINITLIST(hiddenprints)
|
|
for(var/i in _hiddenprints) //We use an associative list, make sure we don't just merge a non-associative list into ours.
|
|
hiddenprints[i] = _hiddenprints[i]
|
|
return TRUE
|
|
|
|
/datum/component/forensics/proc/add_hiddenprint(mob/M)
|
|
if(!isliving(M))
|
|
if(!iscameramob(M))
|
|
return
|
|
if(isaicamera(M))
|
|
var/mob/camera/aiEye/ai_camera = M
|
|
if(!ai_camera.ai)
|
|
return
|
|
M = ai_camera.ai
|
|
if(!M.key)
|
|
return
|
|
var/hasgloves = ""
|
|
if(ishuman(M))
|
|
var/mob/living/carbon/human/H = M
|
|
if(H.gloves)
|
|
hasgloves = "(gloves)"
|
|
var/current_time = time_stamp()
|
|
if(!LAZYACCESS(hiddenprints, M.key))
|
|
LAZYSET(hiddenprints, M.key, "First: [M.real_name]\[[current_time]\][hasgloves]. Ckey: [M.ckey]")
|
|
else
|
|
var/laststamppos = findtext(LAZYACCESS(hiddenprints, M.key), " Last: ")
|
|
if(laststamppos)
|
|
LAZYSET(hiddenprints, M.key, copytext(hiddenprints[M.key], 1, laststamppos))
|
|
hiddenprints[M.key] += " Last: [M.real_name]\[[current_time]\][hasgloves]. Ckey: [M.ckey]" //made sure to be existing by if(!LAZYACCESS);else
|
|
var/atom/A = parent
|
|
A.fingerprintslast = M.ckey
|
|
return TRUE
|
|
|
|
/datum/component/forensics/proc/add_blood_DNA(list/dna) //list(dna_enzymes = type)
|
|
if(!length(dna))
|
|
return
|
|
LAZYINITLIST(blood_DNA)
|
|
for(var/i in dna)
|
|
blood_DNA[i] = dna[i]
|
|
check_blood()
|
|
return TRUE
|
|
|
|
/datum/component/forensics/proc/check_blood()
|
|
if(!isitem(parent))
|
|
return
|
|
if(!length(blood_DNA))
|
|
return
|
|
parent.LoadComponent(/datum/component/decal/blood)
|