forked from tgstation/tgstation
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge remote-tracking branch 'upstream/master'
- Loading branch information
Showing
32 changed files
with
726 additions
and
154 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,198 @@ | ||
/obj/item/forensics_spoofer | ||
name = /obj/item/detective_scanner::name | ||
desc = "Used to adjacently scan objects and biomass for fibers and fingerprints. Can replicate the findings." | ||
icon = /obj/item/detective_scanner::icon | ||
icon_state = /obj/item/detective_scanner::icon_state | ||
w_class = WEIGHT_CLASS_SMALL | ||
inhand_icon_state = /obj/item/detective_scanner::inhand_icon_state | ||
worn_icon_state = /obj/item/detective_scanner::worn_icon_state | ||
lefthand_file = /obj/item/detective_scanner::lefthand_file | ||
righthand_file = /obj/item/detective_scanner::righthand_file | ||
obj_flags = CONDUCTS_ELECTRICITY | ||
item_flags = NOBLUDGEON | ||
slot_flags = ITEM_SLOT_BELT | ||
/// stored fibers in memory | ||
var/list/fibers = list() | ||
/// stored fingerprints in memory | ||
var/list/fingerprints = list() | ||
/// chosen fiber to add to target | ||
var/chosen_fiber | ||
/// chosen fingerprint to add to target | ||
var/chosen_fingerprint | ||
/// max storage for fibers/fingerprints seperate for each | ||
var/max_storage = 5 | ||
/// do we scan for new material? if false will tamper | ||
var/scan_mode = TRUE | ||
/// do we make forensics scanner messages and sounds | ||
var/silent_mode = FALSE | ||
/// tamper cooldown time so people dont spam it on every single wall and thing ever | ||
var/tamper_cooldown_time = 1 SECONDS | ||
COOLDOWN_DECLARE(tamper_cooldown) | ||
|
||
/obj/item/forensics_spoofer/Initialize(mapload) | ||
. = ..() | ||
// most things have add_fingerprint in their item interaction because lol lmao | ||
// tl;dr cut off the chain before anything fires so we dont add user fingerprints to target | ||
RegisterSignal(src, COMSIG_ITEM_INTERACTING_WITH_ATOM, PROC_REF(do_interact)) | ||
|
||
/obj/item/forensics_spoofer/attack_self_secondary(mob/user, modifiers) | ||
. = ..() | ||
if(.) | ||
return | ||
scan_mode = !scan_mode | ||
balloon_alert(user, "now [scan_mode ? "scanning" : "applying"]") | ||
return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN | ||
|
||
// ok due to shenanigans basically every item interact adds your fingerprints to it which isnt ideal so we have this | ||
/obj/item/forensics_spoofer/proc/do_interact(datum/source, mob/living/user, atom/interacting_with, list/modifiers) | ||
SIGNAL_HANDLER | ||
if(scan_mode) | ||
INVOKE_ASYNC(src, PROC_REF(scan), interacting_with, user) | ||
else | ||
tamper(interacting_with, user, do_fibers = !isnull(chosen_fiber)) | ||
return ITEM_INTERACT_SUCCESS | ||
|
||
/obj/item/forensics_spoofer/proc/do_fake_scan(atom/target, mob/user) | ||
if(silent_mode) | ||
return | ||
playsound(src, SFX_INDUSTRIAL_SCAN, 20, TRUE, -2, TRUE, FALSE) | ||
user.visible_message( | ||
span_notice("\The [user] points the [name] at \the [target] and performs a forensic scan.") | ||
) | ||
|
||
/obj/item/forensics_spoofer/proc/clear_values(list/the_list) | ||
for(var/key in the_list) | ||
the_list[key] = "" | ||
|
||
/obj/item/forensics_spoofer/proc/scan(atom/target, mob/living/user) | ||
do_fake_scan(target, user) | ||
if(isnull(target.forensics)) | ||
target.balloon_alert(user, "nothing!") | ||
return ITEM_INTERACT_FAILURE | ||
var/list/new_fibers = LAZYCOPY(target.forensics.fibers) - fibers | ||
var/list/new_prints = LAZYCOPY(target.forensics.fingerprints) - fingerprints | ||
var/new_len = length(new_fibers) + length(new_prints) | ||
balloon_alert(user, "[new_len ? new_len : "no"] new prints/fibers") | ||
if(new_len) | ||
var/list/message = list(span_bold("Scan results (Unstored Only):")) | ||
for(var/text in new_fibers) | ||
message += span_notice("Fiber: [text]") | ||
if(length(fibers) > max_storage) | ||
message += span_boldwarning("Fiber storage full.") | ||
for(var/text in new_prints) | ||
message += span_notice("Fingerprint: [text]") | ||
if(length(fingerprints) > max_storage) | ||
message += span_boldwarning("Fingerprint storage full.") | ||
to_chat(user, boxed_message(jointext(message, "\n")), type = MESSAGE_TYPE_INFO) | ||
if(length(fingerprints) < max_storage) | ||
while(length(fingerprints) + length(new_prints) > max_storage) | ||
var/to_remove = tgui_input_list(user, "Too many prints, cancel to discard all", "What to discard", new_fibers) | ||
if(isnull(to_remove)) | ||
return ITEM_INTERACT_FAILURE | ||
new_prints -= to_remove | ||
clear_values(new_prints) | ||
fingerprints += new_prints | ||
for(var/fingerprint in fingerprints) | ||
fingerprints[fingerprint] = get_name_from_fingerprint(fingerprint) | ||
if(length(fibers) < max_storage) | ||
while(length(fibers) + length(new_fibers) > max_storage) | ||
var/to_remove = tgui_input_list(user, "Too many prints, cancel to discard all", "What to discard", new_fibers) | ||
if(isnull(to_remove)) | ||
return ITEM_INTERACT_FAILURE | ||
new_fibers -= to_remove | ||
clear_values(new_fibers) | ||
fibers += new_fibers | ||
return ITEM_INTERACT_SUCCESS | ||
|
||
/obj/item/forensics_spoofer/proc/tamper(atom/target, mob/living/user, do_fibers = FALSE) | ||
do_fake_scan(target, user) | ||
if((!do_fibers && isnull(chosen_fingerprint)) || (do_fibers && isnull(chosen_fiber))) | ||
balloon_alert(user, "no [do_fibers ? "fiber" : "fingerprint"] selected!") // we CAN automatically select it but if they dont have it selected then they likely didnt know of it in the first place so they learn it now | ||
return ITEM_INTERACT_FAILURE | ||
if(!COOLDOWN_FINISHED(src, tamper_cooldown)) | ||
balloon_alert(user, "please wait!") | ||
return ITEM_INTERACT_FAILURE | ||
if(!isnull(target.forensics) && LAZYFIND(do_fibers ? target.forensics.fibers : target.forensics.fingerprints, do_fibers ? chosen_fiber : chosen_fingerprint)) | ||
balloon_alert(user, "already present!") | ||
return ITEM_INTERACT_FAILURE | ||
|
||
if(do_fibers) | ||
target.add_fiber_list(list(chosen_fiber)) | ||
user.log_message("has tampered with the fingerprints/fibers of [src]. Added [chosen_fiber]", LOG_ATTACK) | ||
else | ||
target.add_fingerprint_list(list(chosen_fingerprint)) | ||
user.log_message("has tampered with the fingerprints/fibers of [src]. Added [chosen_fingerprint]", LOG_ATTACK) | ||
|
||
target.balloon_alert(user, "[do_fibers ? "fiber" : "fingerprint"] added") | ||
target.add_hiddenprint(user) | ||
COOLDOWN_START(src, tamper_cooldown, tamper_cooldown_time) | ||
|
||
return ITEM_INTERACT_SUCCESS | ||
|
||
/obj/item/forensics_spoofer/proc/get_name_from_fingerprint(fingerprint) | ||
. = "Unknown" | ||
for(var/datum/record/crew/player_record as anything in GLOB.manifest.general) | ||
if(player_record.fingerprint != fingerprint) | ||
continue | ||
return player_record.name | ||
|
||
/obj/item/forensics_spoofer/ui_state(mob/user) | ||
return GLOB.hands_state | ||
|
||
/obj/item/forensics_spoofer/ui_interact(mob/user, datum/tgui/ui) | ||
ui = SStgui.try_update_ui(user, src, ui) | ||
if(!ui) | ||
ui = new(user, src, "ForensicsSpoofer", name) | ||
ui.open() | ||
|
||
/obj/item/forensics_spoofer/ui_static_data(mob/user) | ||
. = list( | ||
"max_storage" = max_storage, | ||
) | ||
|
||
/obj/item/forensics_spoofer/ui_data(mob/user) | ||
return list( | ||
"scanmode" = scan_mode, | ||
"silent" = silent_mode, | ||
"fibers" = fibers, | ||
"fingerprints" = fingerprints, | ||
"chosen_fiber" = chosen_fiber, | ||
"chosen_fingerprint" = chosen_fingerprint, | ||
) | ||
|
||
/obj/item/forensics_spoofer/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state) | ||
. = ..() | ||
if(.) | ||
return | ||
if(!isnull(params["chosen"])) //fiber/print actions | ||
var/chosen = params["chosen"] | ||
switch(action) | ||
if("delete") | ||
if(chosen in fibers) | ||
if(chosen_fiber == chosen) | ||
chosen_fiber = null | ||
fibers -= chosen | ||
else | ||
if(chosen_fingerprint == chosen) | ||
chosen_fingerprint = null | ||
fingerprints -= chosen | ||
return TRUE | ||
if("choose") | ||
var/is_fiber = !!(chosen in fibers) | ||
chosen_fiber = is_fiber ? chosen : null | ||
chosen_fingerprint = is_fiber ? null : chosen | ||
return TRUE | ||
if("make_note") | ||
if(chosen in fibers) | ||
fibers[chosen] = params["note"] | ||
else | ||
fingerprints[chosen] = params["note"] | ||
return TRUE | ||
else | ||
switch(action) | ||
if("scanmode") | ||
scan_mode = !scan_mode | ||
return TRUE | ||
if("stealth") | ||
silent_mode = !silent_mode | ||
return TRUE |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.