Skip to content

CSI Eridani: Detective content update #27512

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 45 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 27 commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
ef9139f
Ports Bay/ss220 detective work
silverplatedelta Nov 21, 2024
ba7292a
Removs detective scanner from circulation
silverplatedelta Nov 21, 2024
577c794
forensic supply crate
silverplatedelta Dec 1, 2024
60c7b72
Ports Bay/ss220 detective work
silverplatedelta Nov 21, 2024
fc74f0d
Removs detective scanner from circulation
silverplatedelta Nov 21, 2024
63579e3
forensic supply crate
silverplatedelta Dec 1, 2024
375121e
Merge branch 'detContentV2' of https://github.com/silverplatedelta/Pa…
silverplatedelta Dec 1, 2024
5bb74a0
Mapping changes
silverplatedelta Dec 1, 2024
202d2ea
Mapping changes
silverplatedelta Dec 1, 2024
0efb25b
Merge branch 'detContentV2' of https://github.com/silverplatedelta/Pa…
silverplatedelta Dec 1, 2024
ebde63c
Ports Bay/ss220 detective work
silverplatedelta Nov 21, 2024
2ce6282
Removs detective scanner from circulation
silverplatedelta Nov 21, 2024
e94d3c9
Merge branch 'detContentV2' of https://github.com/silverplatedelta/Pa…
silverplatedelta Dec 1, 2024
feda2ee
makes linters work
silverplatedelta Dec 1, 2024
cc09cac
i hate vscode
silverplatedelta Dec 1, 2024
ded3080
fixes some nonsence
silverplatedelta Dec 1, 2024
344c16e
may fix CI
silverplatedelta Dec 1, 2024
49f5f7a
restore maps to CURRENT
silverplatedelta Dec 1, 2024
7ca6915
QOL
silverplatedelta Dec 1, 2024
5d1b0a2
makes gunshot residue actually work.
silverplatedelta Dec 1, 2024
8b6844d
fixes cursed logic
silverplatedelta Dec 1, 2024
9290b5e
adds scene cards again
silverplatedelta Dec 1, 2024
fd3d7f6
scene cards but real!
silverplatedelta Dec 1, 2024
8f13d75
Merge branch 'master' into detContentV2
silverplatedelta Dec 19, 2024
2adaa82
fix med records, breaks attack chain
silverplatedelta Dec 19, 2024
4a6717f
Merge branch 'master' into detContentV2
silverplatedelta Dec 30, 2024
d717549
Merge branch 'master' into detContentV2
silverplatedelta Jan 2, 2025
26ce1c4
Merge branch 'master' into detContentV2
silverplatedelta Feb 19, 2025
8dc4645
Revives the PR
silverplatedelta Feb 19, 2025
1c77433
fixes swabs
silverplatedelta Feb 21, 2025
938112d
Merge branch 'master' into detContentV2
silverplatedelta Apr 29, 2025
b2be54f
TGUI update
silverplatedelta Apr 29, 2025
a78c5a4
lewc and dgl first reviews
silverplatedelta Apr 29, 2025
c8c4e4e
dna medical records
Burzah Apr 30, 2025
568a34f
Merge pull request #4 from silverplatedelta/tgui-det-records
Burzah Apr 30, 2025
df6dde5
LINTERS FIX
silverplatedelta May 3, 2025
3ffde65
Merge branch 'master' into detContentV2
silverplatedelta May 17, 2025
e177887
linter fix 2
silverplatedelta May 17, 2025
e96137d
blood fix and linters again
silverplatedelta May 17, 2025
7175a4f
oops
silverplatedelta May 17, 2025
33f983c
updated but broke
silverplatedelta May 17, 2025
fba6773
help
silverplatedelta May 17, 2025
2fea276
Chuga suggestion
silverplatedelta May 18, 2025
d068f59
Fix shoes ending up with a null blood_DNA entry
chuga-git May 18, 2025
3fa0fb6
replace astype() because linters are still in the stone age
chuga-git May 18, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion code/game/jobs/job/security_jobs.dm
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,6 @@
pda = /obj/item/pda/detective
backpack_contents = list(
/obj/item/storage/box/evidence = 1,
/obj/item/detective_scanner = 1,
/obj/item/melee/classic_baton/telescopic = 1
)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,6 @@
new /obj/item/storage/box/evidence(src)
new /obj/item/clipboard(src)
new /obj/item/radio/headset/headset_sec/alt(src)
new /obj/item/detective_scanner(src)
new /obj/item/ammo_box/magazine/detective/speedcharger(src)
new /obj/item/ammo_box/magazine/detective/speedcharger(src)
new /obj/effect/spawner/detgun(src)
Expand Down
1 change: 1 addition & 0 deletions code/modules/clothing/clothing.dm
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@

/// Detective Work, used for allowing a given atom to leave its fibers on stuff. Allowed by default
var/can_leave_fibers = TRUE
var/gunshot_residue

/obj/item/clothing/update_icon_state()
if(!can_toggle)
Expand Down
174 changes: 174 additions & 0 deletions code/modules/detective_work/evidence.dm
Original file line number Diff line number Diff line change
Expand Up @@ -80,3 +80,177 @@
else
to_chat(user, "[src] is empty.")
icon_state = "evidenceobj"

/obj/item/forensics
icon = 'icons/obj/forensics/forensics.dmi'
w_class = WEIGHT_CLASS_TINY

/obj/item/sample
name = "\improper Forensic sample"
icon = 'icons/obj/forensics/forensics.dmi'
w_class = WEIGHT_CLASS_TINY
var/list/evidence = list()

/obj/item/sample/New(newloc, atom/supplied)
..(newloc)
if(supplied)
copy_evidence(supplied)
name = "[initial(name)] (\the [supplied])"

/obj/item/sample/print/New(newloc, atom/supplied)
..(newloc, supplied)
if(evidence && evidence.len)
icon_state = "fingerprint1"

/obj/item/sample/proc/copy_evidence(atom/supplied)
if(supplied.suit_fibers && supplied.suit_fibers.len)
evidence = supplied.suit_fibers.Copy()
supplied.suit_fibers.Cut()

/obj/item/sample/proc/merge_evidence(obj/item/sample/supplied, mob/user)
if(!supplied.evidence || !supplied.evidence.len)
return FALSE
evidence |= supplied.evidence
name = ("[initial(name)] (combined)")
to_chat(user, "<span class='notice'>You are moving \the [supplied] to \the [src].</span>")
return TRUE

/obj/item/sample/print/merge_evidence(obj/item/sample/supplied, mob/user)
if(!supplied.evidence || !supplied.evidence.len)
return FALSE
for(var/print in supplied.evidence)
if(evidence[print])
evidence[print] = stringmerge(evidence[print],supplied.evidence[print])
else
evidence[print] = supplied.evidence[print]
name = ("[initial(name)] (combined)")
to_chat(user, "<span class='notice'>You overlay \the [src] and \the [supplied], combining the print records.</span>")
return TRUE

/obj/item/sample/pre_attack(atom/A, mob/living/user, params)
. = ..()
// Fingerprints will be handled in after_attack() to not mess up the samples taken
return A.attackby(src, user, params)

/obj/item/sample/attackby(obj/O, mob/user)
if(O.type == src.type)
user.unEquip(O)
if(merge_evidence(O, user))
qdel(O)
return TRUE
return ..()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This proc can be cleaned up by using a guard clause


/obj/item/sample/fibers
name = "\improper fiber bag"
desc = "Used to store fiber evidence for forensic examination."
icon_state = "fiberbag"

/obj/item/sample/print
name = "\improper fingerprint card"
desc = "Preserves fingerprints."
icon = 'icons/obj/card.dmi'
icon_state = "fingerprint0"
item_state = "paper"

/obj/item/sample/print/attack_self(mob/user)
if(evidence && evidence.len)
return
if(!ishuman(user))
return
var/mob/living/carbon/human/H = user
if(H.gloves)
to_chat(user, "<span class='warning'>Take [H.gloves] off first.</span>")
return

to_chat(user, "<span class='notice'>You press your fingertips firmly against the card.</span>")
var/fullprint = H.get_full_print()
evidence[fullprint] = fullprint
name = ("[initial(name)] ([H])")
icon_state = "fingerprint1"

/obj/item/sample/print/attack(mob/living/M, mob/user)

if(!ishuman(M))
return ..()

if(evidence && evidence.len)
return FALSE

var/mob/living/carbon/human/H = M

if(H.gloves)
to_chat(user, "<span class='warning'>[H] is wearing gloves.</span>")
return TRUE

if(user != H && H.a_intent != INTENT_HELP && !IS_HORIZONTAL(H))
user.visible_message("<span class='danger'>[user] tried to fingerprint [H], but he resists.</span>")
return TRUE

if(user.zone_selected == "r_hand" || user.zone_selected == "l_hand")
var/has_hand
var/obj/item/organ/external/O = H.has_organ("r_hand")
if(istype(O))
has_hand = TRUE
else
O = H.has_organ("l_hand")
if(istype(O))
has_hand = TRUE
if(!has_hand)
to_chat(user, "<span class='warning'>But [H] has no hands.</span>")
return FALSE
if(!do_after(user, 2 SECONDS, target = user))
return FALSE

user.visible_message("<span class='notice'>[user] makes a copy of [H]'s fingerprints'.</span>")
var/fullprint = H.get_full_print()
evidence[fullprint] = fullprint
copy_evidence(src)
name = ("[initial(name)] (\the [H])")
icon_state = "fingerprint1"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you change the icon state in an update_icon_state() override, and then invoke update_appearance() with the right flags here, instead?

return TRUE
return FALSE

/obj/item/sample/print/copy_evidence(atom/supplied)
if(supplied.fingerprints && supplied.fingerprints.len)
for(var/print in supplied.fingerprints)
evidence[print] = supplied.fingerprints[print]
supplied.fingerprints.Cut()

/obj/item/forensics/sample_kit
name = "\improper fiber collection kit"
desc = "Magnifying glass and tweezers. Used to lift fabric fibers."
icon_state = "m_glass"
w_class = WEIGHT_CLASS_SMALL
var/evidence_type = "fibers"
var/evidence_path = /obj/item/sample/fibers

/obj/item/forensics/sample_kit/proc/can_take_sample(mob/user, atom/supplied)
return (supplied.suit_fibers && supplied.suit_fibers.len)

/obj/item/forensics/sample_kit/proc/take_sample(mob/user, atom/supplied)
var/obj/item/sample/S = new evidence_path(get_turf(user), supplied)
to_chat(user, "<span class='notice'>You move [S.evidence.len] [S.evidence.len > 1 ? "[evidence_type]" : "[evidence_type]"] в \the [S].</span>")

/obj/item/forensics/sample_kit/afterattack(atom/A, mob/user, proximity)
if(!proximity)
return
if(can_take_sample(user, A))
take_sample(user,A)
. = TRUE
else
to_chat(user, "<span class='warning'>You cannot find [evidence_type] on [A].</span>")
. = ..()

/obj/item/forensics/sample_kit/MouseDrop(atom/over)
if(ismob(src.loc))
afterattack(over, usr, TRUE)

/obj/item/forensics/sample_kit/powder
name = "\improper Fingerprint Powder"
desc = "A jar of aluminum powder and a specialized brush."
icon_state = "dust"
evidence_type = "prints"
evidence_path = /obj/item/sample/print

/obj/item/forensics/sample_kit/powder/can_take_sample(mob/user, atom/supplied)
return (supplied.fingerprints && supplied.fingerprints.len)
68 changes: 68 additions & 0 deletions code/modules/detective_work/forensic_kits.dm
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
// Boxes
/obj/item/storage/box/swabs
name = "\improper Box of Forensic Swabs"
desc = "Sterile equipment inside. Avoid contamination."
icon = 'icons/obj/boxes.dmi'
icon_state = "sec_box"

/obj/item/storage/box/swabs/populate_contents()
..()
new /obj/item/forensics/swab(src)
new /obj/item/forensics/swab(src)
new /obj/item/forensics/swab(src)
new /obj/item/forensics/swab(src)
new /obj/item/forensics/swab(src)
new /obj/item/forensics/swab(src)

/obj/item/storage/box/fingerprints
name = "\improper Box of Fingerprint Cards"
desc = "Sterile equipment inside. Avoid contamination."
icon = 'icons/obj/boxes.dmi'
icon_state = "id_prisoner_box"

/obj/item/storage/box/fingerprints/populate_contents()
..()
new /obj/item/sample/print(src)
new /obj/item/sample/print(src)
new /obj/item/sample/print(src)
new /obj/item/sample/print(src)
new /obj/item/sample/print(src)
new /obj/item/sample/print(src)

// Crime scene kit
/obj/item/storage/briefcase/crimekit
name = "\improper Crime Scene Kit"
desc = "Stainless steel coated case containing everything a detective could need. Feels heavy."
icon = 'icons/obj/forensics/forensics.dmi'
icon_state = "case"
lefthand_file = 'icons/obj/forensics/items_lefthand.dmi'
righthand_file = 'icons/obj/forensics/items_righthand.dmi'
item_state = "case"

/obj/item/storage/briefcase/crimekit/populate_contents()
..()
new /obj/item/storage/box/swabs(src)
new /obj/item/storage/box/fingerprints(src)
new /obj/item/forensics/sample_kit(src)
new /obj/item/forensics/sample_kit/powder(src)
new /obj/item/storage/csi_markers(src)

/obj/structure/closet/secure_closet/detective/populate_contents()
new /obj/item/storage/briefcase/crimekit(src)
. = ..()

/obj/item/storage/csi_markers
name = "crime scene markers box"
desc = "A cardboard box for crime scene marker cards."
icon = 'icons/obj/boxes.dmi'
icon_state = "sec_box"
w_class = WEIGHT_CLASS_TINY

/obj/item/storage/csi_markers/populate_contents()
new /obj/item/csi_marker/n1(src)
new /obj/item/csi_marker/n2(src)
new /obj/item/csi_marker/n3(src)
new /obj/item/csi_marker/n4(src)
new /obj/item/csi_marker/n5(src)
new /obj/item/csi_marker/n6(src)
new /obj/item/csi_marker/n7(src)
Loading
Loading