diff --git a/code/__DEFINES/~skyrat_defines/traits.dm b/code/__DEFINES/~skyrat_defines/traits.dm index 920b58a082f..49f025e4ab0 100644 --- a/code/__DEFINES/~skyrat_defines/traits.dm +++ b/code/__DEFINES/~skyrat_defines/traits.dm @@ -90,3 +90,6 @@ /// Trait given to a piece of eyewear that allows the user to use NIFSoft HUDs #define TRAIT_NIFSOFT_HUD_GRANTER "nifsoft_hud_granter" + +/// Trait given to a brain that is able to accept souls from a RSD +#define TRAIT_RSD_COMPATIBLE "rsd_compatible" diff --git a/modular_skyrat/master_files/code/modules/research/techweb/all_nodes.dm b/modular_skyrat/master_files/code/modules/research/techweb/all_nodes.dm index e263c4062c7..70f7195c8c3 100644 --- a/modular_skyrat/master_files/code/modules/research/techweb/all_nodes.dm +++ b/modular_skyrat/master_files/code/modules/research/techweb/all_nodes.dm @@ -212,6 +212,7 @@ . = ..() design_ids += list( "soulcatcher_device", + "rsd_interface", ) /datum/techweb_node/cyborg_upg_util/New() diff --git a/modular_skyrat/modules/modular_implants/code/soulcatcher/handheld_soulcatcher.dm b/modular_skyrat/modules/modular_implants/code/soulcatcher/handheld_soulcatcher.dm index 842aee82d59..767f396057e 100644 --- a/modular_skyrat/modules/modular_implants/code/soulcatcher/handheld_soulcatcher.dm +++ b/modular_skyrat/modules/modular_implants/code/soulcatcher/handheld_soulcatcher.dm @@ -111,4 +111,52 @@ return TRUE +/obj/item/handheld_soulcatcher/attack_secondary(mob/living/carbon/human/target_mob, mob/living/user, params) + if(!istype(target_mob)) + return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN + + var/obj/item/organ/internal/brain/target_brain = target_mob.get_organ_slot(ORGAN_SLOT_BRAIN) + if(!istype(target_brain)) + to_chat(user, span_warning("[target_mob] lacks a brain!")) + return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN + + if(!HAS_TRAIT(target_brain, TRAIT_RSD_COMPATIBLE)) + to_chat(user, span_warning("[target_mob]'s brain isn't compatible.")) + return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN + + if(target_mob.mind || target_mob.ckey || GetComponent(/datum/component/previous_body)) + to_chat(user, span_warning("[target_mob] is not able to receive a soul")) + return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN + + var/list/soul_list = list() + for(var/datum/soulcatcher_room/room as anything in linked_soulcatcher.soulcatcher_rooms) + for(var/mob/living/soulcatcher_soul/soul as anything in room.current_souls) + if(!soul.round_participant || soul.body_scan_needed) + continue + + soul_list += soul + + if(!length(soul_list)) + to_chat(user, span_warning("There are no souls that can be transferred to [target_mob].")) + return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN + + var/mob/living/soulcatcher_soul/chosen_soul = tgui_input_list(user, "Choose a soul to transfer into the body", name, soul_list) + if(!chosen_soul) + return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN + + if(chosen_soul.previous_body) + var/mob/living/old_body = chosen_soul.previous_body.resolve() + if(!old_body) + return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN + + SEND_SIGNAL(old_body, COMSIG_SOULCATCHER_CHECK_SOUL, FALSE) + + chosen_soul.mind.transfer_to(target_mob, TRUE) + playsound(src, 'modular_skyrat/modules/modular_implants/sounds/default_good.ogg', 50, FALSE, ignore_walls = FALSE) + visible_message(span_notice("[src] beeps: Body transfer complete.")) + log_admin("[src] was used by [user] to transfer [chosen_soul]'s soulcatcher soul to [target_mob].") + + qdel(chosen_soul) + return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN + #undef RSD_ATTEMPT_COOLDOWN diff --git a/modular_skyrat/modules/resleeving/code/research/resleeving_research.dm b/modular_skyrat/modules/resleeving/code/research/resleeving_research.dm new file mode 100644 index 00000000000..4dcd00cc73e --- /dev/null +++ b/modular_skyrat/modules/resleeving/code/research/resleeving_research.dm @@ -0,0 +1,14 @@ +/datum/design/rsd_interface + name = "RSD Phylactery" + desc = "A brain interface that allows for transfer of Resonance from a handheld RSD, such as the Evoker model." + id = "rsd_interface" + build_type = PROTOLATHE | AWAY_LATHE + departmental_flags = DEPARTMENT_BITFLAG_MEDICAL | DEPARTMENT_BITFLAG_SCIENCE + category = list(RND_CATEGORY_EQUIPMENT) + materials = list( + /datum/material/iron = SHEET_MATERIAL_AMOUNT * 0.5, + /datum/material/gold = SHEET_MATERIAL_AMOUNT, + /datum/material/silver = SHEET_MATERIAL_AMOUNT, + ) + build_path = /obj/item/rsd_interface + diff --git a/modular_skyrat/modules/resleeving/code/rsd_interface.dm b/modular_skyrat/modules/resleeving/code/rsd_interface.dm new file mode 100644 index 00000000000..106bb11ea38 --- /dev/null +++ b/modular_skyrat/modules/resleeving/code/rsd_interface.dm @@ -0,0 +1,44 @@ +/obj/item/rsd_interface + name = "RSD Phylactery" + desc = "A small device inserted, typically, into inert brains. As Resonance cannot persist in what's referred to as a 'vacuum', RSDs--much like the brains and CPUs they emulate--employ cerebral white noise as a foundation for Resonance to persist in otherwise dead-quiet containers.." + icon = 'modular_skyrat/modules/aesthetics/implanter/implanter.dmi' + icon_state = "implanter1" + inhand_icon_state = "syringe_0" + lefthand_file = 'icons/mob/inhands/equipment/medical_lefthand.dmi' + righthand_file = 'icons/mob/inhands/equipment/medical_righthand.dmi' + +/// Attempts to use the item on the target brain. +/obj/item/rsd_interface/afterattack(obj/item/organ/internal/brain/target_brain, mob/user, proximity_flag, click_parameters) + . = ..() + if(!proximity_flag || !istype(target_brain)) + return FALSE + + if(HAS_TRAIT(target_brain, TRAIT_NIFSOFT_HUD_GRANTER)) + balloon_alert("already upgraded!") + return FALSE + + user.visible_message(span_notice("[user] upgrades [target_brain] with [src]."), span_notice("You upgrade [target_brain] to be RSD compatible.")) + target_brain.AddElement(/datum/element/rsd_interface) + playsound(target_brain.loc, 'sound/weapons/circsawhit.ogg', 50, vary = TRUE) + + qdel(src) + +/datum/element/rsd_interface/Attach(datum/target) + . = ..() + if(!istype(target, /obj/item/organ/internal/brain)) + return ELEMENT_INCOMPATIBLE + + RegisterSignal(target, COMSIG_ATOM_EXAMINE, PROC_REF(on_examine)) + ADD_TRAIT(target, TRAIT_RSD_COMPATIBLE, INNATE_TRAIT) + +/// Adds text to the examine text of the parent item, explaining that the item can be used to enable the use of NIFSoft HUDs +/datum/element/rsd_interface/proc/on_examine(datum/source, mob/user, list/examine_text) + SIGNAL_HANDLER + examine_text += span_cyan("Souls can be transferred to [source], assuming it is inert.") + +/datum/element/rsd_interface/Detach(datum/target) + UnregisterSignal(target, COMSIG_ATOM_EXAMINE) + REMOVE_TRAIT(target, TRAIT_RSD_COMPATIBLE, INNATE_TRAIT) + + return ..() + diff --git a/tgstation.dme b/tgstation.dme index 32dcb7f22c5..b564e4b4705 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -7503,6 +7503,8 @@ #include "modular_skyrat\modules\records_on_examine\code\record_variables.dm" #include "modular_skyrat\modules\records_on_examine\code\records_procs.dm" #include "modular_skyrat\modules\records_on_examine\code\view_exploitables.dm" +#include "modular_skyrat\modules\resleeving\code\rsd_interface.dm" +#include "modular_skyrat\modules\resleeving\code\research\resleeving_research.dm" #include "modular_skyrat\modules\robohand\code\bodypart_autosurgeon.dm" #include "modular_skyrat\modules\robohand\code\robohand.dm" #include "modular_skyrat\modules\robohand\code\silverhand_bundle.dm"