diff --git a/code/__DEFINES/assert.dm b/code/__DEFINES/assert.dm new file mode 100644 index 0000000000..cff7810771 --- /dev/null +++ b/code/__DEFINES/assert.dm @@ -0,0 +1,13 @@ +#undef ASSERT + +/// Override BYOND's native ASSERT to optionally specify a message +#define ASSERT(condition, message...) \ + if (!(condition)) { \ + CRASH(assertion_message(__FILE__, __LINE__, #condition, ##message)) \ + } + +/proc/assertion_message(file, line, condition, message) + if (!isnull(message)) + message = " - [message]" + + return "[file]:[line]:Assertion failed: [condition][message]" diff --git a/code/__DEFINES/conflict.dm b/code/__DEFINES/conflict.dm index 0820c709cd..d69f0891ff 100644 --- a/code/__DEFINES/conflict.dm +++ b/code/__DEFINES/conflict.dm @@ -109,6 +109,7 @@ #define SHOES_SLOWDOWN -1 #define SLOWDOWN_ARMOR_NONE 0 +#define SLOWDOWN_ARMOR_SUPER_LIGHT 0.10 #define SLOWDOWN_ARMOR_VERY_LIGHT 0.20 #define SLOWDOWN_ARMOR_LIGHT 0.35 #define SLOWDOWN_ARMOR_MEDIUM 0.55 diff --git a/code/__DEFINES/dcs/signals/atom/mob/signals_mob.dm b/code/__DEFINES/dcs/signals/atom/mob/signals_mob.dm index b9e89bf441..529b2e9314 100644 --- a/code/__DEFINES/dcs/signals/atom/mob/signals_mob.dm +++ b/code/__DEFINES/dcs/signals/atom/mob/signals_mob.dm @@ -1,3 +1,5 @@ +///from base of mob/set_stat(): (new_stat, old_stat) +#define COMSIG_MOB_STATCHANGE "mob_statchange" /// From /obj/structure/machinery/door/airlock/proc/take_damage #define COMSIG_MOB_DESTROY_AIRLOCK "mob_destroy_airlock" @@ -132,3 +134,6 @@ /// From /mob/proc/say_dead(message) #define COMSIG_DEAD_SPEAK "comsig_dead_speak" #define COMPONENT_OVERRIDE_DEAD_SPEAK (1<<0) + +/// Cancels all running cloaking effects on target +#define COMSIG_MOB_EFFECT_CLOAK_CANCEL "mob_effect_cloak_cancel" diff --git a/code/__DEFINES/dcs/signals/atom/signals_atom.dm b/code/__DEFINES/dcs/signals/atom/signals_atom.dm index 17915824a0..394e63bd6e 100644 --- a/code/__DEFINES/dcs/signals/atom/signals_atom.dm +++ b/code/__DEFINES/dcs/signals/atom/signals_atom.dm @@ -71,3 +71,6 @@ /// Called when an atom is mouse dropped on another atom, from /client/MouseDrop: (atom/dropped_onto) #define COMSIG_ATOM_DROP_ON "atom_drop_on" + +/// Called when an atom has emp_act called on it, from /atom/emp_act: (severity) +#define COMSIG_ATOM_EMP_ACT "atom_emp_act" diff --git a/code/__DEFINES/dcs/signals/atom/signals_cell.dm b/code/__DEFINES/dcs/signals/atom/signals_cell.dm new file mode 100644 index 0000000000..75e13d8bfd --- /dev/null +++ b/code/__DEFINES/dcs/signals/atom/signals_cell.dm @@ -0,0 +1,26 @@ +/// (charge_amount) +#define COMSIG_CELL_USE_CHARGE "cell_use_charge" + #define COMPONENT_CELL_NO_USE_CHARGE (1<<0) + +/// (charge_amount) +#define COMSIG_CELL_ADD_CHARGE "cell_add_charge" + +#define COMSIG_CELL_START_TICK_DRAIN "cell_start_tick_drain" + +#define COMSIG_CELL_STOP_TICK_DRAIN "cell_stop_tick_drain" + +/// (mob/living/user) +#define COMSIG_CELL_TRY_RECHARGING "cell_try_recharging" + #define COMPONENT_CELL_NO_RECHARGE (1<<0) + +#define COMSIG_CELL_OUT_OF_CHARGE "cell_out_of_charge" + +/// (charge_amount) +#define COMSIG_CELL_CHECK_CHARGE "cell_check_charge" + #define COMPONENT_CELL_CHARGE_INSUFFICIENT (1<<0) + +#define COMSIG_CELL_TRY_INSERT_CELL "cell_try_insert_cell" + #define COMPONENT_CANCEL_CELL_INSERT (1<<0) + +/// (mob/living/user) +#define COMSIG_CELL_REMOVE_CELL "cell_remove_cell" diff --git a/code/__DEFINES/dcs/signals/atom/signals_obj.dm b/code/__DEFINES/dcs/signals/atom/signals_obj.dm index 7e4436b3cf..90aa4bd984 100644 --- a/code/__DEFINES/dcs/signals/atom/signals_obj.dm +++ b/code/__DEFINES/dcs/signals/atom/signals_obj.dm @@ -26,3 +26,5 @@ /// from /obj/proc/afterbuckle() #define COSMIG_OBJ_AFTER_BUCKLE "signal_obj_after_buckle" + +#define COMSIG_STRUCTURE_CRATE_SQUAD_LAUNCHED "structure_crate_squad_launched" diff --git a/code/__DEFINES/job.dm b/code/__DEFINES/job.dm index 949f9385e8..e51c6f08ad 100644 --- a/code/__DEFINES/job.dm +++ b/code/__DEFINES/job.dm @@ -11,6 +11,7 @@ #define SQUAD_MARINE_CRYO "Foxtrot" #define SQUAD_MARINE_INTEL "Intel" #define SQUAD_SOF "SOF" +#define SQUAD_CBRN "CBRN" // Job name defines #define JOB_SQUAD_MARINE "Rifleman" diff --git a/code/__DEFINES/keybinding.dm b/code/__DEFINES/keybinding.dm index 5a0809d83a..764282d597 100644 --- a/code/__DEFINES/keybinding.dm +++ b/code/__DEFINES/keybinding.dm @@ -14,6 +14,7 @@ #define COMSIG_KB_ADMIN_INVISIMINTOGGLE_DOWN "keybinding_admin_invisimintoggle_down" #define COMSIG_KB_ADMIN_DEADMIN_DOWN "keybinding_admin_deadmin_down" #define COMSIG_KB_ADMIN_READMIN_DOWN "keybinding_admin_readmin_down" +#define COMSIG_KB_ADMIN_MENTORSAY_DOWN "keybinding_admin_mentorsay_down" //Carbon #define COMSIG_KB_CARBON_HOLDRUNMOVEINTENT_DOWN "keybinding_carbon_holdrunmoveintent_down" diff --git a/code/__DEFINES/speech_channels.dm b/code/__DEFINES/speech_channels.dm index 3f6e4720bd..5a9a74af8a 100644 --- a/code/__DEFINES/speech_channels.dm +++ b/code/__DEFINES/speech_channels.dm @@ -1,6 +1,7 @@ // Used to direct channels to speak into. #define SAY_CHANNEL "Say" #define COMMS_CHANNEL "Comms" +#define WHISPER_CHANNEL "Whisper" #define ME_CHANNEL "Me" #define OOC_CHANNEL "OOC" #define LOOC_CHANNEL "LOOC" diff --git a/code/__DEFINES/traits.dm b/code/__DEFINES/traits.dm index ef500b6af9..b2704fc668 100644 --- a/code/__DEFINES/traits.dm +++ b/code/__DEFINES/traits.dm @@ -1,63 +1,76 @@ -//shamelessly ripped from TG #define SIGNAL_ADDTRAIT(trait_ref) "addtrait [trait_ref]" #define SIGNAL_REMOVETRAIT(trait_ref) "removetrait [trait_ref]" // trait accessor defines -//here be dragons #define ADD_TRAIT(target, trait, source) \ do { \ var/list/_L; \ - if (!target.status_traits) { \ - target.status_traits = list(); \ - _L = target.status_traits; \ + if (!target._status_traits) { \ + target._status_traits = list(); \ + _L = target._status_traits; \ _L[trait] = list(source); \ SEND_SIGNAL(target, SIGNAL_ADDTRAIT(trait), trait); \ - if(trait in GLOB.traits_with_elements){ \ - target.AddElement(GLOB.traits_with_elements[trait]); \ - } \ } else { \ - _L = target.status_traits; \ + _L = target._status_traits; \ if (_L[trait]) { \ _L[trait] |= list(source); \ } else { \ _L[trait] = list(source); \ SEND_SIGNAL(target, SIGNAL_ADDTRAIT(trait), trait); \ - if(trait in GLOB.traits_with_elements){ \ - target.AddElement(GLOB.traits_with_elements[trait]); \ - } \ } \ } \ } while (0) #define REMOVE_TRAIT(target, trait, sources) \ do { \ - var/list/_L = target.status_traits; \ + var/list/_L = target._status_traits; \ var/list/_S; \ if (sources && !islist(sources)) { \ _S = list(sources); \ } else { \ _S = sources\ }; \ - if (_L && _L[trait]) { \ + if (_L?[trait]) { \ for (var/_T in _L[trait]) { \ - if ((!_S && (_T != TRAIT_SOURCE_QUIRK)) || (_T in _S)) { \ + if ((!_S && (_T != ROUNDSTART_TRAIT)) || (_T in _S)) { \ _L[trait] -= _T \ } \ };\ if (!length(_L[trait])) { \ _L -= trait; \ SEND_SIGNAL(target, SIGNAL_REMOVETRAIT(trait), trait); \ - if(trait in GLOB.traits_with_elements) { \ - target.RemoveElement(GLOB.traits_with_elements[trait]); \ - } \ }; \ if (!length(_L)) { \ - target.status_traits = null \ + target._status_traits = null \ + }; \ + } \ + } while (0) +#define REMOVE_TRAIT_NOT_FROM(target, trait, sources) \ + do { \ + var/list/_traits_list = target._status_traits; \ + var/list/_sources_list; \ + if (sources && !islist(sources)) { \ + _sources_list = list(sources); \ + } else { \ + _sources_list = sources\ + }; \ + if (_traits_list?[trait]) { \ + for (var/_trait_source in _traits_list[trait]) { \ + if (!(_trait_source in _sources_list)) { \ + _traits_list[trait] -= _trait_source \ + } \ + };\ + if (!length(_traits_list[trait])) { \ + _traits_list -= trait; \ + SEND_SIGNAL(target, SIGNAL_REMOVETRAIT(trait), trait); \ + }; \ + if (!length(_traits_list)) { \ + target._status_traits = null \ }; \ } \ } while (0) #define REMOVE_TRAITS_NOT_IN(target, sources) \ do { \ - var/list/_L = target.status_traits; \ + var/list/_L = target._status_traits; \ var/list/_S = sources; \ if (_L) { \ for (var/_T in _L) { \ @@ -65,20 +78,17 @@ if (!length(_L[_T])) { \ _L -= _T; \ SEND_SIGNAL(target, SIGNAL_REMOVETRAIT(_T), _T); \ - if(_T in GLOB.traits_with_elements) { \ - target.RemoveElement(GLOB.traits_with_elements[_T]); \ }; \ };\ - };\ if (!length(_L)) { \ - target.status_traits = null\ + target._status_traits = null\ };\ }\ } while (0) #define REMOVE_TRAITS_IN(target, sources) \ do { \ - var/list/_L = target.status_traits; \ + var/list/_L = target._status_traits; \ var/list/_S = sources; \ if (sources && !islist(sources)) { \ _S = list(sources); \ @@ -91,46 +101,36 @@ if (!length(_L[_T])) { \ _L -= _T; \ SEND_SIGNAL(target, SIGNAL_REMOVETRAIT(_T)); \ - if(_T in GLOB.traits_with_elements) { \ - target.RemoveElement(GLOB.traits_with_elements[_T]); \ }; \ };\ - };\ if (!length(_L)) { \ - target.status_traits = null\ + target._status_traits = null\ };\ }\ } while (0) -/// Will 100% nuke a trait regardless of source. Preferably use this as little as possible -#define REMOVE_TRAIT_ALLSOURCES(target, trait) \ - do { \ - var/list/_L = target.status_traits; \ - if (_L?[trait]) { \ - if (length(_L)) { \ - _L -= trait; \ - SEND_SIGNAL(target, SIGNAL_REMOVETRAIT(trait), trait); \ - }; \ - else { \ - target.status_traits = null \ - }; \ - } \ - } while (0) - -#define HAS_TRAIT(target, trait) (target.status_traits ? (target.status_traits[trait] ? TRUE : FALSE) : FALSE) -#define HAS_TRAIT_FROM(target, trait, source) (target.status_traits ? (target.status_traits[trait] ? (source in target.status_traits[trait]) : FALSE) : FALSE) -#define HAS_TRAIT_FROM_ONLY(target, trait, source) (\ - target.status_traits ?\ - (target.status_traits[trait] ?\ - ((source in target.status_traits[trait]) && (length(target.status_traits) == 1))\ - : FALSE)\ - : FALSE) -#define HAS_TRAIT_NOT_FROM(target, trait, source) (target.status_traits ? (target.status_traits[trait] ? (length(target.status_traits[trait] - source) > 0) : FALSE) : FALSE) - +#define HAS_TRAIT(target, trait) (target._status_traits?[trait] ? TRUE : FALSE) +#define HAS_TRAIT_FROM(target, trait, source) (HAS_TRAIT(target, trait) && (source in target._status_traits[trait])) +#define HAS_TRAIT_FROM_ONLY(target, trait, source) (HAS_TRAIT(target, trait) && (source in target._status_traits[trait]) && (length(target._status_traits[trait]) == 1)) +#define HAS_TRAIT_NOT_FROM(target, trait, source) (HAS_TRAIT(target, trait) && (length(target._status_traits[trait] - source) > 0)) +/// Returns a list of trait sources for this trait. Only useful for wacko cases and internal futzing +/// You should not be using this +#define GET_TRAIT_SOURCES(target, trait) (target._status_traits?[trait] || list()) +/// Returns the amount of sources for a trait. useful if you don't want to have a "thing counter" stuck around all the time +#define COUNT_TRAIT_SOURCES(target, trait) length(GET_TRAIT_SOURCES(target, trait)) +/// A simple helper for checking traits in a mob's mind +#define HAS_MIND_TRAIT(target, trait) (HAS_TRAIT(target, trait) || (target.mind ? HAS_TRAIT(target.mind, trait) : FALSE)) /// Example trait // #define TRAIT_X "t_x" + +/// cannot be removed without admin intervention +#define ROUNDSTART_TRAIT "roundstart" + //-- mob traits -- +/// Apply this to make a mob not dense, and remove it when you want it to no longer make them undense, other sorces of undesity will still apply. Always define a unique source when adding a new instance of this! +#define TRAIT_UNDENSE "undense" + // SPECIES TRAITS /// Knowledge of Yautja technology #define TRAIT_YAUTJA_TECH "t_yautja_tech" @@ -279,6 +279,7 @@ GLOBAL_LIST_INIT(mob_traits, list( */ GLOBAL_LIST_INIT(traits_by_type, list( /mob = list( + "TRAIT_UNDENSE" = TRAIT_UNDENSE, "TRAIT_YAUTJA_TECH" = TRAIT_YAUTJA_TECH, "TRAIT_SUPER_STRONG" = TRAIT_SUPER_STRONG, "TRAIT_FOREIGN_BIO" = TRAIT_FOREIGN_BIO, @@ -355,6 +356,8 @@ GLOBAL_LIST(trait_name_map) // #define TRAIT_SOURCE_Y "t_s_y" #define TRAIT_SOURCE_INHERENT "t_s_inherent" //-- mob traits -- +///Status trait coming from lying down through update_canmove() +#define LYING_TRAIT "lying" ///Status trait coming from species. .human/species_gain() #define TRAIT_SOURCE_SPECIES "t_s_species" ///Status trait coming from the hive. @@ -379,6 +382,8 @@ GLOBAL_LIST(trait_name_map) #define TRAIT_SOURCE_ABILITY(ability) "t_s_ability_[ability]" ///Status trait forced by the xeno action charge #define TRAIT_SOURCE_XENO_ACTION_CHARGE "t_s_xeno_action_charge" +///Status trait coming from a xeno nest +#define XENO_NEST_TRAIT "xeno_nest" //-- structure traits -- ///Status trait coming from being flipped or unflipped. #define TRAIT_SOURCE_FLIP_TABLE "t_s_flip_table" @@ -390,3 +395,12 @@ GLOBAL_LIST(trait_name_map) //Status trait coming from clothing. #define TRAIT_SOURCE_CLOTHING "t_s_clothing" + +/// trait effect related to active specialist gear +#define SPECIALIST_GEAR_TRAIT "specialist_gear" +/// traits associated with usage of snowflake dropship double seats +#define DOUBLE_SEATS_TRAIT "double_seats" +/// traits associated with xeno on-ground weeds +#define XENO_WEED_TRAIT "xeno_weed" +/// traits from chloroform usage +#define CHLOROFORM_TRAIT "chloroform" diff --git a/code/__HELPERS/job.dm b/code/__HELPERS/job.dm index 43902b07cf..89fe687764 100644 --- a/code/__HELPERS/job.dm +++ b/code/__HELPERS/job.dm @@ -26,13 +26,6 @@ if(I.assignment in GLOB.joblist) return I.assignment return "Unknown" -/proc/FindNameFromID(mob/living/carbon/human/H) - ASSERT(istype(H)) - var/obj/item/card/id/I = H.wear_id - if(istype(I)) return I.registered_name - I = H.get_active_hand() - if(istype(I)) return I.registered_name - /proc/get_all_job_icons() return GLOB.joblist + list("Prisoner")//For all existing HUD icons /obj/proc/GetJobName() //Used in secHUD icon generation diff --git a/code/__HELPERS/traits.dm b/code/__HELPERS/traits.dm new file mode 100644 index 0000000000..ba99b2e1e7 --- /dev/null +++ b/code/__HELPERS/traits.dm @@ -0,0 +1,43 @@ +#define TRAIT_CALLBACK_ADD(target, trait, source) CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(___TraitAdd), ##target, ##trait, ##source) +#define TRAIT_CALLBACK_REMOVE(target, trait, source) CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(___TraitRemove), ##target, ##trait, ##source) + +///DO NOT USE ___TraitAdd OR ___TraitRemove as a replacement for ADD_TRAIT / REMOVE_TRAIT defines. To be used explicitly for callback. +/proc/___TraitAdd(target,trait,source) + if(!target || !trait || !source) + return + if(islist(target)) + for(var/i in target) + if(!isatom(i)) + continue + var/atom/the_atom = i + ADD_TRAIT(the_atom,trait,source) + else if(isatom(target)) + var/atom/the_atom2 = target + ADD_TRAIT(the_atom2,trait,source) + +///DO NOT USE ___TraitAdd OR ___TraitRemove as a replacement for ADD_TRAIT / REMOVE_TRAIT defines. To be used explicitly for callback. +/proc/___TraitRemove(target,trait,source) + if(!target || !trait || !source) + return + if(islist(target)) + for(var/i in target) + if(!isatom(i)) + continue + var/atom/the_atom = i + REMOVE_TRAIT(the_atom,trait,source) + else if(isatom(target)) + var/atom/the_atom2 = target + REMOVE_TRAIT(the_atom2,trait,source) + + +/// Proc that handles adding multiple traits to a target via a list. Must have a common source and target. +/datum/proc/add_traits(list/list_of_traits, source) + ASSERT(islist(list_of_traits), "Invalid arguments passed to add_traits! Invoked on [src] with [list_of_traits], source being [source].") + for(var/trait in list_of_traits) + ADD_TRAIT(src, trait, source) + +/// Proc that handles removing multiple traits from a target via a list. Must have a common source and target. +/datum/proc/remove_traits(list/list_of_traits, source) + ASSERT(islist(list_of_traits), "Invalid arguments passed to remove_traits! Invoked on [src] with [list_of_traits], source being [source].") + for(var/trait in list_of_traits) + REMOVE_TRAIT(src, trait, source) diff --git a/code/controllers/subsystem/communications.dm b/code/controllers/subsystem/communications.dm index d4144c9f0e..e214b29836 100644 --- a/code/controllers/subsystem/communications.dm +++ b/code/controllers/subsystem/communications.dm @@ -107,6 +107,7 @@ var/const/MAX_FREQ = 1468 // --------------------------------------------------- var/const/HC_FREQ = 1471 var/const/SOF_FREQ = 1472 var/const/PVST_FREQ = 1473 +var/const/CBRN_FREQ = 1474 //Ship department channels var/const/SENTRY_FREQ = 1480 @@ -162,6 +163,7 @@ var/list/radiochannels = list( SQUAD_MARINE_5 = ECHO_FREQ, SQUAD_MARINE_CRYO = CRYO_FREQ, SQUAD_SOF = SOF_FREQ, + SQUAD_CBRN = CBRN_FREQ, RADIO_CHANNEL_ALAMO = DS1_FREQ, RADIO_CHANNEL_NORMANDY = DS2_FREQ, @@ -262,6 +264,7 @@ SUBSYSTEM_DEF(radio) "[DELTA_FREQ]" = "deltaradio", "[ECHO_FREQ]" = "echoradio", "[CRYO_FREQ]" = "cryoradio", + "[CBRN_FREQ]" = "hcradio", "[SOF_FREQ]" = "hcradio", "[HC_FREQ]" = "hcradio", "[PVST_FREQ]" = "pvstradio", diff --git a/code/datums/agents/tools/chloroform.dm b/code/datums/agents/tools/chloroform.dm index 464533309b..cc804c1d27 100644 --- a/code/datums/agents/tools/chloroform.dm +++ b/code/datums/agents/tools/chloroform.dm @@ -48,7 +48,7 @@ /obj/item/weapon/chloroform/proc/grab_stun(mob/living/M, mob/living/user) M.anchored = TRUE M.frozen = TRUE - M.density = FALSE + ADD_TRAIT(M, TRAIT_UNDENSE, CHLOROFORM_TRAIT) M.able_to_speak = FALSE M.update_canmove() @@ -83,6 +83,7 @@ M.able_to_speak = TRUE M.layer = MOB_LAYER M.unfreeze() + REMOVE_TRAIT(M, TRAIT_UNDENSE, CHLOROFORM_TRAIT) QDEL_NULL(mask_item) diff --git a/code/datums/components/cell.dm b/code/datums/components/cell.dm new file mode 100644 index 0000000000..81ef3733e2 --- /dev/null +++ b/code/datums/components/cell.dm @@ -0,0 +1,202 @@ +#define UNLIMITED_CHARGE -1 +#define UNLIMITED_DISTANCE -1 + +/datum/component/cell + dupe_mode = COMPONENT_DUPE_UNIQUE + /// Maximum charge of the power cell, set to -1 for infinite charge + var/max_charge = 10000 + /// Initial max charge of the power cell + var/initial_max_charge + /// Current charge of power cell + var/charge = 10000 + /// If the component can be recharged by hitting its parent with a cell + var/hit_charge = FALSE + /// The maximum amount that can be recharged per tick when using a cell to recharge this component + var/max_recharge_tick = 400 + /// If draining charge on process(), how much to drain per process call + var/charge_drain = 10 + /// If the parent should show cell charge on examine + var/display_charge = TRUE + /// From how many tiles at the highest someone can examine the parent to see the charge + var/charge_examine_range = 1 + /// If the component requires a cell to be inserted to work instead of having an integrated one + var/cell_insert = FALSE + /// Ref to an inserted cell. Should only be null if cell_insert is false + var/obj/item/cell/inserted_cell + + +/datum/component/cell/Initialize( + max_charge = 10000, + hit_charge = FALSE, + max_recharge_tick = 400, + charge_drain = 10, + display_charge = TRUE, + charge_examine_range = 1, + cell_insert = FALSE, + ) + + . = ..() + if(!isatom(parent)) + return COMPONENT_INCOMPATIBLE + + src.max_charge = max_charge + charge = max_charge + src.hit_charge = hit_charge + src.max_recharge_tick = max_recharge_tick + src.charge_drain = charge_drain + src.display_charge = display_charge + src.charge_examine_range = charge_examine_range + src.cell_insert = cell_insert + +/datum/component/cell/Destroy(force, silent) + QDEL_NULL(inserted_cell) + return ..() + + +/datum/component/cell/RegisterWithParent() + ..() + RegisterSignal(parent, list(COMSIG_PARENT_ATTACKBY, COMSIG_ITEM_ATTACKED), PROC_REF(on_object_hit)) + RegisterSignal(parent, COMSIG_CELL_ADD_CHARGE, PROC_REF(add_charge)) + RegisterSignal(parent, COMSIG_CELL_USE_CHARGE, PROC_REF(use_charge)) + RegisterSignal(parent, COMSIG_CELL_CHECK_CHARGE, PROC_REF(has_charge)) + RegisterSignal(parent, COMSIG_CELL_START_TICK_DRAIN, PROC_REF(start_drain)) + RegisterSignal(parent, COMSIG_CELL_STOP_TICK_DRAIN, PROC_REF(stop_drain)) + RegisterSignal(parent, COMSIG_CELL_REMOVE_CELL, PROC_REF(remove_cell)) + RegisterSignal(parent, COMSIG_PARENT_EXAMINE, PROC_REF(on_examine)) + RegisterSignal(parent, COMSIG_ATOM_EMP_ACT, PROC_REF(on_emp)) + +/datum/component/cell/process() + use_charge(null, charge_drain) + +/datum/component/cell/proc/on_emp(datum/source, severity) + SIGNAL_HANDLER + + use_charge(null, round(max_charge / severity)) + +/datum/component/cell/proc/start_drain(datum/source) + SIGNAL_HANDLER + + START_PROCESSING(SSobj, src) + +/datum/component/cell/proc/stop_drain(datum/source) + SIGNAL_HANDLER + + STOP_PROCESSING(SSobj, src) + +/datum/component/cell/proc/on_examine(datum/source, mob/examiner, list/examine_text) + SIGNAL_HANDLER + + if(!display_charge) + return + + if((charge_examine_range != UNLIMITED_DISTANCE) && get_dist(examiner, parent) > charge_examine_range) + return + + examine_text += "A small gauge in the corner reads \"Power: [round(100 * charge / max_charge)]%\"." + +/datum/component/cell/proc/on_object_hit(datum/source, obj/item/cell/attack_obj, mob/living/attacker, params) + SIGNAL_HANDLER + + if(!hit_charge || !istype(attack_obj)) + return + + if(!cell_insert) + INVOKE_ASYNC(src, PROC_REF(charge_from_cell), attack_obj, attacker) + + else + insert_cell(attack_obj, attacker) + + return COMPONENT_NO_AFTERATTACK|COMPONENT_CANCEL_ITEM_ATTACK + +/datum/component/cell/proc/insert_cell(obj/item/cell/power_cell, mob/living/user) + if(inserted_cell) + to_chat(user, SPAN_WARNING("There's already a power cell in [parent]!")) + return + + if(SEND_SIGNAL(parent, COMSIG_CELL_TRY_INSERT_CELL) & COMPONENT_CANCEL_CELL_INSERT) + return + + power_cell.drop_to_floor(user) + power_cell.forceMove(parent) + inserted_cell = power_cell + charge = power_cell.charge + max_charge = power_cell.maxcharge + +/datum/component/cell/proc/remove_cell(mob/living/user) + SIGNAL_HANDLER + + user.put_in_hands(inserted_cell, TRUE) + to_chat(user, SPAN_NOTICE("You remove [inserted_cell] from [parent].")) + inserted_cell = null + max_charge = initial_max_charge + charge = 0 + +/datum/component/cell/proc/charge_from_cell(obj/item/cell/power_cell, mob/living/user) + if(max_charge == UNLIMITED_CHARGE) + to_chat(user, SPAN_WARNING("[parent] doesn't need more power.")) + return + + while(charge < max_charge) + if(SEND_SIGNAL(parent, COMSIG_CELL_TRY_RECHARGING, user) & COMPONENT_CELL_NO_RECHARGE) + return + + if(power_cell.charge <= 0) + to_chat(user, SPAN_WARNING("[power_cell] is completely dry.")) + return + + if(!do_after(user, 1 SECONDS, (INTERRUPT_ALL & (~INTERRUPT_MOVED)), BUSY_ICON_BUILD, power_cell, INTERRUPT_DIFF_LOC)) + to_chat(user, SPAN_WARNING("You were interrupted.")) + return + + if(power_cell.charge <= 0) + return + + var/to_transfer = min(max_recharge_tick, power_cell.charge, (max_charge - charge)) + if(power_cell.use(to_transfer)) + add_charge(null, to_transfer) + to_chat(user, "You transfer some power between [power_cell] and [parent]. The gauge now reads: [round(100 * charge / max_charge)]%.") + +/datum/component/cell/proc/add_charge(datum/source, charge_add = 0) + SIGNAL_HANDLER + + if(max_charge == UNLIMITED_CHARGE) + return + + if(!charge_add) + return + + charge = clamp(charge + charge_add, 0, max_charge) + +/datum/component/cell/proc/use_charge(datum/source, charge_use = 0) + SIGNAL_HANDLER + + if(max_charge == UNLIMITED_CHARGE) + return + + if(!charge_use) + return + + if(!charge) + return COMPONENT_CELL_NO_USE_CHARGE + + charge = clamp(charge - charge_use, 0, max_charge) + + if(!charge) + on_charge_empty() + return + +/datum/component/cell/proc/has_charge(datum/source, charge_amount = 0) + SIGNAL_HANDLER + + if(!charge) + return COMPONENT_CELL_CHARGE_INSUFFICIENT + + if(charge < charge_amount) + return COMPONENT_CELL_CHARGE_INSUFFICIENT + +/datum/component/cell/proc/on_charge_empty() + stop_drain() + SEND_SIGNAL(parent, COMSIG_CELL_OUT_OF_CHARGE) + +#undef UNLIMITED_CHARGE +#undef UNLIMITED_DISTANCE diff --git a/code/datums/components/crate_tag.dm b/code/datums/components/crate_tag.dm new file mode 100644 index 0000000000..379df82a20 --- /dev/null +++ b/code/datums/components/crate_tag.dm @@ -0,0 +1,36 @@ +/datum/component/crate_tag + dupe_mode = COMPONENT_DUPE_UNIQUE_PASSARGS + /// The crate tag used for notifications and as label + var/name + +/datum/component/crate_tag/Initialize(name, obj/structure/closet/crate/masquarade_type) + var/obj/structure/closet/crate/crate = parent + if(!istype(crate)) + return COMPONENT_INCOMPATIBLE + setup(name, masquarade_type) + RegisterSignal(parent, COMSIG_STRUCTURE_CRATE_SQUAD_LAUNCHED, PROC_REF(notify_squad)) + +/datum/component/crate_tag/InheritComponent(datum/component/C, i_am_original, name, obj/structure/closet/crate/masquarade_type) + . = ..() + setup(name, masquarade_type) + +/datum/component/crate_tag/proc/setup(name, obj/structure/closet/crate/masquarade_type) + var/obj/structure/closet/crate/crate = parent + if(masquarade_type) + crate.name = initial(masquarade_type.name) + crate.desc = initial(masquarade_type.desc) + crate.icon_opened = initial(masquarade_type.icon_opened) + crate.icon_closed = initial(masquarade_type.icon_closed) + if(crate.opened) + crate.icon_state = crate.icon_opened + else + crate.icon_state = crate.icon_closed + if(name) + parent.AddComponent(/datum/component/label, name) + src.name = name // Keep it around additionally for notifications + +/// Handler to notify an overwatched squad that this crate has been dropped for them +/datum/component/crate_tag/proc/notify_squad(datum/source, datum/squad/squad) + SIGNAL_HANDLER + squad.send_message("'[name]' supply drop incoming. Heads up!") + squad.send_maptext(name, "Incoming Supply Drop:") diff --git a/code/datums/components/weed_food.dm b/code/datums/components/weed_food.dm index ce6c17e0af..16be8665f5 100644 --- a/code/datums/components/weed_food.dm +++ b/code/datums/components/weed_food.dm @@ -259,7 +259,7 @@ active = FALSE merged = TRUE - parent_mob.density = FALSE + ADD_TRAIT(parent_mob, TRAIT_UNDENSE, XENO_WEED_TRAIT) parent_mob.anchored = TRUE parent_mob.mouse_opacity = MOUSE_OPACITY_TRANSPARENT parent_mob.plane = FLOOR_PLANE diff --git a/code/datums/datacore.dm b/code/datums/datacore.dm index 31e909b068..a2b060572b 100644 --- a/code/datums/datacore.dm +++ b/code/datums/datacore.dm @@ -145,6 +145,9 @@ GLOBAL_DATUM_INIT(data_core, /datum/datacore, new) continue dept_flags |= FLAG_SHOW_MARINES squad_sublists[squad_name] = TRUE + ///If it is a real squad in the USCM squad list to prevent the crew manifest from breaking + if(!(squad_name in ROLES_SQUAD_ALL)) + continue LAZYSET(marines_by_squad[squad_name][real_rank], name, rank) //here we fill manifest diff --git a/code/datums/datum.dm b/code/datums/datum.dm index b26c6afe4d..7d497785a7 100644 --- a/code/datums/datum.dm +++ b/code/datums/datum.dm @@ -19,8 +19,8 @@ /// Active timers with this datum as the target var/list/active_timers - /// Status traits attached. - var/list/status_traits + /// Status traits attached to this datum. associative list of the form: list(trait name (string) = list(source1, source2, source3,...)) + var/list/_status_traits /** * Components attached to this datum diff --git a/code/datums/diseases/black_goo.dm b/code/datums/diseases/black_goo.dm index 38a26f3648..d4d9b6f509 100644 --- a/code/datums/diseases/black_goo.dm +++ b/code/datums/diseases/black_goo.dm @@ -211,6 +211,15 @@ . = ..() reagents.add_reagent("antiZed", 30) +/obj/item/reagent_container/glass/bottle/labeled_black_goo_cure + name = "\"Pathogen\" cure bottle" + desc = "The bottle has a biohazard symbol on the front, and has a label, designating its use against Agent A0-3959X.91–15, colloquially known as the \"Black Goo\"." + icon_state = "bottle20" + +/obj/item/reagent_container/glass/bottle/labeled_black_goo_cure/Initialize() + . = ..() + reagents.add_reagent("antiZed", 60) + /datum/language/zombie name = "Zombie" desc = "A growling, guttural method of communication, only Zombies seem to be capable of producing these sounds." diff --git a/code/datums/emergency_calls/cbrn.dm b/code/datums/emergency_calls/cbrn.dm new file mode 100644 index 0000000000..3a6b1c6406 --- /dev/null +++ b/code/datums/emergency_calls/cbrn.dm @@ -0,0 +1,80 @@ +/datum/emergency_call/cbrn + name = "CBRN (Squad)" + arrival_message = "A CBRN squad has been dispatched to your ship. Stand by." + objectives = "Handle the chemical, biological, radiological, or nuclear threat. Further orders may be provided." + mob_min = 3 + mob_max = 5 + max_heavies = 0 + max_smartgunners = 0 + +/datum/emergency_call/cbrn/create_member(datum/mind/new_mind, turf/override_spawn_loc) + var/turf/spawn_loc = override_spawn_loc ? override_spawn_loc : get_spawn_point() + + if(!istype(spawn_loc)) + return //Didn't find a useable spawn point. + + var/mob/living/carbon/human/mob = new(spawn_loc) + new_mind.transfer_to(mob, TRUE) + + if(!leader && HAS_FLAG(mob.client.prefs.toggles_ert, PLAY_LEADER) && check_timelock(mob.client, JOB_SQUAD_LEADER, time_required_for_job)) + leader = mob + arm_equipment(mob, /datum/equipment_preset/uscm/cbrn/leader, TRUE, TRUE) + to_chat(mob, SPAN_ROLE_HEADER("You are the CBRN Fireteam Leader!")) + + else if(medics < max_medics && HAS_FLAG(mob.client.prefs.toggles_ert, PLAY_MEDIC) && check_timelock(mob.client, JOB_SQUAD_MEDIC, time_required_for_job)) + medics++ + arm_equipment(mob, /datum/equipment_preset/uscm/cbrn/medic, TRUE, TRUE) + to_chat(mob, SPAN_ROLE_HEADER("You are the CBRN Squad Medic!")) + + else if(engineers < max_engineers && HAS_FLAG(mob.client.prefs.toggles_ert, PLAY_ENGINEER) && check_timelock(mob.client, JOB_SQUAD_ENGI, time_required_for_job)) + engineers++ + arm_equipment(mob, /datum/equipment_preset/uscm/cbrn/engineer, TRUE, TRUE) + to_chat(mob, SPAN_ROLE_HEADER("You are the CBRN Squad Engineer!")) + + else + arm_equipment(mob, /datum/equipment_preset/uscm/cbrn/standard, TRUE, TRUE) + to_chat(mob, SPAN_ROLE_HEADER("You are a CBRN Squad Rifleman!")) + + to_chat(mob, SPAN_ROLE_BODY("You are a member of the USCM's CBRN. The CBRN is a force that specializes in handling chemical, biological, radiological, and nuclear threats.")) + addtimer(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(to_chat), mob, SPAN_BOLD("Objectives: [objectives]")), 1 SECONDS) + +/datum/emergency_call/cbrn/ert + name = "CBRN (Distress)" + arrival_message = "Your distress signal has been received and we are dispatching the nearest CBRN squad to board with you now. Stand by." + probability = 10 + +/datum/emergency_call/cbrn/ert/New() + ..() + objectives = "Investigate the distress signal aboard the [MAIN_SHIP_NAME]." + +/datum/emergency_call/cbrn/specialists + name = "CBRN (Specialists)" + mob_min = 2 + mob_max = 5 + max_engineers = 0 + max_medics = 0 + +/datum/emergency_call/cbrn/specialists/New() + var/cbrn_ship_name = "Unit [pick(nato_phonetic_alphabet)]-[rand(1, 99)]" + arrival_message = "[MAIN_SHIP_NAME], CBRN [cbrn_ship_name] has been dispatched. Follow all orders provided by [cbrn_ship_name]." + objectives = "You are a specialist team in [cbrn_ship_name] dispatched to quell a threat to [MAIN_SHIP_NAME]. Further orders may be provided." + +/datum/emergency_call/cbrn/specialists/create_member(datum/mind/new_mind, turf/override_spawn_loc) + var/turf/spawn_loc = override_spawn_loc ? override_spawn_loc : get_spawn_point() + + if(!istype(spawn_loc)) + return //Didn't find a useable spawn point. + + var/mob/living/carbon/human/mob = new(spawn_loc) + new_mind.transfer_to(mob, TRUE) + + if(!leader && HAS_FLAG(mob.client.prefs.toggles_ert, PLAY_LEADER) && check_timelock(mob.client, JOB_SQUAD_LEADER, time_required_for_job)) + leader = mob + arm_equipment(mob, /datum/equipment_preset/uscm/cbrn/specialist/lead, TRUE, TRUE) + to_chat(mob, SPAN_ROLE_HEADER("You are the CBRN Specialist Squad Leader!")) + else + arm_equipment(mob, /datum/equipment_preset/uscm/cbrn/specialist, TRUE, TRUE) + to_chat(mob, SPAN_ROLE_HEADER("You are a CBRN Specialist!")) + + to_chat(mob, SPAN_ROLE_BODY("You are a member of the USCM's CBRN. The CBRN is a force that specializes in handling chemical, biological, radiological, and nuclear threats.")) + addtimer(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(to_chat), mob, SPAN_BOLD("Objectives: [objectives]")), 1 SECONDS) diff --git a/code/datums/emergency_calls/emergency_call.dm b/code/datums/emergency_calls/emergency_call.dm index 4c3dfbbfac..9db46955a5 100644 --- a/code/datums/emergency_calls/emergency_call.dm +++ b/code/datums/emergency_calls/emergency_call.dm @@ -305,7 +305,7 @@ candidates = list() if(arrival_message && announce_incoming) - marine_announcement(arrival_message, "Intercepted Tranmission:") + marine_announcement(arrival_message, "Intercepted Transmission:") /datum/emergency_call/proc/add_candidate(mob/M) if(!M.client || (M.mind && (M.mind in candidates)) || istype(M, /mob/living/carbon/xenomorph)) diff --git a/code/datums/factions/uscm.dm b/code/datums/factions/uscm.dm index 0a989ab206..2197d674c4 100644 --- a/code/datums/factions/uscm.dm +++ b/code/datums/factions/uscm.dm @@ -190,6 +190,19 @@ if(JOB_CMB_OBS) marine_rk = "obs" icon_prefix = "cmb_" + // Check squad marines here too, for the unique ones + if(JOB_SQUAD_ENGI) + marine_rk = "engi" + if(JOB_SQUAD_MEDIC) + marine_rk = "med" + if(JOB_SQUAD_SPECIALIST) + marine_rk = "spec" + if(JOB_SQUAD_SMARTGUN) + marine_rk = "gun" + if(JOB_SQUAD_TEAM_LEADER) + marine_rk = "tl" + if(JOB_SQUAD_LEADER) + marine_rk = "leader" if(marine_rk) var/image/I = image('icons/mob/hud/marine_hud.dmi', current_human, "hudsquad") diff --git a/code/datums/keybinding/communication.dm b/code/datums/keybinding/communication.dm index 4164198d48..e1ba0ab5a3 100644 --- a/code/datums/keybinding/communication.dm +++ b/code/datums/keybinding/communication.dm @@ -32,7 +32,7 @@ /datum/keybinding/client/communication/whisper hotkey_keys = list("Unbound") classic_keys = list("Unbound") - name = "Whisper" + name = WHISPER_CHANNEL full_name = "IC Whisper" keybind_signal = COMSIG_KB_CLIENT_WHISPER_DOWN @@ -56,4 +56,4 @@ name = MENTOR_CHANNEL full_name = "Mentor Say" description = "Talk with other mentors." - keybind_signal = COMSIG_KB_ADMIN_ASAY_DOWN + keybind_signal = COMSIG_KB_ADMIN_MENTORSAY_DOWN diff --git a/code/game/atoms.dm b/code/game/atoms.dm index d1115eb533..4fe098f9fb 100644 --- a/code/game/atoms.dm +++ b/code/game/atoms.dm @@ -35,8 +35,11 @@ var/list/filter_data //For handling persistent filters - // Base transform matrix - var/matrix/base_transform = null + /// Base transform matrix, edited by admin tooling and such + var/matrix/base_transform + /// Last transform used before being compound with base_transform + /// This allows us to re-create transform if only base_transform changes + var/matrix/raw_transform ///Chemistry. var/datum/reagents/reagents = null @@ -118,7 +121,14 @@ directive is properly returned. //=========================================================================== - +// TODO make all atoms use set_density, do not rely on it at present +///Setter for the `density` variable to append behavior related to its changing. +/atom/proc/set_density(new_value) + SHOULD_CALL_PARENT(TRUE) + if(density == new_value) + return + . = density + density = new_value //atmos procs @@ -143,15 +153,27 @@ directive is properly returned. if(loc) return loc.return_gas() -// Updates the atom's transform -/atom/proc/apply_transform(matrix/M) - if(!base_transform) - transform = M - return +/// Updates the atom's transform compounding it with [/atom/var/base_transform] +/atom/proc/apply_transform(matrix/new_transform, time = 0, easing = (EASE_IN|EASE_OUT)) + var/matrix/base_copy + if(base_transform) + base_copy = matrix(base_transform) + else + base_copy = matrix() + raw_transform = matrix(new_transform) // Keep a copy to replay if needed - var/matrix/base_copy = matrix(base_transform) // Compose the base and applied transform in that order - transform = base_copy.Multiply(M) + var/matrix/complete = base_copy.Multiply(raw_transform) + + if(!time) + transform = complete + return + animate(src, transform = complete, time = time, easing = easing) + +/// Upates the base_transform which will be compounded with other transforms +/atom/proc/update_base_transform(matrix/new_transform, time = 0) + base_transform = matrix(new_transform) + apply_transform(raw_transform, time) /atom/proc/on_reagent_change() return @@ -185,7 +207,9 @@ directive is properly returned. return /atom/proc/emp_act(severity) - return + SHOULD_CALL_PARENT(TRUE) + + SEND_SIGNAL(src, COMSIG_ATOM_EMP_ACT, severity) /atom/proc/in_contents_of(container)//can take class or object instance as argument if(ispath(container)) @@ -225,8 +249,8 @@ directive is properly returned. if(!examine_strings) log_debug("Attempted to create an examine block with no strings! Atom : [src], user : [user]") return - to_chat(user, examine_block(examine_strings.Join("\n"))) SEND_SIGNAL(src, COMSIG_PARENT_EXAMINE, user, examine_strings) + to_chat(user, examine_block(examine_strings.Join("\n"))) /atom/proc/get_examine_text(mob/user) . = list() @@ -703,7 +727,6 @@ Parameters are passed from New. var/result = tgui_input_list(usr, "Choose the transformation to apply","Transform Mod", list("Scale","Translate","Rotate")) if(!result) return - var/matrix/M = transform if(!result) return switch(result) @@ -712,18 +735,21 @@ Parameters are passed from New. var/y = tgui_input_real_number(usr, "Choose y mod","Transform Mod") if(isnull(x) || isnull(y)) return - transform = M.Scale(x,y) + var/matrix/base_matrix = matrix(base_transform) + update_base_transform(base_matrix.Scale(x,y)) if("Translate") var/x = tgui_input_real_number(usr, "Choose x mod (negative = left, positive = right)","Transform Mod") var/y = tgui_input_real_number(usr, "Choose y mod (negative = down, positive = up)","Transform Mod") if(isnull(x) || isnull(y)) return - transform = M.Translate(x,y) + var/matrix/base_matrix = matrix(base_transform) + update_base_transform(base_matrix.Translate(x,y)) if("Rotate") var/angle = tgui_input_real_number(usr, "Choose angle to rotate","Transform Mod") if(isnull(angle)) return - transform = M.Turn(angle) + var/matrix/base_matrix = matrix(base_transform) + update_base_transform(base_matrix.Turn(angle)) SEND_SIGNAL(src, COMSIG_ATOM_VV_MODIFY_TRANSFORM) diff --git a/code/game/jobs/job/marine/squads.dm b/code/game/jobs/job/marine/squads.dm index 55be638e69..b50d5a2ae0 100644 --- a/code/game/jobs/job/marine/squads.dm +++ b/code/game/jobs/job/marine/squads.dm @@ -210,6 +210,17 @@ roundstart = FALSE locked = TRUE +/datum/squad/marine/cbrn + name = SQUAD_CBRN + equipment_color = "#3B2A7B" //Chemical Corps Purple + chat_color = "#553EB2" + radio_freq = CBRN_FREQ + minimap_color = "#3B2A7B" + + active = FALSE + roundstart = FALSE + locked = TRUE + //############################### UPP Squads /datum/squad/upp name = "Root" diff --git a/code/game/jobs/role_authority.dm b/code/game/jobs/role_authority.dm index 5aab13f68a..1e2e2ac6ed 100644 --- a/code/game/jobs/role_authority.dm +++ b/code/game/jobs/role_authority.dm @@ -524,9 +524,7 @@ I hope it's easier to tell what the heck this proc is even doing, unlike previou new_human.sec_hud_set_ID() new_human.hud_set_squad() - for(var/obj/current_item in new_human.get_contents()) - SEND_SIGNAL(current_item, COMSIG_POST_SPAWN_UPDATE, new_human) - + SEND_SIGNAL(new_human, COMSIG_POST_SPAWN_UPDATE) SSround_recording.recorder.track_player(new_human) //Find which squad has the least population. If all 4 squads are equal it should just use a random one diff --git a/code/game/machinery/atmoalter/scrubber.dm b/code/game/machinery/atmoalter/scrubber.dm index 0af38cacd7..1c240fb05d 100644 --- a/code/game/machinery/atmoalter/scrubber.dm +++ b/code/game/machinery/atmoalter/scrubber.dm @@ -18,16 +18,14 @@ PF.flags_can_pass_all = PASS_OVER|PASS_AROUND|PASS_UNDER /obj/structure/machinery/portable_atmospherics/powered/scrubber/emp_act(severity) + . = ..() if(inoperable()) - ..(severity) return if(prob(50/severity)) on = !on update_icon() - ..(severity) - /obj/structure/machinery/portable_atmospherics/powered/scrubber/update_icon() src.overlays = 0 diff --git a/code/game/machinery/bots/bots.dm b/code/game/machinery/bots/bots.dm index 116753093f..912a607032 100644 --- a/code/game/machinery/bots/bots.dm +++ b/code/game/machinery/bots/bots.dm @@ -114,6 +114,7 @@ /obj/structure/machinery/bot/emp_act(severity) + . = ..() var/was_on = on stat |= EMPED new /obj/effect/overlay/temp/emp_sparks (loc) diff --git a/code/game/machinery/bots/mulebot.dm b/code/game/machinery/bots/mulebot.dm index d82591994e..b88f824956 100644 --- a/code/game/machinery/bots/mulebot.dm +++ b/code/game/machinery/bots/mulebot.dm @@ -916,11 +916,11 @@ post_signal_multiple(control_freq, kv) /obj/structure/machinery/bot/mulebot/emp_act(severity) + . = ..() if (cell) cell.emp_act(severity) if(load) load.emp_act(severity) - ..() /obj/structure/machinery/bot/mulebot/explode() diff --git a/code/game/machinery/camera/camera.dm b/code/game/machinery/camera/camera.dm index d416c561fc..3b2a91eea3 100644 --- a/code/game/machinery/camera/camera.dm +++ b/code/game/machinery/camera/camera.dm @@ -35,6 +35,9 @@ var/colony_camera_mapload = TRUE + /// If this camera should have innate EMP-proofing + var/emp_proof = FALSE + /obj/structure/machinery/camera/Initialize(mapload, ...) . = ..() WireColorToFlag = randomCameraWires() @@ -72,6 +75,7 @@ if(WEST) pixel_x = 27 /obj/structure/machinery/camera/emp_act(severity) + . = ..() if(!isEmpProof()) if(prob(100/severity)) icon_state = "[initial(icon_state)]emp" @@ -89,7 +93,6 @@ if(can_use()) cameranet.addCamera(src) kick_viewers() - ..() /obj/structure/machinery/camera/ex_act(severity) diff --git a/code/game/machinery/camera/presets.dm b/code/game/machinery/camera/presets.dm index b075808652..fc23282581 100644 --- a/code/game/machinery/camera/presets.dm +++ b/code/game/machinery/camera/presets.dm @@ -30,6 +30,7 @@ network = list(CAMERA_NET_LASER_TARGETS) unslashable = TRUE unacidable = TRUE + emp_proof = TRUE /obj/structure/machinery/camera/laser_cam/Initialize(mapload, laser_name) . = ..() @@ -37,8 +38,6 @@ var/area/A = get_area(src) c_tag = "[laser_name] ([A.name])" -/obj/structure/machinery/camera/laser_cam/emp_act(severity) - return //immune to EMPs, just in case /obj/structure/machinery/camera/laser_cam/ex_act() return @@ -132,9 +131,7 @@ invisibility = 101 //fuck you init() colony_camera_mapload = FALSE - -/obj/structure/machinery/camera/autoname/lz_camera/emp_act(severity) - return //immune to EMPs, just in case + emp_proof = TRUE /obj/structure/machinery/camera/autoname/lz_camera/ex_act() return @@ -144,7 +141,7 @@ /obj/structure/machinery/camera/proc/isEmpProof() var/O = locate(/obj/item/stack/sheet/mineral/osmium) in assembly.upgrades - return O + return O || emp_proof /obj/structure/machinery/camera/proc/isXRay() var/obj/item/stock_parts/scanning_module/O = locate(/obj/item/stock_parts/scanning_module) in assembly.upgrades diff --git a/code/game/machinery/cell_charger.dm b/code/game/machinery/cell_charger.dm index fcd8c65e93..eb7a501fa0 100644 --- a/code/game/machinery/cell_charger.dm +++ b/code/game/machinery/cell_charger.dm @@ -80,11 +80,11 @@ return /obj/structure/machinery/cell_charger/emp_act(severity) + . = ..() if(inoperable()) return if(charging) charging.emp_act(severity) - ..(severity) /obj/structure/machinery/cell_charger/process() diff --git a/code/game/machinery/computer/arcade.dm b/code/game/machinery/computer/arcade.dm index 8d35dd1b6a..1ac5a06738 100644 --- a/code/game/machinery/computer/arcade.dm +++ b/code/game/machinery/computer/arcade.dm @@ -165,8 +165,8 @@ return /obj/structure/machinery/computer/arcade/emp_act(severity) + . = ..() if(inoperable()) - ..(severity) return var/empprize = null var/num_of_prizes = 0 @@ -178,5 +178,3 @@ for(num_of_prizes; num_of_prizes > 0; num_of_prizes--) empprize = pickweight(prizes) new empprize(src.loc) - - ..(severity) diff --git a/code/game/machinery/computer/camera_console.dm b/code/game/machinery/computer/camera_console.dm index b5cfc856b0..b78f306162 100644 --- a/code/game/machinery/computer/camera_console.dm +++ b/code/game/machinery/computer/camera_console.dm @@ -354,8 +354,8 @@ exproof = TRUE colony_camera_mapload = FALSE -/obj/structure/machinery/computer/cameras/mortar/emp_act(severity) - return FALSE +/obj/structure/machinery/computer/cameras/mortar/set_broken() + return /obj/structure/machinery/computer/cameras/dropship name = "abstract dropship camera computer" diff --git a/code/game/machinery/computer/computer.dm b/code/game/machinery/computer/computer.dm index 304b24a14f..c335177962 100644 --- a/code/game/machinery/computer/computer.dm +++ b/code/game/machinery/computer/computer.dm @@ -31,8 +31,9 @@ return 1 /obj/structure/machinery/computer/emp_act(severity) - if(prob(20/severity)) set_broken() - ..() + . = ..() + if(prob(20/severity)) + set_broken() /obj/structure/machinery/computer/ex_act(severity) diff --git a/code/game/machinery/computer/medical.dm b/code/game/machinery/computer/medical.dm index fe85599018..53efad3da8 100644 --- a/code/game/machinery/computer/medical.dm +++ b/code/game/machinery/computer/medical.dm @@ -483,8 +483,8 @@ return /obj/structure/machinery/computer/med_data/emp_act(severity) + . = ..() if(inoperable()) - ..(severity) return for(var/datum/data/record/R as anything in GLOB.data_core.medical) @@ -509,8 +509,6 @@ qdel(R) continue - ..(severity) - /obj/structure/machinery/computer/med_data/laptop name = "Medical Laptop" diff --git a/code/game/machinery/computer/security.dm b/code/game/machinery/computer/security.dm index 8571189379..2d9a4a1dbe 100644 --- a/code/game/machinery/computer/security.dm +++ b/code/game/machinery/computer/security.dm @@ -524,8 +524,8 @@ What a mess.*/ return selection.fields["img"] /obj/structure/machinery/computer/secure_data/emp_act(severity) + . = ..() if(inoperable()) - ..(severity) return for(var/datum/data/record/R in GLOB.data_core.security) @@ -550,8 +550,6 @@ What a mess.*/ qdel(R) continue - ..(severity) - /obj/structure/machinery/computer/secure_data/detective_computer icon = 'icons/obj/structures/machinery/computer.dmi' icon_state = "messyfiles" diff --git a/code/game/machinery/computer/skills.dm b/code/game/machinery/computer/skills.dm index a20d344b53..60b5aa2329 100644 --- a/code/game/machinery/computer/skills.dm +++ b/code/game/machinery/computer/skills.dm @@ -347,8 +347,8 @@ What a mess.*/ return /obj/structure/machinery/computer/skills/emp_act(severity) + . = ..() if(inoperable()) - ..(severity) return for(var/datum/data/record/R in GLOB.data_core.security) @@ -373,4 +373,3 @@ What a mess.*/ qdel(R) continue - ..(severity) diff --git a/code/game/machinery/deployable.dm b/code/game/machinery/deployable.dm index 99996bea89..687882d9d7 100644 --- a/code/game/machinery/deployable.dm +++ b/code/game/machinery/deployable.dm @@ -65,6 +65,7 @@ return /obj/structure/machinery/deployable/barrier/emp_act(severity) + . = ..() if(inoperable()) return if(prob(50/severity)) diff --git a/code/game/machinery/doors/airlock.dm b/code/game/machinery/doors/airlock.dm index b7257ff4e7..c6d9ddf3ef 100644 --- a/code/game/machinery/doors/airlock.dm +++ b/code/game/machinery/doors/airlock.dm @@ -866,3 +866,8 @@ GLOBAL_LIST_INIT(airlock_wire_descriptions, list( var/damage = xeno.melee_damage_upper * TAILSTAB_AIRLOCK_DAMAGE_MULTIPLIER take_damage(damage, xeno) return TAILSTAB_COOLDOWN_NORMAL + +/obj/structure/machinery/door/airlock/autoclose() + if(locked) + return + ..() diff --git a/code/game/machinery/doors/airlock_types.dm b/code/game/machinery/doors/airlock_types.dm index b13138cd7c..7796ad74df 100644 --- a/code/game/machinery/doors/airlock_types.dm +++ b/code/game/machinery/doors/airlock_types.dm @@ -138,7 +138,6 @@ opacity = 0 assembly_type = /obj/structure/airlock_assembly/airlock_assembly_research glass = 1 - heat_proof = 1 req_one_access = list(ACCESS_CIVILIAN_RESEARCH, ACCESS_CIVILIAN_COMMAND, ACCESS_WY_COLONIAL) /obj/structure/machinery/door/airlock/glass_mining/colony diff --git a/code/game/machinery/doors/door.dm b/code/game/machinery/doors/door.dm index a7d86d629b..99353a6688 100644 --- a/code/game/machinery/doors/door.dm +++ b/code/game/machinery/doors/door.dm @@ -1,4 +1,3 @@ - /obj/structure/machinery/door name = "\improper Door" desc = "It opens and closes." @@ -7,50 +6,43 @@ anchored = TRUE opacity = TRUE density = TRUE - throwpass = 0 + throwpass = FALSE layer = DOOR_OPEN_LAYER minimap_color = MINIMAP_DOOR var/open_layer = DOOR_OPEN_LAYER var/closed_layer = DOOR_CLOSED_LAYER var/id = "" + var/width = 1 var/secondsElectrified = 0 - var/visible = 1 + var/visible = TRUE var/panel_open = FALSE - var/operating = 0 - var/autoclose = 0 - var/glass = 0 - var/normalspeed = 1 - var/openspeed = 10 //How many seconds does it take to open it? Default 1 second. Use only if you have long door opening animations - var/heat_proof = 0 // For glass airlocks/opacity firedoors - var/air_properties_vary_with_direction = 0 - var/turf/filler //Fixes double door opacity issue + var/operating = FALSE + var/autoclose = FALSE + var/glass = FALSE + /// If FALSE it speeds up the autoclosing timing. + var/normalspeed = TRUE + /// Time to open/close airlock, default is 1 second. + var/openspeed = 1 SECONDS + /// Fixes multi_tile doors opacity issues. + var/list/filler_turfs = list() //Previously this was just var, because no one had forseen someone creating doors more than 2 tiles wide /// Stops it being forced open through normal means (Hunters/Zombies/Aliens). var/heavy = FALSE /// Resistance to masterkey var/masterkey_resist = FALSE var/masterkey_mod = 0.1 - - - //Multi-tile doors - dir = EAST - var/width = 1 + dir = EAST //So multitile doors are directioned properly /obj/structure/machinery/door/Initialize(mapload, ...) . = ..() - if(density) - layer = closed_layer - update_flags_heat_protection(get_turf(src)) - else - layer = open_layer - + layer = density ? closed_layer : open_layer handle_multidoor() /obj/structure/machinery/door/Destroy() . = ..() - if(filler && width > 1) - filler.set_opacity(0)// Ehh... let's hope there are no walls there. Must fix this - filler = null + if(length(filler_turfs) && width > 1) + change_filler_opacity(0) // It still doesn't check for walls, might want to add checking that in the future + filler_turfs = null density = FALSE /obj/structure/machinery/door/initialize_pass_flags(datum/pass_flags_container/PF) @@ -58,21 +50,41 @@ if (PF) PF.flags_can_pass_all = NONE +/// Also refreshes filler_turfs list. +/obj/structure/machinery/door/proc/change_filler_opacity(new_opacity) + // I have no idea why do we null opacity first before... changing it + for(var/turf/filler_turf as anything in filler_turfs) + filler_turf.set_opacity(null) + + filler_turfs = list() + for(var/turf/filler as anything in locate_filler_turfs()) + filler.set_opacity(new_opacity) + filler_turfs += filler + +/// Updates collision box and opacity of multi_tile airlocks. /obj/structure/machinery/door/proc/handle_multidoor() if(width > 1) if(dir in list(EAST, WEST)) bound_width = width * world.icon_size bound_height = world.icon_size - filler = get_step(src,EAST) - filler.set_opacity(opacity) else bound_width = world.icon_size bound_height = width * world.icon_size - filler = get_step(src,NORTH) - filler.set_opacity(opacity) + change_filler_opacity(opacity) + +/// Finds turfs which should be filler ones. +/obj/structure/machinery/door/proc/locate_filler_turfs() + var/turf/filler_temp + var/list/located_turfs = list() -//process() - //return + for(var/i in 1 to width - 1) + if (dir in list(EAST, WEST)) + filler_temp = locate(x + i, y, z) + else + filler_temp = locate(x, y + i, z) + if (filler_temp) + located_turfs += filler_temp + return located_turfs /obj/structure/machinery/door/proc/borders_space() for(var/turf/target in range(1, src)) @@ -81,7 +93,8 @@ return FALSE /obj/structure/machinery/door/Collided(atom/movable/AM) - if(panel_open || operating) return + if(panel_open || operating) + return if(ismob(AM)) var/mob/M = AM if(world.time - M.last_bumped <= openspeed) return //Can bump-open one airlock per second. This is to prevent shock spam. @@ -89,12 +102,10 @@ if(!M.is_mob_restrained() && M.mob_size > MOB_SIZE_SMALL) bumpopen(M) return - if(istype(AM, /obj)) var/obj/O = AM if(O.buckled_mob) Collided(O.buckled_mob) - if(istype(AM, /obj/structure/machinery/bot)) var/obj/structure/machinery/bot/bot = AM if(src.check_access(bot.botcard)) @@ -102,16 +113,17 @@ open() return - /obj/structure/machinery/door/proc/bumpopen(mob/user as mob) - if(operating) return - src.add_fingerprint(user) - if(!src.requiresID()) + if(operating) + return + add_fingerprint(user) + if(!requiresID()) user = null - if(density) - if(allowed(user)) open() - else flick("door_deny", src) + if(allowed(user)) + open() + else + flick("door_deny", src) return /obj/structure/machinery/door/attack_remote(mob/user) @@ -124,9 +136,7 @@ add_fingerprint(user) if(operating) return - if(!Adjacent(user)) - user = null //so allowed(user) always succeeds - if(!requiresID()) + if(!Adjacent(user) || !requiresID()) user = null //so allowed(user) always succeeds if(allowed(user)) if(density) @@ -137,64 +147,56 @@ if(density) flick("door_deny", src) - /obj/structure/machinery/door/attackby(obj/item/I, mob/user) if(!(I.flags_item & NOBLUDGEON)) try_to_activate_door(user) - return 1 + return TRUE /obj/structure/machinery/door/emp_act(severity) - if(prob(20/severity) && (istype(src,/obj/structure/machinery/door/airlock) || istype(src,/obj/structure/machinery/door/window)) ) + . = ..() + if(prob(20/severity) && use_power) open() if(prob(40/severity)) if(secondsElectrified == 0) secondsElectrified = -1 spawn(30 SECONDS) secondsElectrified = 0 - ..() - /obj/structure/machinery/door/ex_act(severity) - if(unacidable) return + if(unacidable) + return if(density) switch(severity) if(0 to EXPLOSION_THRESHOLD_LOW) if(prob(80)) - var/datum/effect_system/spark_spread/s = new /datum/effect_system/spark_spread - s.set_up(2, 1, src) - s.start() + var/datum/effect_system/spark_spread/spark = new /datum/effect_system/spark_spread + spark.set_up(2, 1, src) + spark.start() if(EXPLOSION_THRESHOLD_LOW to INFINITY) qdel(src) else switch(severity) if(0 to EXPLOSION_THRESHOLD_MEDIUM) if(prob(80)) - var/datum/effect_system/spark_spread/s = new /datum/effect_system/spark_spread - s.set_up(2, 1, src) - s.start() + var/datum/effect_system/spark_spread/spark = new /datum/effect_system/spark_spread + spark.set_up(2, 1, src) + spark.start() else qdel(src) return - /obj/structure/machinery/door/get_explosion_resistance() if(density) if(unacidable) - return 1000000 + return 1000000 //Used for negation of explosions, should probably be made into define in the future else return EXPLOSION_THRESHOLD_LOW //this should exactly match the amount of damage needed to destroy the door else return 0 - /obj/structure/machinery/door/update_icon() - if(density) - icon_state = "door1" - else - icon_state = "door0" - return - + icon_state = density ? "door1" : "door0" /obj/structure/machinery/door/proc/do_animate(animation) switch(animation) @@ -212,7 +214,6 @@ flick("door_deny", src) return - /obj/structure/machinery/door/proc/open(forced=0) if(!density) return TRUE @@ -223,8 +224,8 @@ do_animate("opening") icon_state = "door0" set_opacity(FALSE) - if(filler) - filler.set_opacity(opacity) + if(length(filler_turfs)) + change_filler_opacity(opacity) addtimer(CALLBACK(src, PROC_REF(finish_open)), openspeed) return TRUE @@ -235,11 +236,9 @@ if(operating) operating = FALSE - if(autoclose) addtimer(CALLBACK(src, PROC_REF(autoclose)), normalspeed ? 150 + openspeed : 5) - /obj/structure/machinery/door/proc/close() if(density) return TRUE @@ -256,22 +255,19 @@ update_icon() if(visible && !glass) set_opacity(TRUE) - if(filler) - filler.set_opacity(opacity) + if(length(filler_turfs)) + change_filler_opacity(opacity) operating = FALSE /obj/structure/machinery/door/proc/requiresID() return TRUE - -/obj/structure/machinery/door/proc/update_flags_heat_protection(turf/source) - - +/// Used for overriding in airlocks /obj/structure/machinery/door/proc/autoclose() - var/obj/structure/machinery/door/airlock/A = src - if(!A.density && !A.operating && !A.locked && !A.welded && A.autoclose) + if(!autoclose) + return + if(!density && !operating) close() - return /obj/structure/machinery/door/Move(new_loc, new_dir) . = ..() @@ -279,15 +275,10 @@ if(dir in list(EAST, WEST)) bound_width = width * world.icon_size bound_height = world.icon_size - filler.set_opacity(0) - filler = (get_step(src,EAST)) //Find new turf - filler.set_opacity(opacity) else bound_width = world.icon_size bound_height = width * world.icon_size - filler.set_opacity(0) - filler = (get_step(src,NORTH)) //Find new turf - filler.set_opacity(opacity) + change_filler_opacity(opacity) /obj/structure/machinery/door/attack_animal(mob/living/user) . = ..() @@ -318,6 +309,10 @@ return TRUE +/obj/structure/machinery/door/afterShuttleMove(turf/oldT, list/movement_force, shuttle_dir, shuttle_preferred_direction, move_dir, rotation) + . = ..() + // Yes, for a split second after departure you can see through rear dropship airlocks, but it's the simplest solution I could've think of + handle_multidoor() /obj/structure/machinery/door/morgue icon = 'icons/obj/structures/doors/doormorgue.dmi' diff --git a/code/game/machinery/doors/multi_tile.dm b/code/game/machinery/doors/multi_tile.dm index 65ecd67a43..ca21812816 100644 --- a/code/game/machinery/doors/multi_tile.dm +++ b/code/game/machinery/doors/multi_tile.dm @@ -13,7 +13,6 @@ /obj/structure/machinery/door/airlock/multi_tile/Initialize() . = ..() - handle_multidoor() update_icon() /obj/structure/machinery/door/airlock/multi_tile/glass @@ -137,7 +136,6 @@ /obj/structure/window/framed/almayer, /obj/structure/machinery/door/airlock, ) - var/multi_filler = list() /obj/structure/machinery/door/airlock/multi_tile/almayer/Initialize() . = ..() @@ -233,42 +231,6 @@ req_access = null req_one_access = list(ACCESS_CIVILIAN_BRIG, ACCESS_CIVILIAN_COMMAND, ACCESS_WY_COLONIAL) -/obj/structure/machinery/door/airlock/multi_tile/almayer/handle_multidoor() - . = ..() - if(!(width > 1)) return //Bubblewrap - - update_filler_turfs() - -//We have to find these again since these doors are used on shuttles a lot so the turfs changes -/obj/structure/machinery/door/airlock/multi_tile/almayer/proc/update_filler_turfs() - for(var/turf/T in multi_filler) - T.set_opacity(null) - - multi_filler = list() - for(var/turf/T in get_filler_turfs()) - T.set_opacity(opacity) - multi_filler += list(T) - -/obj/structure/machinery/door/airlock/multi_tile/proc/get_filler_turfs() - . = list() - for(var/i = 1, i < width, i++) - if(dir in list(NORTH, SOUTH)) - var/turf/T = locate(x, y + i, z) - if(T) - . += list(T) - else if(dir in list(EAST, WEST)) - var/turf/T = locate(x + i, y, z) - if(T) - . += list(T) - -/obj/structure/machinery/door/airlock/multi_tile/almayer/open() - . = ..() - update_filler_turfs() - -/obj/structure/machinery/door/airlock/multi_tile/almayer/close() - . = ..() - update_filler_turfs() - //------Dropship Cargo Doors -----// /obj/structure/machinery/door/airlock/multi_tile/almayer/dropshiprear diff --git a/code/game/machinery/doors/runed_sandstone.dm b/code/game/machinery/doors/runed_sandstone.dm index 4bf66dfdc8..a6de7348dd 100644 --- a/code/game/machinery/doors/runed_sandstone.dm +++ b/code/game/machinery/doors/runed_sandstone.dm @@ -110,8 +110,8 @@ density = FALSE update_icon() set_opacity(0) - if(filler) - filler.set_opacity(opacity) + if(length(filler_turfs)) + change_filler_opacity(opacity) if(operating) operating = FALSE diff --git a/code/game/machinery/doors/windowdoor.dm b/code/game/machinery/doors/windowdoor.dm index 2b57fbd0a4..bd544c5c3f 100644 --- a/code/game/machinery/doors/windowdoor.dm +++ b/code/game/machinery/doors/windowdoor.dm @@ -11,7 +11,6 @@ flags_atom = ON_BORDER opacity = FALSE var/obj/item/circuitboard/airlock/electronics = null - air_properties_vary_with_direction = 1 /obj/structure/machinery/door/window/Initialize() . = ..() diff --git a/code/game/machinery/fire_alarm.dm b/code/game/machinery/fire_alarm.dm index fe1f80646c..dd7e0ee701 100644 --- a/code/game/machinery/fire_alarm.dm +++ b/code/game/machinery/fire_alarm.dm @@ -63,8 +63,9 @@ FIRE ALARM return src.alarm() /obj/structure/machinery/firealarm/emp_act(severity) - if(prob(50/severity)) alarm() - ..() + . = ..() + if(prob(50/severity)) + alarm() /obj/structure/machinery/firealarm/attackby(obj/item/held_object as obj, mob/user as mob) src.add_fingerprint(user) diff --git a/code/game/machinery/flasher.dm b/code/game/machinery/flasher.dm index 75d0de56de..cd59862a2e 100644 --- a/code/game/machinery/flasher.dm +++ b/code/game/machinery/flasher.dm @@ -84,12 +84,11 @@ /obj/structure/machinery/flasher/emp_act(severity) + . = ..() if(inoperable()) - ..(severity) return if(prob(75/severity)) flash() - ..(severity) /obj/structure/machinery/flasher/portable/HasProximity(atom/movable/AM as mob|obj) if ((src.disable) || (src.last_flash && world.time < src.last_flash + 150)) diff --git a/code/game/machinery/igniter.dm b/code/game/machinery/igniter.dm index 33f75c50e3..d5a0505fca 100644 --- a/code/game/machinery/igniter.dm +++ b/code/game/machinery/igniter.dm @@ -105,11 +105,10 @@ return 1 /obj/structure/machinery/sparker/emp_act(severity) + . = ..() if(inoperable()) - ..(severity) return ignite() - ..(severity) /obj/structure/machinery/ignition_switch/attack_remote(mob/user as mob) return attack_hand(user) diff --git a/code/game/machinery/lightswitch.dm b/code/game/machinery/lightswitch.dm index 66eb038671..de61830c25 100644 --- a/code/game/machinery/lightswitch.dm +++ b/code/game/machinery/lightswitch.dm @@ -62,8 +62,7 @@ updateicon() /obj/structure/machinery/light_switch/emp_act(severity) + . = ..() if(inoperable()) - ..(severity) return power_change() - ..(severity) diff --git a/code/game/machinery/machinery.dm b/code/game/machinery/machinery.dm index 4ce295aa99..66bf08afba 100644 --- a/code/game/machinery/machinery.dm +++ b/code/game/machinery/machinery.dm @@ -175,10 +175,10 @@ Class Procs: . += SPAN_WARNING("[msg]") /obj/structure/machinery/emp_act(severity) + . = ..() if(use_power && stat == 0) use_power(7500/severity) new /obj/effect/overlay/temp/emp_sparks (loc) - ..() /obj/structure/machinery/ex_act(severity) diff --git a/code/game/machinery/medical_pod/sleeper.dm b/code/game/machinery/medical_pod/sleeper.dm index 35d9a44863..bf2abe246c 100644 --- a/code/game/machinery/medical_pod/sleeper.dm +++ b/code/game/machinery/medical_pod/sleeper.dm @@ -332,14 +332,13 @@ /obj/structure/machinery/medical_pod/sleeper/emp_act(severity) + . = ..() if(filtering) toggle_filter() if(inoperable()) - ..(severity) return if(occupant) go_out() - ..() /obj/structure/machinery/medical_pod/sleeper/proc/toggle_filter() if(!occupant) diff --git a/code/game/machinery/recharger.dm b/code/game/machinery/recharger.dm index c75360e075..72e311c6d8 100644 --- a/code/game/machinery/recharger.dm +++ b/code/game/machinery/recharger.dm @@ -218,20 +218,14 @@ update_icon() /obj/structure/machinery/recharger/emp_act(severity) + . = ..() if(inoperable() || !anchored) - ..(severity) return -/* - if(istype(charging, /obj/item/weapon/gun/energy)) - var/obj/item/weapon/gun/energy/E = charging - if(E.power_supply) - E.power_supply.emp_act(severity) -*/ + if(istype(charging, /obj/item/weapon/baton)) var/obj/item/weapon/baton/B = charging if(B.bcell) B.bcell.charge = 0 - ..(severity) /obj/structure/machinery/recharger/update_icon() //we have an update_icon() in addition to the stuff in process to make it feel a tiny bit snappier. src.overlays = 0 diff --git a/code/game/machinery/rechargestation.dm b/code/game/machinery/rechargestation.dm index 6444021288..56b782cd77 100644 --- a/code/game/machinery/rechargestation.dm +++ b/code/game/machinery/rechargestation.dm @@ -109,13 +109,12 @@ return /obj/structure/machinery/recharge_station/emp_act(severity) + . = ..() if(inoperable()) - ..(severity) return if(occupant) occupant.emp_act(severity) go_out() - ..(severity) /obj/structure/machinery/recharge_station/update_icon() ..() diff --git a/code/game/machinery/spaceheater.dm b/code/game/machinery/spaceheater.dm index aa51201ae1..dd45ad5978 100644 --- a/code/game/machinery/spaceheater.dm +++ b/code/game/machinery/spaceheater.dm @@ -40,12 +40,11 @@ /obj/structure/machinery/space_heater/emp_act(severity) + . = ..() if(inoperable()) - ..(severity) return if(cell) cell.emp_act(severity) - ..(severity) /obj/structure/machinery/space_heater/attackby(obj/item/I, mob/user) if(istype(I, /obj/item/cell)) diff --git a/code/game/machinery/status_display.dm b/code/game/machinery/status_display.dm index c56f8da361..79ead63215 100644 --- a/code/game/machinery/status_display.dm +++ b/code/game/machinery/status_display.dm @@ -188,11 +188,10 @@ var/emotion = "Neutral" /obj/structure/machinery/ai_status_display/emp_act(severity) + . = ..() if(inoperable()) - ..(severity) return set_picture("ai_bsod") - ..(severity) /obj/structure/machinery/ai_status_display/proc/update() if(mode==0) //Blank diff --git a/code/game/machinery/telecomms/presets.dm b/code/game/machinery/telecomms/presets.dm index d93304c663..510d488bb3 100644 --- a/code/game/machinery/telecomms/presets.dm +++ b/code/game/machinery/telecomms/presets.dm @@ -449,8 +449,7 @@ GLOBAL_LIST_EMPTY(all_static_telecomms_towers) id = "CentComm Receiver" network = "tcommsat" autolinkers = list("receiverCent") - freq_listening = list(WY_WO_FREQ, PMC_FREQ, DUT_FREQ, YAUT_FREQ, HC_FREQ, PVST_FREQ, SOF_FREQ) - + freq_listening = list(WY_WO_FREQ, PMC_FREQ, DUT_FREQ, YAUT_FREQ, HC_FREQ, PVST_FREQ, SOF_FREQ, CBRN_FREQ) //Buses @@ -469,7 +468,7 @@ GLOBAL_LIST_EMPTY(all_static_telecomms_towers) /obj/structure/machinery/telecomms/bus/preset_three id = "Bus 3" network = "tcommsat" - freq_listening = list(SEC_FREQ, COMM_FREQ, WY_WO_FREQ, PMC_FREQ, DUT_FREQ, YAUT_FREQ, JTAC_FREQ, INTEL_FREQ, WY_FREQ, HC_FREQ, PVST_FREQ, SOF_FREQ) + freq_listening = list(SEC_FREQ, COMM_FREQ, WY_WO_FREQ, PMC_FREQ, DUT_FREQ, YAUT_FREQ, JTAC_FREQ, INTEL_FREQ, WY_FREQ, HC_FREQ, PVST_FREQ, SOF_FREQ, CBRN_FREQ) autolinkers = list("processor3", "security", "command", "JTAC") /obj/structure/machinery/telecomms/bus/preset_four @@ -485,7 +484,7 @@ GLOBAL_LIST_EMPTY(all_static_telecomms_towers) /obj/structure/machinery/telecomms/bus/preset_cent id = "CentComm Bus" network = "tcommsat" - freq_listening = list(WY_WO_FREQ, PMC_FREQ, DUT_FREQ, YAUT_FREQ, HC_FREQ, PVST_FREQ, SOF_FREQ) + freq_listening = list(WY_WO_FREQ, PMC_FREQ, DUT_FREQ, YAUT_FREQ, HC_FREQ, PVST_FREQ, SOF_FREQ, CBRN_FREQ) autolinkers = list("processorCent", "centcomm") //Processors @@ -550,7 +549,7 @@ GLOBAL_LIST_EMPTY(all_static_telecomms_towers) /obj/structure/machinery/telecomms/server/presets/command id = "Command Server" - freq_listening = list(COMM_FREQ, WY_WO_FREQ, PMC_FREQ, DUT_FREQ, YAUT_FREQ, JTAC_FREQ, INTEL_FREQ, WY_FREQ, HC_FREQ, PVST_FREQ, SOF_FREQ) + freq_listening = list(COMM_FREQ, WY_WO_FREQ, PMC_FREQ, DUT_FREQ, YAUT_FREQ, JTAC_FREQ, INTEL_FREQ, WY_FREQ, HC_FREQ, PVST_FREQ, SOF_FREQ, CBRN_FREQ) autolinkers = list("command") /obj/structure/machinery/telecomms/server/presets/engineering @@ -565,10 +564,9 @@ GLOBAL_LIST_EMPTY(all_static_telecomms_towers) /obj/structure/machinery/telecomms/server/presets/centcomm id = "CentComm Server" - freq_listening = list(WY_WO_FREQ, PMC_FREQ, DUT_FREQ, YAUT_FREQ, HC_FREQ, PVST_FREQ, SOF_FREQ) + freq_listening = list(WY_WO_FREQ, PMC_FREQ, DUT_FREQ, YAUT_FREQ, HC_FREQ, PVST_FREQ, SOF_FREQ, CBRN_FREQ) autolinkers = list("centcomm") - //Broadcasters //--PRESET LEFT--// diff --git a/code/game/machinery/telecomms/telecomunications.dm b/code/game/machinery/telecomms/telecomunications.dm index 255d70f458..8b8b12dfd1 100644 --- a/code/game/machinery/telecomms/telecomunications.dm +++ b/code/game/machinery/telecomms/telecomunications.dm @@ -93,13 +93,13 @@ GLOBAL_LIST_EMPTY_TYPED(telecomms_list, /obj/structure/machinery/telecomms) update_state() /obj/structure/machinery/telecomms/emp_act(severity) + . = ..() if(prob(100/severity)) if(!(stat & EMPED)) stat |= EMPED var/duration = (300 * 10)/severity spawn(rand(duration - 20, duration + 20)) // Takes a long time for the machines to reboot. stat &= ~EMPED - ..() /* The receiver idles and receives messages from subspace-compatible radio equipment; diff --git a/code/game/machinery/vending/cm_vending.dm b/code/game/machinery/vending/cm_vending.dm index 56a4429146..a7013a0249 100644 --- a/code/game/machinery/vending/cm_vending.dm +++ b/code/game/machinery/vending/cm_vending.dm @@ -140,9 +140,9 @@ GLOBAL_LIST_EMPTY(vending_products) if(vend_dir_whitelist) var/user_dir = get_dir(loc, user) if(!(user_dir in vend_dir_whitelist)) - return turf + return get_turf(user) var/turf/relative_turf = get_step(user, vend_dir) - if(relative_turf.Adjacent(src)) + if(relative_turf) return relative_turf return turf diff --git a/code/game/machinery/vending/vendor_types/crew/synthetic.dm b/code/game/machinery/vending/vendor_types/crew/synthetic.dm index bf96246e92..c912ae8ce3 100644 --- a/code/game/machinery/vending/vendor_types/crew/synthetic.dm +++ b/code/game/machinery/vending/vendor_types/crew/synthetic.dm @@ -102,7 +102,7 @@ GLOBAL_LIST_INIT(cm_vending_clothing_synth, list( list("Surgical Drop Pouch", 0, /obj/item/clothing/accessory/storage/surg_vest/drop_green, MARINE_CAN_BUY_ACCESSORY, VENDOR_ITEM_REGULAR), list("Surgical Drop Pouch (Blue)", 0, /obj/item/clothing/accessory/storage/surg_vest/drop_blue, MARINE_CAN_BUY_ACCESSORY, VENDOR_ITEM_REGULAR), list("Surgical Drop Pouch (Black)", 0, /obj/item/clothing/accessory/storage/surg_vest/drop_black, MARINE_CAN_BUY_ACCESSORY, VENDOR_ITEM_REGULAR), - list("Tool Webbing", 0, /obj/item/clothing/accessory/storage/black_vest/tool_webbing, MARINE_CAN_BUY_ACCESSORY, VENDOR_ITEM_REGULAR), + list("Tool Webbing", 0, /obj/item/clothing/accessory/storage/tool_webbing/equipped, MARINE_CAN_BUY_ACCESSORY, VENDOR_ITEM_REGULAR), list("Drop Pouch", 0, /obj/item/clothing/accessory/storage/droppouch, MARINE_CAN_BUY_ACCESSORY, VENDOR_ITEM_REGULAR), list("SHOES (CHOOSE 1)", 0, null, null, null), diff --git a/code/game/objects/items/circuitboards/robot_modules.dm b/code/game/objects/items/circuitboards/robot_modules.dm index 2e51853538..04fcff10fa 100644 --- a/code/game/objects/items/circuitboards/robot_modules.dm +++ b/code/game/objects/items/circuitboards/robot_modules.dm @@ -9,13 +9,12 @@ var/list/stacktypes /obj/item/circuitboard/robot_module/emp_act(severity) + . = ..() if(modules) for(var/obj/O in modules) O.emp_act(severity) if(emag) emag.emp_act(severity) - ..() - return /obj/item/circuitboard/robot_module/Initialize() diff --git a/code/game/objects/items/devices/flash.dm b/code/game/objects/items/devices/flash.dm index 0a7709aa61..33a93ed18d 100644 --- a/code/game/objects/items/devices/flash.dm +++ b/code/game/objects/items/devices/flash.dm @@ -155,6 +155,7 @@ do_flash(user = user, aoe = TRUE) /obj/item/device/flash/emp_act(severity) + . = ..() if(broken) return switch(flashes_stored) if(0 to 5) @@ -168,7 +169,6 @@ if(M.flash_eyes()) M.apply_effect(10, WEAKEN) M.visible_message(SPAN_DISARM("[M] is blinded by \the [src]!")) - ..() /obj/item/device/flash/synthetic name = "synthetic flash" diff --git a/code/game/objects/items/devices/portable_vendor.dm b/code/game/objects/items/devices/portable_vendor.dm index 65e2128a02..29e1d06018 100644 --- a/code/game/objects/items/devices/portable_vendor.dm +++ b/code/game/objects/items/devices/portable_vendor.dm @@ -210,6 +210,7 @@ s.start() /obj/item/device/portable_vendor/emp_act(severity) + . = ..() if (broken) return if (prob(40*severity)) diff --git a/code/game/objects/items/devices/radio/headset.dm b/code/game/objects/items/devices/radio/headset.dm index d34444487f..c3320e031e 100644 --- a/code/game/objects/items/devices/radio/headset.dm +++ b/code/game/objects/items/devices/radio/headset.dm @@ -863,6 +863,14 @@ "Corporate Liaison" = TRACKER_CL ) +/obj/item/device/radio/headset/distress/cbrn + name = "\improper CBRN headset" + desc = "A headset given to CBRN marines. Channels are as follows: :g - public, :v - marine command, :a - alpha squad, :b - bravo squad, :c - charlie squad, :d - delta squad, :n - engineering, :m - medbay, :u - requisitions, :j - JTAC, :t - intel" + frequency = CBRN_FREQ + initial_keys = list(/obj/item/device/encryptionkey/public, /obj/item/device/encryptionkey/mcom) + ignore_z = TRUE + has_hud = TRUE + /obj/item/device/radio/headset/distress/pmc/hvh desc = "A special headset used by corporate personnel. Channels are as follows: :o - colony." initial_keys = list(/obj/item/device/encryptionkey/colony, /obj/item/device/encryptionkey/WY) diff --git a/code/game/objects/items/devices/radio/radio.dm b/code/game/objects/items/devices/radio/radio.dm index 2092ffa108..c503edc8f9 100644 --- a/code/game/objects/items/devices/radio/radio.dm +++ b/code/game/objects/items/devices/radio/radio.dm @@ -425,11 +425,11 @@ else return /obj/item/device/radio/emp_act(severity) + . = ..() broadcasting = FALSE listening = FALSE for (var/ch_name in channels) channels[ch_name] = 0 - ..() /////////////////////////////// //////////Borg Radios////////// diff --git a/code/game/objects/items/explosives/mine.dm b/code/game/objects/items/explosives/mine.dm index 742a5f314c..57dd23bf4e 100644 --- a/code/game/objects/items/explosives/mine.dm +++ b/code/game/objects/items/explosives/mine.dm @@ -42,6 +42,7 @@ prime() //We don't care about how strong the explosion was. /obj/item/explosive/mine/emp_act() + . = ..() prime() //Same here. Don't care about the effect strength. diff --git a/code/game/objects/items/handcuffs.dm b/code/game/objects/items/handcuffs.dm index 71fb02cf3f..2137b41d86 100644 --- a/code/game/objects/items/handcuffs.dm +++ b/code/game/objects/items/handcuffs.dm @@ -29,20 +29,6 @@ if(!C.handcuffed) place_handcuffs(C, user) -/obj/item/handcuffs/obj/structure/MouseDrop(mob/living/carbon/human/H) - var/mob/living/carbon/human/user = usr - if (!istype(user)) - return - if (user.stat || get_dist(user, src) > 1 || get_dist(user, H) > 1 || H.lying) - return - if (!istype(H)) - return - - if(!do_after(user, cuff_delay, INTERRUPT_ALL, BUSY_ICON_HOSTILE, H, INTERRUPT_MOVED, BUSY_ICON_GENERIC)) - return - - // TODO: apply handcuffs - /obj/item/handcuffs/get_mob_overlay(mob/user_mob, slot) var/image/ret = ..() diff --git a/code/game/objects/items/implants/implant.dm b/code/game/objects/items/implants/implant.dm index d39b7e6754..e7ebe0391f 100644 --- a/code/game/objects/items/implants/implant.dm +++ b/code/game/objects/items/implants/implant.dm @@ -82,6 +82,7 @@ Implant Specifics:
"} return dat /obj/item/implant/tracking/emp_act(severity) + . = ..() if (malfunction) //no, dawg, you can't malfunction while you are malfunctioning return malfunction = MALFUNCTION_TEMPORARY @@ -216,6 +217,7 @@ Implant Specifics:
"} return 1 /obj/item/implant/explosive/emp_act(severity) + . = ..() if (malfunction) return malfunction = MALFUNCTION_TEMPORARY @@ -307,6 +309,7 @@ the implant may become unstable and either pre-maturely inject the subject or si return /obj/item/implant/chem/emp_act(severity) + . = ..() if (malfunction) return malfunction = MALFUNCTION_TEMPORARY @@ -432,6 +435,7 @@ the implant may become unstable and either pre-maturely inject the subject or si STOP_PROCESSING(SSobj, src) /obj/item/implant/death_alarm/emp_act(severity) //for some reason alarms stop going off in case they are emp'd, even without this + . = ..() if (malfunction) //so I'm just going to add a meltdown chance here return malfunction = MALFUNCTION_TEMPORARY diff --git a/code/game/objects/items/implants/implantneurostim.dm b/code/game/objects/items/implants/implantneurostim.dm index a46cc31a2c..544cf70147 100644 --- a/code/game/objects/items/implants/implantneurostim.dm +++ b/code/game/objects/items/implants/implantneurostim.dm @@ -105,6 +105,7 @@ /obj/item/implant/neurostim/emp_act(severity) + . = ..() if (malfunction) return if (prob(80)) diff --git a/code/game/objects/items/props/helmetgarb.dm b/code/game/objects/items/props/helmetgarb.dm index 72c49a0ea1..b20c567150 100644 --- a/code/game/objects/items/props/helmetgarb.dm +++ b/code/game/objects/items/props/helmetgarb.dm @@ -99,10 +99,8 @@ var/nvg_maxhealth = 125 var/nvg_health = 125 - var/nvg_maxcharge = 2500 - var/nvg_charge = 2500 - var/nvg_drain = 8 // has a 5 minute duration but byond may give it a couple of irl time due to lag - var/infinite_charge = FALSE + /// How much charge the cell should have at most. -1 is infinite + var/cell_max_charge = 2500 var/activated = FALSE var/nightvision = FALSE @@ -117,6 +115,13 @@ var/mob/living/attached_mob var/lighting_alpha = 100 +/obj/item/prop/helmetgarb/helmet_nvg/Initialize(mapload, ...) + . = ..() + if(shape != NVG_SHAPE_COSMETIC) + AddComponent(/datum/component/cell, cell_max_charge, TRUE, charge_drain = 8) + RegisterSignal(src, COMSIG_CELL_TRY_RECHARGING, PROC_REF(cell_try_recharge)) + RegisterSignal(src, COMSIG_CELL_OUT_OF_CHARGE, PROC_REF(on_power_out)) + /obj/item/prop/helmetgarb/helmet_nvg/on_enter_storage(obj/item/storage/internal/S) ..() @@ -139,42 +144,30 @@ /obj/item/prop/helmetgarb/helmet_nvg/attackby(obj/item/A as obj, mob/user as mob) - if(istype(A,/obj/item/cell)) - recharge(A, user) - if(HAS_TRAIT(A, TRAIT_TOOL_SCREWDRIVER)) repair(user) else ..() -/obj/item/prop/helmetgarb/helmet_nvg/proc/recharge(obj/item/cell/C, mob/user as mob) +/obj/item/prop/helmetgarb/helmet_nvg/proc/cell_try_recharge(datum/source, mob/living/user) + SIGNAL_HANDLER + if(user.action_busy) - return + return COMPONENT_CELL_NO_RECHARGE + if(src != user.get_inactive_hand()) - to_chat(user, SPAN_WARNING("You need to hold \the [src] in hand in order to recharge them.")) - return + to_chat(user, SPAN_WARNING("You need to hold [src] in hand in order to recharge them.")) + return COMPONENT_CELL_NO_RECHARGE + if(shape == NVG_SHAPE_COSMETIC) - to_chat(user, SPAN_WARNING("There is no connector for the power cell inside \the [src].")) - return + to_chat(user, SPAN_WARNING("There is no connector for the power cell inside [src].")) + return COMPONENT_CELL_NO_RECHARGE + if(shape == NVG_SHAPE_BROKEN) - to_chat(user, SPAN_WARNING("You need to repair \the [src] first.")) - return - if(nvg_charge == nvg_maxcharge) - to_chat(user, SPAN_WARNING("\The [src] are already fully charged.")) - return + to_chat(user, SPAN_WARNING("You need to repair [src] first.")) + return COMPONENT_CELL_NO_RECHARGE - while(nvg_charge < nvg_maxcharge) - if(C.charge <= 0) - to_chat(user, SPAN_WARNING("\The [C] is completely dry.")) - break - if(!do_after(user, 1 SECONDS, (INTERRUPT_ALL & (~INTERRUPT_MOVED)), BUSY_ICON_BUILD, C, INTERRUPT_DIFF_LOC)) - to_chat(user, SPAN_WARNING("You were interrupted.")) - break - var/to_transfer = min(400, C.charge, (nvg_maxcharge - nvg_charge)) - if(C.use(to_transfer)) - nvg_charge += to_transfer - to_chat(user, "You transfer some power between \the [C] and \the [src]. The gauge now reads: [round(100.0*nvg_charge/nvg_maxcharge) ]%.") /obj/item/prop/helmetgarb/helmet_nvg/proc/repair(mob/user as mob) if(user.action_busy) @@ -202,7 +195,6 @@ to_chat(user, "You successfully patch \the [src].") nvg_maxhealth = 65 nvg_health = 65 - nvg_drain = initial(nvg_drain) * 2 return else if(nvg_health == nvg_maxhealth) @@ -244,9 +236,6 @@ else if(nvg_health_procent >= 0) . += "They are falling apart." - if (get_dist(user, src) <= 1 && (shape == NVG_SHAPE_FINE || shape == NVG_SHAPE_PATCHED)) - . += "A small gauge in the corner reads: Power: [round(100.0*nvg_charge/nvg_maxcharge) ]%." - /obj/item/prop/helmetgarb/helmet_nvg/on_exit_storage(obj/item/storage/S) remove_attached_item() return ..() @@ -296,7 +285,7 @@ if(attached_mob != user && slot == WEAR_HEAD) set_attached_mob(user) - if(slot == WEAR_HEAD && !nightvision && activated && nvg_charge > 0 && shape > NVG_SHAPE_BROKEN) + if(slot == WEAR_HEAD && !nightvision && activated && !SEND_SIGNAL(src, COMSIG_CELL_CHECK_CHARGE) && shape > NVG_SHAPE_BROKEN) enable_nvg(user) else remove_nvg() @@ -319,7 +308,7 @@ attached_item.update_icon() activation.update_button_icon() - START_PROCESSING(SSobj, src) + SEND_SIGNAL(src, COMSIG_CELL_START_TICK_DRAIN) /obj/item/prop/helmetgarb/helmet_nvg/proc/update_sight(mob/M) @@ -353,20 +342,15 @@ attached_mob.update_sight() - STOP_PROCESSING(SSobj, src) + SEND_SIGNAL(src, COMSIG_CELL_STOP_TICK_DRAIN) /obj/item/prop/helmetgarb/helmet_nvg/process(delta_time) - if(nvg_charge > 0 && !infinite_charge) - nvg_charge = max(0, nvg_charge - nvg_drain * delta_time) - if(!attached_mob) return PROCESS_KILL - if(!activated || !attached_item || nvg_charge <= 0 || attached_mob.is_dead()) - if(activated && !attached_mob.is_dead()) - to_chat(attached_mob, SPAN_WARNING("\The [src] emit a low power warning and immediately shut down!")) - remove_nvg() + if(!activated || !attached_item || attached_mob.is_dead()) + on_power_out() return if(!attached_item.has_garb_overlay()) @@ -375,6 +359,13 @@ return +/obj/item/prop/helmetgarb/helmet_nvg/proc/on_power_out(datum/source) + SIGNAL_HANDLER + + if(activated && !attached_mob.is_dead()) + to_chat(attached_mob, SPAN_WARNING("[src] emit a low power warning and immediately shut down!")) + remove_nvg() + /obj/item/prop/helmetgarb/helmet_nvg/ui_action_click(mob/owner, obj/item/holder) toggle_nods(owner) @@ -410,7 +401,7 @@ if(activated) to_chat(user, SPAN_NOTICE("You flip the goggles down.")) icon_state = active_icon_state - if(nvg_charge > 0 && user.head == attached_item && shape > NVG_SHAPE_BROKEN) + if(!SEND_SIGNAL(src, COMSIG_CELL_CHECK_CHARGE) && user.head == attached_item && shape > NVG_SHAPE_BROKEN) enable_nvg(user) else icon_state = active_icon_state @@ -462,7 +453,7 @@ /obj/item/prop/helmetgarb/helmet_nvg/marsoc //for Marine Raiders name = "\improper Tactical M3 night vision goggles" desc = "With an integrated self-recharging battery, nothing can stop you. Put them on your helmet and press the button and it's go-time." - infinite_charge = TRUE + cell_max_charge = -1 #undef NVG_SHAPE_COSMETIC #undef NVG_SHAPE_BROKEN @@ -527,29 +518,38 @@ icon = 'icons/obj/items/items.dmi' icon_state = "photo" ///The human who spawns with the photo - var/mob/living/carbon/human/owner + var/datum/weakref/owner + ///The belonging human name + var/owner_name + ///The belonging human faction + var/owner_faction ///Text written on the back var/scribble -/obj/item/prop/helmetgarb/family_photo/Initialize(mapload, ...) +/obj/item/prop/helmetgarb/family_photo/pickup(mob/user, silent) . = ..() - if(!mapload) - RegisterSignal(src, COMSIG_POST_SPAWN_UPDATE, PROC_REF(set_owner)) + if(!owner) + RegisterSignal(user, COMSIG_POST_SPAWN_UPDATE, PROC_REF(set_owner)) + ///Sets the owner of the family photo to the human it spawns with, needs var/source for signals -/obj/item/prop/helmetgarb/family_photo/proc/set_owner(source = src, mob/living/carbon/human/user) - UnregisterSignal(src, COMSIG_POST_SPAWN_UPDATE) - owner = user +/obj/item/prop/helmetgarb/family_photo/proc/set_owner(datum/source) + SIGNAL_HANDLER + UnregisterSignal(source, COMSIG_POST_SPAWN_UPDATE) + var/mob/living/carbon/human/user = source + owner = WEAKREF(user) + owner_name = user.name + owner_faction = user.faction /obj/item/prop/helmetgarb/family_photo/get_examine_text(mob/user) . = ..() if(scribble) . += "\"[scribble]\" is written on the back of the photo." - if(user == owner) + if(user.weak_reference == owner) . += "A photo of you and your family." return - if(user.faction == owner?.faction) - . += "A photo of [owner] and their family." + if(user.faction == owner_faction) + . += "A photo of [owner_name] and their family." return . += "A photo of a family you do not know." diff --git a/code/game/objects/items/storage/backpack.dm b/code/game/objects/items/storage/backpack.dm index 95c5f181cd..32158a7fe1 100644 --- a/code/game/objects/items/storage/backpack.dm +++ b/code/game/objects/items/storage/backpack.dm @@ -670,6 +670,7 @@ RegisterSignal(H, COMSIG_GRENADE_PRE_PRIME, PROC_REF(cloak_grenade_callback)) RegisterSignal(H, COMSIG_HUMAN_EXTINGUISH, PROC_REF(wrapper_fizzle_camouflage)) + RegisterSignal(H, COMSIG_MOB_EFFECT_CLOAK_CANCEL, PROC_REF(deactivate_camouflage)) camo_active = TRUE ADD_TRAIT(H, TRAIT_CLOAKED, TRAIT_SOURCE_EQUIPMENT(WEAR_BACK)) @@ -699,12 +700,14 @@ deactivate_camouflage(wearer, TRUE, TRUE) /obj/item/storage/backpack/marine/satchel/scout_cloak/proc/deactivate_camouflage(mob/living/carbon/human/H, anim = TRUE, forced) + SIGNAL_HANDLER if(!istype(H)) return FALSE UnregisterSignal(H, list( COMSIG_GRENADE_PRE_PRIME, - COMSIG_HUMAN_EXTINGUISH + COMSIG_HUMAN_EXTINGUISH, + COMSIG_MOB_EFFECT_CLOAK_CANCEL, )) if(forced) diff --git a/code/game/objects/items/storage/pouch.dm b/code/game/objects/items/storage/pouch.dm index 618356f44a..3b1726fd68 100644 --- a/code/game/objects/items/storage/pouch.dm +++ b/code/game/objects/items/storage/pouch.dm @@ -833,6 +833,15 @@ new /obj/item/stack/medical/advanced/ointment(src) new /obj/item/stack/medical/splint(src) +/obj/item/storage/pouch/medkit/full/toxin/fill_preset_inventory() + new /obj/item/device/healthanalyzer(src) + new /obj/item/storage/pill_bottle/antitox(src) + new /obj/item/storage/pill_bottle/antitox(src) + new /obj/item/roller(src) + new /obj/item/stack/medical/splint(src) + new /obj/item/stack/medical/advanced/bruise_pack(src) + new /obj/item/stack/medical/advanced/ointment(src) + /obj/item/storage/pouch/pressurized_reagent_canister name = "Pressurized Reagent Canister Pouch" max_w_class = SIZE_SMALL diff --git a/code/game/objects/items/storage/storage.dm b/code/game/objects/items/storage/storage.dm index cfdb2f88b0..6e7e891d6b 100644 --- a/code/game/objects/items/storage/storage.dm +++ b/code/game/objects/items/storage/storage.dm @@ -852,6 +852,7 @@ W is always an item. stop_warning prevents messaging. user may be null.**/ return ..() /obj/item/storage/emp_act(severity) + . = ..() if(!istype(src.loc, /mob/living)) for(var/obj/O in contents) O.emp_act(severity) diff --git a/code/game/objects/items/tools/misc_tools.dm b/code/game/objects/items/tools/misc_tools.dm index 98dc89321d..0b4a7cc987 100644 --- a/code/game/objects/items/tools/misc_tools.dm +++ b/code/game/objects/items/tools/misc_tools.dm @@ -284,21 +284,24 @@ matter = list("metal" = 20, "gold" = 10) var/static/list/colour_list = list("red", "blue", "green", "yellow", "purple", "pink", "brown", "black", "orange") // Can add more colors as required var/current_colour_index = 1 - var/owner = "hard to read text" + var/owner_name -/obj/item/tool/pen/fountain/Initialize(mapload, ...) +/obj/item/tool/pen/fountain/pickup(mob/user, silent) . = ..() - if(!mapload) - RegisterSignal(src, COMSIG_POST_SPAWN_UPDATE, PROC_REF(set_owner)) + if(!owner_name) + RegisterSignal(user, COMSIG_POST_SPAWN_UPDATE, PROC_REF(set_owner)) ///Sets the owner of the pen to who it spawns with, requires var/source for signals -/obj/item/tool/pen/fountain/proc/set_owner(source = src, mob/living/carbon/human/user) - UnregisterSignal(src, COMSIG_POST_SPAWN_UPDATE) - owner = user +/obj/item/tool/pen/fountain/proc/set_owner(datum/source) + SIGNAL_HANDLER + UnregisterSignal(source, COMSIG_POST_SPAWN_UPDATE) + var/mob/living/carbon/human/user = source + owner_name = user.name /obj/item/tool/pen/fountain/get_examine_text(mob/user) . = ..() - . += "There's a laser engraving of [owner] on it." + if(owner_name) + . += "There's a laser engraving of [owner_name] on it." /obj/item/tool/pen/fountain/attack_self(mob/living/carbon/human/user) if(on) diff --git a/code/game/objects/items/toys/toys.dm b/code/game/objects/items/toys/toys.dm index 7a17904635..851f203c52 100644 --- a/code/game/objects/items/toys/toys.dm +++ b/code/game/objects/items/toys/toys.dm @@ -553,15 +553,15 @@ ///Hexadecimal 0-F (0-15) var/static/list/hexadecimal = list("0", "1", "2", "3" , "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F") -/obj/item/toy/plush/therapy/random_color/New(loc, ...) +/obj/item/toy/plush/therapy/random_color/Initialize(mapload, ...) . = ..() var/color_code = "#[pick(hexadecimal)][pick(hexadecimal)][pick(hexadecimal)][pick(hexadecimal)][pick(hexadecimal)][pick(hexadecimal)]" //This is dumb and I hope theres a better way I'm missing color = color_code - desc = "A custom therapy plush, in a unique color. This one is labeled with \"#[color_code]\"." + desc = "A custom therapy plush, in a unique color." /obj/item/toy/plush/random_plushie //Not using an effect so it can fit into storage from loadout name = "random plush" - desc = "You should not be seeing this" + desc = "This plush looks awfully standard and bland. Is it actually yours?" /// Standard plushies for the spawner to pick from var/list/plush_list = list( /obj/item/toy/plush/farwa, @@ -587,22 +587,32 @@ . = ..() if(mapload) //Placed in mapping, will be randomized instantly on spawn create_plushie() - return - RegisterSignal(src, COMSIG_POST_SPAWN_UPDATE, PROC_REF(create_plushie)) + return INITIALIZE_HINT_QDEL + +/obj/item/toy/plush/random_plushie/pickup(mob/user, silent) + . = ..() + RegisterSignal(user, COMSIG_POST_SPAWN_UPDATE, PROC_REF(create_plushie)) ///The randomizer picking and spawning a plushie on either the ground or in the humans backpack. Needs var/source due to signals -/obj/item/toy/plush/random_plushie/proc/create_plushie(source = src, mob/living/user) - UnregisterSignal(src, COMSIG_POST_SPAWN_UPDATE) +/obj/item/toy/plush/random_plushie/proc/create_plushie(datum/source) + SIGNAL_HANDLER + if(source) + UnregisterSignal(source, COMSIG_POST_SPAWN_UPDATE) + var/turf/spawn_location = get_turf(src) var/plush_list_variety = pick(60; plush_list, 40; therapy_plush_list) var/random_plushie = pick(plush_list_variety) - var/obj/item/toy/plush/plush = new random_plushie(get_turf(src)) //Starts on floor by default + var/obj/item/toy/plush/plush = new random_plushie(spawn_location) //Starts on floor by default + var/mob/living/carbon/human/user = source if(!user) //If it didn't spawn on a humanoid qdel(src) return + var/obj/item/storage/backpack/storage = locate() in user //If the user has a backpack, put it there if(storage?.can_be_inserted(plush, user, stop_messages = TRUE)) storage.attempt_item_insertion(plush, TRUE, user) + if(plush.loc == spawn_location) // Still on the ground + user.put_in_hands(plush, drop_on_fail = TRUE) qdel(src) //Admin plushies diff --git a/code/game/objects/items/weapons/stunbaton.dm b/code/game/objects/items/weapons/stunbaton.dm index 6cb9f58aae..82fdf30f0f 100644 --- a/code/game/objects/items/weapons/stunbaton.dm +++ b/code/game/objects/items/weapons/stunbaton.dm @@ -197,9 +197,9 @@ return TRUE /obj/item/weapon/baton/emp_act(severity) + . = ..() if(bcell) bcell.emp_act(severity) //let's not duplicate code everywhere if we don't have to please. - ..() //secborg stun baton module /obj/item/weapon/baton/robot/attack_self(mob/user) diff --git a/code/game/objects/prop.dm b/code/game/objects/prop.dm index e59c24b30d..c067a9730e 100644 --- a/code/game/objects/prop.dm +++ b/code/game/objects/prop.dm @@ -11,6 +11,66 @@ w_class = SIZE_SMALL garbage = TRUE +/obj/item/prop/geiger_counter + name = "geiger counter" + desc = "A geiger counter measures the radiation it receives. This type automatically records and transfers any information it reads, provided it has a battery, with no user input required beyond being enabled." + icon = 'icons/obj/items/devices.dmi' + icon_state = "geiger" + item_state = "" + w_class = SIZE_SMALL + flags_equip_slot = SLOT_WAIST + ///Whether the geiger counter is on or off + var/toggled_on = FALSE + ///Iconstate of geiger counter when on + var/enabled_state = "geiger_on" + ///Iconstate of geiger counter when off + var/disabled_state = "geiger" + ///New battery it will spawn with + var/starting_battery = /obj/item/cell/crap + ///Battery inside geiger counter + var/obj/item/cell/battery //It doesn't drain the battery, but it has a battery for emergency use + +/obj/item/prop/geiger_counter/Initialize(mapload, ...) + . = ..() + if(!starting_battery) + return + battery = new starting_battery(src) + +/obj/item/prop/geiger_counter/Destroy() + . = ..() + if(battery) + qdel(battery) + +/obj/item/prop/geiger_counter/attack_self(mob/user) + . = ..() + toggled_on = !toggled_on + if(!battery) + to_chat(user, SPAN_NOTICE("[src] is missing a battery.")) + return + to_chat(user, SPAN_NOTICE("You [toggled_on ? "enable" : "disable"] [src].")) + update_icon() + +/obj/item/prop/geiger_counter/attackby(obj/item/attacking_item, mob/user) + . = ..() + if(!HAS_TRAIT(attacking_item, TRAIT_TOOL_SCREWDRIVER) && !HAS_TRAIT(attacking_item, TRAIT_TOOL_CROWBAR)) + return + + if(!battery) + to_chat(user, SPAN_NOTICE("There is no battery for you to remove.")) + return + to_chat(user, SPAN_NOTICE("You jam [battery] out of [src] with [attacking_item], prying it out irreversibly.")) + user.put_in_hands(battery) + battery = null + update_icon() + +/obj/item/prop/geiger_counter/update_icon() + . = ..() + + if(battery && toggled_on) + icon_state = enabled_state + return + icon_state = disabled_state + /obj/item/prop/tableflag name = "United Americas table flag" icon = 'icons/obj/items/items.dmi' diff --git a/code/game/objects/structures/crates_lockers/closets/secure/secure_closets.dm b/code/game/objects/structures/crates_lockers/closets/secure/secure_closets.dm index e290a23a61..331cb884bd 100644 --- a/code/game/objects/structures/crates_lockers/closets/secure/secure_closets.dm +++ b/code/game/objects/structures/crates_lockers/closets/secure/secure_closets.dm @@ -30,6 +30,7 @@ return 0 /obj/structure/closet/secure_closet/emp_act(severity) + . = ..() for(var/obj/O in src) O.emp_act(severity) if(!broken) @@ -42,7 +43,6 @@ else src.req_access = list() src.req_access += pick(get_access(ACCESS_LIST_MARINE_MAIN)) - ..() /obj/structure/closet/secure_closet/proc/togglelock(mob/living/user) if(src.opened) diff --git a/code/game/objects/structures/crates_lockers/crates.dm b/code/game/objects/structures/crates_lockers/crates.dm index 9f0417ccb3..119615ab7a 100644 --- a/code/game/objects/structures/crates_lockers/crates.dm +++ b/code/game/objects/structures/crates_lockers/crates.dm @@ -12,6 +12,19 @@ throwpass = 1 //prevents moving crates by hurling things at them store_mobs = FALSE var/rigged = 0 + /// Types this crate can be made into + var/list/crate_customizing_types = list( + "Plain" = /obj/structure/closet/crate, + "Weapons" = /obj/structure/closet/crate/weapon, + "Supply" = /obj/structure/closet/crate/supply, + "Ammo" = /obj/structure/closet/crate/ammo, + "Construction" = /obj/structure/closet/crate/construction, + "Explosives" = /obj/structure/closet/crate/explosives, + "Alpha" = /obj/structure/closet/crate/alpha, + "Bravo" = /obj/structure/closet/crate/bravo, + "Charlie" = /obj/structure/closet/crate/charlie, + "Delta" = /obj/structure/closet/crate/delta, + ) /obj/structure/closet/crate/initialize_pass_flags(datum/pass_flags_container/PF) ..() @@ -207,6 +220,7 @@ icon_state = "closed_freezer" icon_opened = "open_freezer" icon_closed = "closed_freezer" + crate_customizing_types = null var/target_temp = T0C - 40 var/cooling_power = 40 diff --git a/code/game/objects/structures/crates_lockers/secure_crates.dm b/code/game/objects/structures/crates_lockers/secure_crates.dm index a308c4c0a2..28a77e0c81 100644 --- a/code/game/objects/structures/crates_lockers/secure_crates.dm +++ b/code/game/objects/structures/crates_lockers/secure_crates.dm @@ -4,6 +4,7 @@ icon_state = "secure_locked_basic" icon_opened = "secure_open_basic" icon_closed = "secure_locked_basic" + crate_customizing_types = null var/icon_locked = "secure_locked_basic" var/icon_unlocked = "secure_unlocked_basic" var/sparks = "securecratesparks" @@ -86,6 +87,7 @@ ..() /obj/structure/closet/crate/secure/emp_act(severity) + . = ..() for(var/obj/O in src) O.emp_act(severity) if(!broken && !opened && prob(50/severity)) @@ -105,7 +107,6 @@ else src.req_access = list() src.req_access += pick(get_access(ACCESS_LIST_MARINE_MAIN)) - ..() //------------------------------------ diff --git a/code/game/objects/structures/stool_bed_chair_nest/xeno_nest.dm b/code/game/objects/structures/stool_bed_chair_nest/xeno_nest.dm index 7a4274c2c1..6375fcd138 100644 --- a/code/game/objects/structures/stool_bed_chair_nest/xeno_nest.dm +++ b/code/game/objects/structures/stool_bed_chair_nest/xeno_nest.dm @@ -53,7 +53,7 @@ current_mob.pixel_y = buckling_y["[dir]"] current_mob.pixel_x = buckling_x["[dir]"] current_mob.dir = turn(dir, 180) - current_mob.density = FALSE + ADD_TRAIT(current_mob, TRAIT_UNDENSE, XENO_NEST_TRAIT) pixel_y = buckling_y["[dir]"] pixel_x = buckling_x["[dir]"] if(dir == SOUTH) @@ -67,7 +67,7 @@ current_mob.pixel_y = initial(buckled_mob.pixel_y) current_mob.pixel_x = initial(buckled_mob.pixel_x) - current_mob.density = !(current_mob.lying || current_mob.stat == DEAD) + REMOVE_TRAIT(current_mob, TRAIT_UNDENSE, XENO_NEST_TRAIT) if(dir == SOUTH) current_mob.layer = initial(current_mob.layer) if(!ishuman(current_mob)) diff --git a/code/modules/admin/admin.dm b/code/modules/admin/admin.dm index 5042167023..38b63b9457 100644 --- a/code/modules/admin/admin.dm +++ b/code/modules/admin/admin.dm @@ -261,7 +261,7 @@ if("Remove") if(!GLOB.trait_name_map) GLOB.trait_name_map = generate_trait_name_map() - for(var/trait in D.status_traits) + for(var/trait in D._status_traits) var/name = GLOB.trait_name_map[trait] || trait available_traits[name] = trait @@ -282,7 +282,7 @@ if("All") source = null if("Specific") - source = input("Source to be removed","Trait Remove/Add") as null|anything in sort_list(D.status_traits[chosen_trait]) + source = input("Source to be removed","Trait Remove/Add") as null|anything in sort_list(D._status_traits[chosen_trait]) if(!source) return REMOVE_TRAIT(D,chosen_trait,source) diff --git a/code/modules/admin/fax_templates.dm b/code/modules/admin/fax_templates.dm index 91b23abb24..459ab675d3 100644 --- a/code/modules/admin/fax_templates.dm +++ b/code/modules/admin/fax_templates.dm @@ -1,11 +1,13 @@ /proc/generate_templated_fax(show_wy_logo, fax_header, fax_subject, addressed_to, message_body, sent_by, sent_title, sent_department) + var/datum/asset/asset = get_asset_datum(/datum/asset/simple/paper) + var/dat = "" dat += "