diff --git a/code/__DEFINES/~~bubber_defines/_globalvars/lists/invalid_uplink_item.dm b/code/__DEFINES/~~bubber_defines/_globalvars/lists/invalid_uplink_item.dm new file mode 100644 index 00000000000..bd7d7c6e422 --- /dev/null +++ b/code/__DEFINES/~~bubber_defines/_globalvars/lists/invalid_uplink_item.dm @@ -0,0 +1,4 @@ +//Whether an item is a valid uplink location or not +GLOBAL_LIST_INIT(invalid_uplink_location, typecacheof(list( + /obj/item/modular_computer/pda/synth +))) diff --git a/code/datums/mind/antag.dm b/code/datums/mind/antag.dm index 4641abe1c89..312f6838577 100644 --- a/code/datums/mind/antag.dm +++ b/code/datums/mind/antag.dm @@ -86,7 +86,9 @@ * Returns the item found, or null if no item was found. */ /mob/living/carbon/proc/get_uplink_location(desired_location = UPLINK_PDA) - var/list/all_contents = get_all_contents() + //BUBBER EDIT BEGIN - original line is var/list/all_contents = get_all_contents() + var/list/all_contents = typecache_filter_list_reverse(get_all_contents(), GLOB.invalid_uplink_location) + //BUBBER EDIT END var/obj/item/modular_computer/pda/my_pda = locate() in all_contents var/obj/item/radio/my_radio = locate() in all_contents var/obj/item/pen/my_pen = (locate() in my_pda) || (locate() in all_contents) diff --git a/code/modules/jobs/job_types/_job.dm b/code/modules/jobs/job_types/_job.dm index 21c81e9d711..5edbf0780f7 100644 --- a/code/modules/jobs/job_types/_job.dm +++ b/code/modules/jobs/job_types/_job.dm @@ -480,7 +480,10 @@ if(equipped_client) pda.update_pda_prefs(equipped_client) - + //BUBBER EDIT BEGIN + var/obj/item/modular_computer/pda/synth/brainpooter = locate() in equipped.get_all_contents() + brainpooter.update_user_settings(equipped_client) + //BUBBER EDIT END /datum/outfit/job/get_chameleon_disguise_info() var/list/types = ..() types -= /obj/item/storage/backpack //otherwise this will override the actual backpacks diff --git a/modular_skyrat/modules/organs/code/brain.dm b/modular_skyrat/modules/organs/code/brain.dm index 03695119579..50fa77cda76 100644 --- a/modular_skyrat/modules/organs/code/brain.dm +++ b/modular_skyrat/modules/organs/code/brain.dm @@ -9,6 +9,43 @@ organ_flags = ORGAN_ORGANIC | ORGAN_ROBOTIC | ORGAN_VITAL | ORGAN_PROMINENT //it's a bit weird to be both organic and robotic, but yk emp_dmg_mult = 1.5 //Note that the base damage is 20/10 + //internal computer for cortical + var/obj/item/modular_computer/pda/synth/internal_computer + actions_types = list(/datum/action/item_action/synth/open_internal_computer) + +/obj/item/organ/brain/cybernetic/cortical/Initialize(mapload) + . = ..() + internal_computer = new(src) + ADD_TRAIT(src, TRAIT_SILICON_EMOTES_ALLOWED, INNATE_TRAIT) + +/obj/item/organ/brain/cybernetic/cortical/Destroy() + QDEL_NULL(internal_computer) + return ..() + +/obj/item/organ/brain/cybernetic/cortical/on_mob_insert(mob/living/carbon/human/brain_owner, special, movement_flags) + . = ..() + if(!istype(brain_owner)) + return + RegisterSignal(brain_owner, COMSIG_MOB_EQUIPPED_ITEM, PROC_REF(on_equip_signal)) + if(internal_computer && brain_owner.wear_id) + internal_computer.handle_id_slot(brain_owner, brain_owner.wear_id) + +/obj/item/organ/brain/cybernetic/cortical/on_mob_remove(mob/living/carbon/human/brain_owner, special) + . = ..() + if(!istype(brain_owner)) + return + UnregisterSignal(brain_owner, COMSIG_MOB_EQUIPPED_ITEM) + if(internal_computer) + internal_computer.handle_id_slot(brain_owner) + internal_computer.clear_id_slot_signals(brain_owner.wear_id) + +/obj/item/organ/brain/cybernetic/cortical/proc/on_equip_signal(datum/source, obj/item/item, slot) + SIGNAL_HANDLER + if(isnull(internal_computer)) + return + if(slot == ITEM_SLOT_ID) + internal_computer.handle_id_slot(owner, item) + //Extra effects /obj/item/organ/brain/cybernetic/cortical/emp_act(severity) . = ..() @@ -45,6 +82,61 @@ emp_dmg_mult = 1.5 //Note that the base damage is 20/10 emp_dmg_max = 999 + //internal computer for surplus + var/obj/item/modular_computer/pda/synth/internal_computer + actions_types = list(/datum/action/item_action/synth/open_internal_computer) +/obj/item/organ/brain/cybernetic/surplus/Initialize(mapload) + . = ..() + internal_computer = new(src) + ADD_TRAIT(src, TRAIT_SILICON_EMOTES_ALLOWED, INNATE_TRAIT) + +/obj/item/organ/brain/cybernetic/surplus/Destroy() + QDEL_NULL(internal_computer) + return ..() + +/obj/item/organ/brain/cybernetic/surplus/on_mob_insert(mob/living/carbon/human/brain_owner, special, movement_flags) + . = ..() + if(!istype(brain_owner)) + return + RegisterSignal(brain_owner, COMSIG_MOB_EQUIPPED_ITEM, PROC_REF(on_equip_signal)) + if(internal_computer && brain_owner.wear_id) + internal_computer.handle_id_slot(brain_owner, brain_owner.wear_id) + +/obj/item/organ/brain/cybernetic/surplus/on_mob_remove(mob/living/carbon/human/brain_owner, special) + . = ..() + if(!istype(brain_owner)) + return + UnregisterSignal(brain_owner, COMSIG_MOB_EQUIPPED_ITEM) + if(internal_computer) + internal_computer.handle_id_slot(brain_owner) + internal_computer.clear_id_slot_signals(brain_owner.wear_id) + +/obj/item/organ/brain/cybernetic/surplus/proc/on_equip_signal(datum/source, obj/item/item, slot) + SIGNAL_HANDLER + if(isnull(internal_computer)) + return + if(slot == ITEM_SLOT_ID) + internal_computer.handle_id_slot(owner, item) + + + +//Extra effects for surplus - tripled from cortical +/obj/item/organ/brain/cybernetic/surplus/emp_act(severity) + . = ..() + if(. & EMP_PROTECT_SELF) + return + if(owner.stat == DEAD) + return + switch(severity) + if(1) + owner.set_jitter_if_lower(90 SECONDS) + owner.adjust_stutter(90 SECONDS) + owner.adjust_confusion(30 SECONDS) + if(2) + owner.set_jitter_if_lower(45 SECONDS) + owner.adjust_stutter(45 SECONDS) + owner.adjust_confusion(9 SECONDS) + /obj/item/organ/brain/cybernetic/surplus/Initialize(mapload) . = ..() AddElement(/datum/element/dangerous_organ_removal, /*surgical = */ TRUE, /*annihilate = */ FALSE) //annihilate just means it wont qdel when removed diff --git a/modular_skyrat/modules/synths/code/bodyparts/internal_computer/internal_computer.dm b/modular_skyrat/modules/synths/code/bodyparts/internal_computer/internal_computer.dm index 0f564989296..55638f18ceb 100644 --- a/modular_skyrat/modules/synths/code/bodyparts/internal_computer/internal_computer.dm +++ b/modular_skyrat/modules/synths/code/bodyparts/internal_computer/internal_computer.dm @@ -5,7 +5,6 @@ icon_state = "posibrain" base_icon_state = "posibrain" greyscale_config = null - post_init_icon_state = null base_active_power_usage = 0 WATTS base_idle_power_usage = 0 WATTS @@ -13,32 +12,31 @@ max_idle_programs = 3 - max_capacity = parent_type::max_capacity * 2 + max_capacity = 64 + flags_1 = parent_type::flags_1 | NO_NEW_GAGS_PREVIEW_1 /obj/item/modular_computer/pda/synth/Initialize(mapload) . = ..() - // prevent these from being created outside of synth brains - if(!istype(loc, /obj/item/organ/brain/synth)) + // prevent these from being created outside of valid brains + if(!istype(loc, /obj/item/organ/brain/synth) && !istype(loc, /obj/item/organ/brain/cybernetic/cortical) && !istype(loc, /obj/item/organ/brain/cybernetic/surplus)) return INITIALIZE_HINT_QDEL - //this code has to be called at a delay because the required data (synth owner's job) is null when initialized - addtimer(CALLBACK(src, TYPE_PROC_REF(/obj/item/modular_computer/pda/synth, post_initialize)), 1 DECISECONDS) +/obj/item/modular_computer/pda/synth/proc/update_user_settings(client/client) + var/obj/item/organ/brain/cybernetic/brainpooter = loc + var/mob/living/brain_owner = brainpooter.owner + if(!isnull(brain_owner)) + imprint_id("[brain_owner.real_name] Persocom", brain_owner.job) + var/datum/mind/owner_mind = brain_owner?.mind + if(!isnull(owner_mind)) + update_ringtone(owner_mind?.assigned_role?.job_tone) + UpdateDisplay() + if(!isnull(client)) + update_pda_prefs(client) -/obj/item/modular_computer/pda/synth/proc/post_initialize() - var/obj/item/organ/brain/synth/brain_loc = loc - var/mob/living/carbon/owner = brain_loc?.bodypart_owner?.owner - if(istype(owner)) - var/obj/item/modular_computer/pda/job_pda = SSjob.get_pda_type_by_job(owner.job) - if(istype(job_pda)) - starting_programs += job_pda.starting_programs - var/obj/item/modular_computer/pda/heads/head_pda = job_pda - if(istype(head_pda)) - starting_programs += head_pda.head_programs - install_default_programs() - QDEL_NULL(job_pda) +/obj/item/modular_computer/pda/synth/check_power_override() + return TRUE -/* Action for opening the synthbrain computer */ /datum/action/item_action/synth/open_internal_computer name = "Open persocom emulation" desc = "Accesses your built-in virtual machine." @@ -46,18 +44,26 @@ /datum/action/item_action/synth/open_internal_computer/Trigger(trigger_flags) . = ..() - var/obj/item/organ/brain/synth/targetmachine = target - targetmachine.internal_computer.interact(owner) + if(!.) + return + var/obj/item/organ/brain/synth/synth_brain = target + if(istype(synth_brain)) + synth_brain.internal_computer.interact(owner) + return + var/obj/item/organ/brain/cybernetic/cortical/cort_brain = target + if(istype(cort_brain)) + cort_brain.internal_computer.interact(owner) + return + var/obj/item/organ/brain/cybernetic/surplus/surp_brain = target + if(istype(surp_brain)) + surp_brain.internal_computer.interact(owner) -/* -Various overrides necessary to get the persocom working, namely ui status, power, and ID handling -*/ /obj/item/modular_computer/pda/synth/ui_state(mob/user) return GLOB.default_state /obj/item/modular_computer/pda/synth/ui_status(mob/user) - var/obj/item/organ/brain/synth/brain_loc = loc - if(!istype(brain_loc)) + var/obj/item/organ/brain/brain_loc = loc + if(!(istype(brain_loc, /obj/item/organ/brain/synth) || istype(brain_loc, /obj/item/organ/brain/cybernetic/cortical) || istype(brain_loc, /obj/item/organ/brain/cybernetic/surplus))) return UI_CLOSE if(!QDELETED(brain_loc.owner)) @@ -68,37 +74,110 @@ Various overrides necessary to get the persocom working, namely ui status, power ) return ..() -// Needed to tell the power check that we're handling power ourselves -/obj/item/modular_computer/pda/synth/check_power_override(amount) - return TRUE +/// Id card arg is optional. Leaving it null causes the id to become unpaired from the synth computer +/obj/item/modular_computer/pda/synth/proc/update_id_slot(obj/item/card/id/id_card) + var/obj/item/organ/brain/brain_loc = loc + if(!(istype(brain_loc, /obj/item/organ/brain/synth) || istype(brain_loc, /obj/item/organ/brain/cybernetic/cortical) || istype(brain_loc, /obj/item/organ/brain/cybernetic/surplus))) + return + if(istype(brain_loc, /obj/item/organ/brain/synth)) + var/obj/item/organ/brain/synth/synth_brain = brain_loc + if(isnull(synth_brain.internal_computer)) + return + synth_brain.internal_computer.handle_id_slot(synth_brain.owner, id_card) + return + var/obj/item/organ/brain/cybernetic/cortical/cortical_brain = brain_loc + if(isnull(cortical_brain.internal_computer)) + return + cortical_brain.internal_computer.handle_id_slot(cortical_brain.owner, id_card) + var/obj/item/organ/brain/cybernetic/surplus/surplus_brain = brain_loc + if(isnull(surplus_brain.internal_computer)) + return + surplus_brain.internal_computer.handle_id_slot(surplus_brain.owner, id_card) -// Handles the id slot reading our id -/obj/item/modular_computer/pda/synth/proc/handle_id_slot(mob/living/carbon/human/synth) + +/// Called when id slot item is unequipped from the id slot +/obj/item/modular_computer/pda/synth/proc/on_id_item_unequipped(datum/source) + SIGNAL_HANDLER + clear_id_slot_signals(source) + update_id_slot() + +/// Called when id slot item's contained id is moved out of the id slot item +/obj/item/modular_computer/pda/synth/proc/on_id_item_moved(datum/source) + SIGNAL_HANDLER + clear_id_slot_signals(source) + update_id_slot() + +/// Called when something is inserted into an id slot wallet or pda +/obj/item/modular_computer/pda/synth/proc/on_id_item_stored(datum/source, obj/item/card/id/to_insert) + SIGNAL_HANDLER + if(!istype(to_insert)) + return + + UnregisterSignal(source, COMSIG_STORAGE_STORED_ITEM) + update_id_slot(to_insert) + +/obj/item/modular_computer/pda/synth/proc/clear_id_slot_signals(obj/item/id_slot_item) + if(!istype(id_slot_item)) + return + + UnregisterSignal(id_slot_item, list( + COMSIG_ITEM_POST_UNEQUIP, + COMSIG_MOVABLE_MOVED, + COMSIG_ITEM_UNSTORED, + COMSIG_STORAGE_STORED_ITEM, + COMSIG_MODULAR_COMPUTER_INSERTED_ID, + )) + + // make sure we clear all the signals on the contained id too + var/obj/item/card/id/contained_id_item + if(istype(id_slot_item, /obj/item/modular_computer/pda)) + var/obj/item/modular_computer/pda/id_slot_pda = id_slot_item + contained_id_item = id_slot_pda.stored_id + else if(istype(id_slot_item, /obj/item/storage/wallet)) + var/obj/item/storage/wallet/id_slot_wallet = id_slot_item + contained_id_item = id_slot_wallet.GetID() + + if(contained_id_item) + UnregisterSignal(contained_id_item, list(COMSIG_MOVABLE_MOVED, COMSIG_ITEM_UNSTORED)) + +/obj/item/modular_computer/pda/synth/proc/handle_id_slot(mob/living/carbon/human/synth, obj/item/id_item) if(!istype(synth)) return - var/obj/item = synth.wear_id - if(item) - if(istype(item, /obj/item/card/id)) - stored_id = item - else if(istype(item, /obj/item/modular_computer)) - var/obj/item/modular_computer/pda = item - stored_id = pda.stored_id - else if(istype(item, /obj/item/storage/wallet)) - var/obj/item/storage/wallet/wallet = item - stored_id = wallet.front_id - else - stored_id = null + if(isnull(id_item)) + if(stored_id) + to_chat(synth, span_notice("Persocom RFID link disconnected.")) + stored_id = null + return + if(istype(id_item, /obj/item/card/id)) + stored_id = id_item + to_chat(synth, span_notice("Persocom establishing new RFID link with [id_item].")) + RegisterSignal(id_item, COMSIG_ITEM_POST_UNEQUIP, PROC_REF(on_id_item_unequipped)) + else if(istype(id_item, /obj/item/modular_computer)) + var/obj/item/modular_computer/pda = id_item + stored_id = pda.stored_id + to_chat(synth, span_notice("Persocom establishing new RFID link with [pda].")) + RegisterSignal(pda, COMSIG_ITEM_POST_UNEQUIP, PROC_REF(on_id_item_unequipped)) + RegisterSignal(pda, COMSIG_MODULAR_COMPUTER_INSERTED_ID, PROC_REF(on_id_item_stored)) + RegisterSignal(pda.stored_id, COMSIG_MOVABLE_MOVED, PROC_REF(on_id_item_moved)) + else if(istype(id_item, /obj/item/storage/wallet)) + var/obj/item/storage/wallet/your_wallet = id_item + stored_id = your_wallet.GetID() + to_chat(synth, span_notice("Persocom establishing new RFID link with [your_wallet].")) + RegisterSignal(your_wallet, COMSIG_ITEM_POST_UNEQUIP, PROC_REF(on_id_item_unequipped)) + RegisterSignal(your_wallet, COMSIG_STORAGE_STORED_ITEM, PROC_REF(on_id_item_stored)) + RegisterSignal(your_wallet.GetID(), COMSIG_ITEM_UNSTORED, PROC_REF(on_id_item_moved)) + else stored_id = null -/* /obj/item/modular_computer/pda/synth/RemoveID(mob/user, silent = TRUE) - return */ // Fix this if we need it. +/obj/item/modular_computer/pda/synth/remove_id(mob/user, silent = FALSE) + return /obj/item/modular_computer/pda/synth/get_ntnet_status() . = ..() - if(is_centcom_level(loc.z)) // Centcom is excluded because cafe would allow people to abuse these - . = NTNET_NO_SIGNAL - return . + if(is_centcom_level(loc.z)) // Centcom is excluded because cafe + return NTNET_NO_SIGNAL + /obj/item/modular_computer/pda/attack(mob/living/target_mob, mob/living/user, params) var/mob/living/carbon/human/targetmachine = target_mob @@ -110,18 +189,40 @@ Various overrides necessary to get the persocom working, namely ui status, power if(user.zone_selected == BODY_ZONE_PRECISE_EYES) balloon_alert(user, "establishing SSH login with persocom...") if(do_after(user, 5 SECONDS)) - balloon_alert(user, "connection established!") + balloon_alert(user, "connection established") to_chat(targetmachine, span_notice("[user] establishes an SSH connection between [src] and your persocom emulation.")) robotbrain.internal_computer.interact(user) return + + // Also supports cortical augmented brains and surplus + var/obj/item/organ/brain/cybernetic/cortical/cortbrain = targetmachine.get_organ_slot(ORGAN_SLOT_BRAIN) + if(istype(cortbrain)) + if(user.zone_selected == BODY_ZONE_PRECISE_EYES) + balloon_alert(user, "establishing SSH login with persocom...") + if(do_after(user, 5 SECONDS)) + balloon_alert(user, "connection established") + to_chat(targetmachine, span_notice("[user] establishes an SSH connection between [src] and your persocom emulation.")) + cortbrain.internal_computer.interact(user) + return + + var/obj/item/organ/brain/cybernetic/surplus/surpbrain = targetmachine.get_organ_slot(ORGAN_SLOT_BRAIN) + if(istype(surpbrain)) + if(user.zone_selected == BODY_ZONE_PRECISE_EYES) + balloon_alert(user, "establishing SSH login with persocom...") + if(do_after(user, 5 SECONDS)) + balloon_alert(user, "connection established") + to_chat(targetmachine, span_notice("[user] establishes an SSH connection between [src] and your persocom emulation.")) + surpbrain.internal_computer.interact(user) + return return ..() + /obj/item/modular_computer/pda/synth/get_header_data() var/list/data = ..() - var/obj/item/organ/brain/synth/brain_loc = loc + var/obj/item/organ/brain/brain_loc = loc // Battery level is now according to the synth charge - if(istype(brain_loc)) - var/charge_level = (brain_loc.owner.nutrition / NUTRITION_LEVEL_ALMOST_FULL) * 100 + if(istype(brain_loc, /obj/item/organ/brain/synth) || istype(brain_loc, /obj/item/organ/brain/cybernetic/cortical) || istype(brain_loc, /obj/item/organ/brain/cybernetic/surplus)) + var/charge_level = (brain_loc.owner.nutrition / NUTRITION_LEVEL_FULL) * 100 switch(charge_level) if(80 to 110) data["PC_batteryicon"] = "batt_100.gif" diff --git a/tgstation.dme b/tgstation.dme index 7f129ce594f..08571afb412 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -562,6 +562,7 @@ #include "code\__DEFINES\~~bubber_defines\transport.dm" #include "code\__DEFINES\~~bubber_defines\vehicles.dm" #include "code\__DEFINES\~~bubber_defines\vomit.dm" +#include "code\__DEFINES\~~bubber_defines\_globalvars\lists\invalid_uplink_item.dm" #include "code\__DEFINES\~~bubber_defines\atmospherics\atmos_mob_interaction.dm" #include "code\__DEFINES\~~bubber_defines\research\techweb_nodes.dm" #include "code\__DEFINES\~~bubber_defines\traits\declarations.dm"