From f45e49fbe034cbcdb94d62a4c6eed63ab18c1dd0 Mon Sep 17 00:00:00 2001 From: MistakeNot4892 Date: Sun, 26 Jan 2025 14:05:25 +1100 Subject: [PATCH] Converting auras, cloaking and stasis into mob modifiers, something like the HUD effect markers on Polaris. HUD datum no longer keeps a hard mob reference. Removing debugging modifier. Renaming obj/var for mob modifiers HUD holder Narrows the mob modifier icons. --- code/__defines/hud.dm | 1 + code/__defines/misc.dm | 11 + code/__defines/mob_status.dm | 4 +- code/__defines/mobs.dm | 16 +- code/__defines/xenoarcheaology.dm | 13 -- code/_macros.dm | 4 +- .../hud/hud_elements/hud_auxilliary.dm | 3 + code/_onclick/hud/hud_types/_hud.dm | 212 ++++++++++++------ code/_onclick/hud/hud_types/robot.dm | 81 ++++--- .../hud/screen/screen_mob_modifier.dm | 155 +++++++++++++ code/_onclick/item_attack.dm | 3 +- code/datums/cinematic.dm | 4 +- code/datums/wires/camera.dm | 2 +- code/game/atoms.dm | 2 +- code/game/atoms_movable.dm | 2 + .../gamemodes/endgame/ftl_jump/ftl_jump.dm | 4 +- code/game/machinery/Sleeper.dm | 5 +- .../stock_parts/_stock_parts.dm | 6 +- .../stock_parts/power/battery.dm | 4 +- .../stock_parts/power/terminal.dm | 4 +- code/game/machinery/camera/camera.dm | 6 +- code/game/machinery/cryopod.dm | 5 +- .../machinery/doors/airlock_interactions.dm | 4 +- code/game/machinery/jukebox.dm | 4 +- code/game/objects/auras/aura.dm | 58 ----- .../auras/personal_shields/personal_shield.dm | 34 --- code/game/objects/auras/radiant_aura.dm | 20 -- code/game/objects/auras/regenerating_aura.dm | 121 ---------- code/game/objects/items/cryobag.dm | 7 +- .../objects/items/devices/personal_shield.dm | 51 +++-- code/game/objects/items/robot/robot_items.dm | 6 +- code/game/objects/items/weapons/stunbaton.dm | 6 +- code/game/objects/structures/mineral_bath.dm | 37 ++- code/game/objects/structures/signs.dm | 2 +- code/modules/abstract/_abstract.dm | 24 +- code/modules/abstract/follower.dm | 18 ++ code/modules/admin/admin.dm | 4 +- code/modules/admin/topic.dm | 2 +- code/modules/admin/view_variables/helpers.dm | 4 +- code/modules/admin/view_variables/topic.dm | 60 +++-- code/modules/augment/passive/nanoaura.dm | 64 ++---- code/modules/client/ui_styles/_ui_style.dm | 3 +- .../client/ui_styles/_ui_style_states.dm | 7 +- .../client/ui_styles/ui_style_subtypes.dm | 18 +- code/modules/clothing/_clothing.dm | 2 +- .../modules/clothing/_clothing_accessories.dm | 4 +- .../gloves/jewelry/rings/ring_aura.dm | 29 --- .../gloves/jewelry/rings/ring_effect.dm | 18 ++ code/modules/clothing/head/fated_key.dm | 2 +- .../modules/clothing/sensors/vitals_sensor.dm | 2 +- .../spacesuits/rig/modules/infiltration.dm | 4 +- code/modules/clothing/spacesuits/rig/rig.dm | 2 +- .../modules/clothing/spacesuits/spacesuits.dm | 4 +- code/modules/clothing/webbing/holster.dm | 2 +- code/modules/events/ailments.dm | 2 +- code/modules/hydroponics/seed_mobs.dm | 2 +- .../implants/implant_types/adrenaline.dm | 6 +- code/modules/item_effects/item_effect_aura.dm | 28 --- .../modules/item_effects/item_effect_debug.dm | 2 +- .../item_effects/item_effect_modifier.dm | 27 +++ code/modules/mechs/equipment/combat.dm | 185 ++------------- code/modules/mechs/mech_damage_immunity.dm | 2 +- code/modules/mob/death.dm | 2 +- code/modules/mob/grab/grab_object.dm | 2 +- code/modules/mob/living/bot/bot.dm | 6 +- code/modules/mob/living/bot/secbot.dm | 4 +- code/modules/mob/living/human/human.dm | 1 - .../mob/living/human/human_attackhand.dm | 2 +- code/modules/mob/living/human/human_grabs.dm | 2 +- .../modules/mob/living/human/human_helpers.dm | 66 ------ code/modules/mob/living/human/life.dm | 6 +- code/modules/mob/living/human/update_icons.dm | 2 +- code/modules/mob/living/life.dm | 11 +- code/modules/mob/living/living.dm | 54 +---- code/modules/mob/living/living_appearance.dm | 32 ++- code/modules/mob/living/living_defense.dm | 36 +-- code/modules/mob/living/living_defines.dm | 3 - code/modules/mob/living/living_status.dm | 19 +- code/modules/mob/living/silicon/login.dm | 2 +- .../mob/living/silicon/pai/software.dm | 7 +- code/modules/mob/living/silicon/robot/life.dm | 4 +- .../mob/living/silicon/robot/robot_items.dm | 4 +- code/modules/mob/living/stasis.dm | 23 -- code/modules/mob/mob.dm | 3 + code/modules/mob/mob_defines.dm | 2 +- code/modules/mob/mob_status.dm | 21 +- code/modules/mob/transform_procs.dm | 4 +- code/modules/mob_modifiers/_modifiers.dm | 89 ++++++++ .../definitions/modifiers_cloaked.dm | 17 ++ .../definitions/modifiers_light.dm | 39 ++++ .../definitions/modifiers_mech_shields.dm | 166 ++++++++++++++ .../definitions/modifiers_nanoswarm.dm | 34 +++ .../definitions/modifiers_object.dm | 19 ++ .../definitions/modifiers_prone.dm | 10 + .../definitions/modifiers_regeneration.dm | 123 ++++++++++ .../definitions/modifiers_restrained.dm | 9 + .../definitions/modifiers_shield.dm | 45 ++++ .../definitions/modifiers_stasis.dm | 26 +++ code/modules/mob_modifiers/modifiers_datum.dm | 75 +++++++ .../mob_modifiers/modifiers_helpers.dm | 78 +++++++ .../modular_computers/hardware/lan_port.dm | 2 +- code/modules/nano/nanoui.dm | 4 +- .../organs/external/_external_icons.dm | 4 +- code/modules/organs/external/head.dm | 2 +- code/modules/organs/internal/brain.dm | 2 +- code/modules/organs/internal/heart.dm | 4 +- code/modules/projectiles/projectile.dm | 2 +- code/modules/reagents/chems/chems_drinks.dm | 2 +- code/modules/species/species.dm | 18 -- .../{_status.dm => _status_condition.dm} | 20 +- .../status_conditions/_status_markers.dm | 19 +- .../{ => definitions}/status_dizzy.dm | 0 .../{ => definitions}/status_jittery.dm | 0 .../{ => definitions}/status_paralyzed.dm | 0 .../{ => definitions}/status_sleeping.dm | 0 .../{ => definitions}/status_stunned.dm | 0 .../{ => definitions}/status_weakened.dm | 0 code/modules/xenoarcheaology/_xenoarch.dm | 12 + .../artifacts/effects/_effect.dm | 28 +-- .../artifacts/effects/badfeeling.dm | 2 +- .../artifacts/effects/cellcharge.dm | 2 +- .../artifacts/effects/celldrain.dm | 2 +- .../artifacts/effects/dnaswitch.dm | 4 +- .../xenoarcheaology/artifacts/effects/emp.dm | 4 +- .../artifacts/effects/forcefield.dm | 2 +- .../artifacts/effects/gas_generation.dm | 4 +- .../artifacts/effects/goodfeeling.dm | 2 +- .../xenoarcheaology/artifacts/effects/heal.dm | 2 +- .../xenoarcheaology/artifacts/effects/hurt.dm | 2 +- .../artifacts/effects/radiate.dm | 2 +- .../artifacts/effects/roboheal.dm | 2 +- .../artifacts/effects/robohurt.dm | 2 +- .../artifacts/effects/sleepy.dm | 6 +- .../xenoarcheaology/artifacts/effects/stun.dm | 2 +- .../artifacts/effects/teleport.dm | 2 +- .../artifacts/effects/temperature.dm | 8 +- .../machinery/artifact_harvester.dm | 2 +- .../tools/ano_device_battery.dm | 6 +- .../mob/screen/styles/midnight/modifiers.dmi | Bin 0 -> 372 bytes .../screen/styles/minimalist/modifiers.dmi | Bin 0 -> 336 bytes icons/mob/screen/styles/modifiers.dmi | Bin 0 -> 233 bytes icons/mob/screen/styles/old/modifiers.dmi | Bin 0 -> 360 bytes .../screen/styles/old_noborder/modifiers.dmi | Bin 0 -> 233 bytes icons/mob/screen/styles/orange/modifiers.dmi | Bin 0 -> 425 bytes .../screen/styles/underworld/modifiers.dmi | Bin 0 -> 417 bytes icons/mob/screen/styles/white/modifiers.dmi | Bin 0 -> 312 bytes icons/obj/decals.dmi | Bin 568 -> 0 bytes icons/screen/mob_modifiers.dmi | Bin 0 -> 1725 bytes .../system/psionics/faculties/coercion.dm | 2 +- .../cult/mobs/constructs/constructs.dm | 2 +- mods/mobs/borers/mob/borer/borer.dm | 4 +- .../drakes/drake_abilities_friendly.dm | 6 +- mods/species/drakes/drake_modifiers.dm | 77 +++---- mods/species/drakes/icons/sifsap.dmi | Bin 0 -> 619 bytes mods/species/serpentid/datum/species.dm | 2 +- .../serpentid/mobs/bodyparts_serpentid.dm | 10 +- .../patches/fantasy/drake_fantasy.dm | 4 +- nebula.dme | 38 ++-- 158 files changed, 1646 insertions(+), 1148 deletions(-) create mode 100644 code/_onclick/hud/screen/screen_mob_modifier.dm delete mode 100644 code/game/objects/auras/aura.dm delete mode 100644 code/game/objects/auras/personal_shields/personal_shield.dm delete mode 100644 code/game/objects/auras/radiant_aura.dm delete mode 100644 code/game/objects/auras/regenerating_aura.dm create mode 100644 code/modules/abstract/follower.dm delete mode 100644 code/modules/clothing/gloves/jewelry/rings/ring_aura.dm create mode 100644 code/modules/clothing/gloves/jewelry/rings/ring_effect.dm delete mode 100644 code/modules/item_effects/item_effect_aura.dm create mode 100644 code/modules/item_effects/item_effect_modifier.dm create mode 100644 code/modules/mob_modifiers/_modifiers.dm create mode 100644 code/modules/mob_modifiers/definitions/modifiers_cloaked.dm create mode 100644 code/modules/mob_modifiers/definitions/modifiers_light.dm create mode 100644 code/modules/mob_modifiers/definitions/modifiers_mech_shields.dm create mode 100644 code/modules/mob_modifiers/definitions/modifiers_nanoswarm.dm create mode 100644 code/modules/mob_modifiers/definitions/modifiers_object.dm create mode 100644 code/modules/mob_modifiers/definitions/modifiers_prone.dm create mode 100644 code/modules/mob_modifiers/definitions/modifiers_regeneration.dm create mode 100644 code/modules/mob_modifiers/definitions/modifiers_restrained.dm create mode 100644 code/modules/mob_modifiers/definitions/modifiers_shield.dm create mode 100644 code/modules/mob_modifiers/definitions/modifiers_stasis.dm create mode 100644 code/modules/mob_modifiers/modifiers_datum.dm create mode 100644 code/modules/mob_modifiers/modifiers_helpers.dm rename code/modules/status_conditions/{_status.dm => _status_condition.dm} (67%) rename code/modules/status_conditions/{ => definitions}/status_dizzy.dm (100%) rename code/modules/status_conditions/{ => definitions}/status_jittery.dm (100%) rename code/modules/status_conditions/{ => definitions}/status_paralyzed.dm (100%) rename code/modules/status_conditions/{ => definitions}/status_sleeping.dm (100%) rename code/modules/status_conditions/{ => definitions}/status_stunned.dm (100%) rename code/modules/status_conditions/{ => definitions}/status_weakened.dm (100%) create mode 100644 code/modules/xenoarcheaology/_xenoarch.dm create mode 100644 icons/mob/screen/styles/midnight/modifiers.dmi create mode 100644 icons/mob/screen/styles/minimalist/modifiers.dmi create mode 100644 icons/mob/screen/styles/modifiers.dmi create mode 100644 icons/mob/screen/styles/old/modifiers.dmi create mode 100644 icons/mob/screen/styles/old_noborder/modifiers.dmi create mode 100644 icons/mob/screen/styles/orange/modifiers.dmi create mode 100644 icons/mob/screen/styles/underworld/modifiers.dmi create mode 100644 icons/mob/screen/styles/white/modifiers.dmi delete mode 100644 icons/obj/decals.dmi create mode 100644 icons/screen/mob_modifiers.dmi create mode 100644 mods/species/drakes/icons/sifsap.dmi diff --git a/code/__defines/hud.dm b/code/__defines/hud.dm index 3353b89d20a..edd1ff5ea4d 100644 --- a/code/__defines/hud.dm +++ b/code/__defines/hud.dm @@ -24,6 +24,7 @@ #define HUD_FIRE /decl/hud_element/fire #define HUD_CHARGE /decl/hud_element/charge #define HUD_ROBOT_MODULE /decl/hud_element/module_selection +#define HUD_MODIFIERS /decl/hud_element/modifiers #define GET_HUD_ALERT(M, A) ((istype(M?.hud_used, /datum/hud) && (A in M.hud_used.alerts)) ? M.hud_used.alerts[A] : 0) #define CLEAR_HUD_ALERTS(M) if(istype(M?.hud_used, /datum/hud) && M.hud_used.alerts) { M.hud_used.alerts = null; } diff --git a/code/__defines/misc.dm b/code/__defines/misc.dm index 85583c6cedf..b9c5a60b173 100644 --- a/code/__defines/misc.dm +++ b/code/__defines/misc.dm @@ -390,3 +390,14 @@ // Default UI style applied to client prefs. #define DEFAULT_UI_STYLE /decl/ui_style/midnight +// Indicates a modifier will never expire. +#define MOB_MODIFIER_INDEFINITE (-1) + +// Indicators for attack checking proc. +#define MM_ATTACK_TYPE_WEAPON 0 +#define MM_ATTACK_TYPE_THROWN 1 +#define MM_ATTACK_TYPE_PROJECTILE 2 + +#define MM_ATTACK_RESULT_NONE 0 +#define MM_ATTACK_RESULT_DEFLECTED BITFLAG(0) +#define MM_ATTACK_RESULT_BLOCKED BITFLAG(1) diff --git a/code/__defines/mob_status.dm b/code/__defines/mob_status.dm index 42bc8854a7a..238ac560411 100644 --- a/code/__defines/mob_status.dm +++ b/code/__defines/mob_status.dm @@ -1,5 +1,5 @@ #define PENDING_STATUS(MOB, COND) (LAZYACCESS(MOB.pending_status_counters, COND) || LAZYACCESS(MOB.status_counters, COND)) #define GET_STATUS(MOB, COND) (LAZYACCESS(MOB.status_counters, COND)) #define HAS_STATUS(MOB, COND) (GET_STATUS(MOB, COND) > 0) -#define ADJ_STATUS(MOB, COND, AMT) (MOB.set_status(COND, PENDING_STATUS(MOB, COND) + AMT)) -#define SET_STATUS_MAX(MOB, COND, AMT) (MOB.set_status(COND, max(PENDING_STATUS(MOB, COND), AMT))) \ No newline at end of file +#define ADJ_STATUS(MOB, COND, AMT) (MOB.set_status_condition(COND, PENDING_STATUS(MOB, COND) + AMT)) +#define SET_STATUS_MAX(MOB, COND, AMT) (MOB.set_status_condition(COND, max(PENDING_STATUS(MOB, COND), AMT))) \ No newline at end of file diff --git a/code/__defines/mobs.dm b/code/__defines/mobs.dm index 00633e438b2..3ea4d3cde8d 100644 --- a/code/__defines/mobs.dm +++ b/code/__defines/mobs.dm @@ -3,7 +3,7 @@ #define UNCONSCIOUS 1 #define DEAD 2 -// Bitflags defining which status effects could be or are inflicted on a mob. +// Bitflags defining which status conditions could be or are inflicted on a mob. #define CANSTUN BITFLAG(0) #define CANWEAKEN BITFLAG(1) #define CANPARALYSE BITFLAG(2) @@ -278,17 +278,6 @@ #define SURGERY_RETRACTED 2 #define SURGERY_ENCASED 3 -#define STASIS_MISC "misc" -#define STASIS_CRYOBAG "cryobag" -#define STASIS_COLD "cold" - -#define AURA_CANCEL 1 -#define AURA_FALSE 2 -#define AURA_TYPE_BULLET "Bullet" -#define AURA_TYPE_WEAPON "Weapon" -#define AURA_TYPE_THROWN "Thrown" -#define AURA_TYPE_LIFE "Life" - #define SPECIES_BLOOD_DEFAULT 560 #define SLIME_EVOLUTION_THRESHOLD 15 @@ -387,7 +376,8 @@ var/global/list/dexterity_levels = list( #define HO_HANDCUFF_LAYER 25 #define HO_INHAND_LAYER 26 #define HO_FIRE_LAYER 27 //If you're on fire -#define TOTAL_OVER_LAYERS 27 +#define HO_EFFECT_LAYER 28 +#define TOTAL_OVER_LAYERS 28 ////////////////////////////////// // Underlay defines; vestigal implementation currently. diff --git a/code/__defines/xenoarcheaology.dm b/code/__defines/xenoarcheaology.dm index 52667268b7d..488ff479067 100644 --- a/code/__defines/xenoarcheaology.dm +++ b/code/__defines/xenoarcheaology.dm @@ -1,16 +1,3 @@ #define XENOFIND_APPLY_PREFIX BITFLAG(0) #define XENOFIND_APPLY_DECOR BITFLAG(1) #define XENOFIND_REPLACE_ICON BITFLAG(2) - -#define EFFECT_TOUCH 0 -#define EFFECT_AURA 1 -#define EFFECT_PULSE 2 -#define MAX_EFFECT 2 - -#define EFFECT_UNKNOWN 0 -#define EFFECT_ENERGY 1 -#define EFFECT_PSIONIC 2 -#define EFFECT_ELECTRO 3 -#define EFFECT_PARTICLE 4 -#define EFFECT_ORGANIC 5 -#define EFFECT_SYNTH 6 \ No newline at end of file diff --git a/code/_macros.dm b/code/_macros.dm index 11e6c146b5d..fba1b139fae 100644 --- a/code/_macros.dm +++ b/code/_macros.dm @@ -147,9 +147,9 @@ #define JOINTEXT(X) jointext(X, null) -#define SPAN_STYLE(S, X) "[X]" +#define SPAN_STYLE(S, X) "" + X + "" +#define SPAN_CLASS(C, X) "" + X + "" -#define SPAN_CLASS(C, X) "[X]" #define SPAN_ITALIC(X) SPAN_CLASS("italic", X) #define SPAN_BOLD(X) SPAN_CLASS("bold", X) #define SPAN_NOTICE(X) SPAN_CLASS("notice", X) diff --git a/code/_onclick/hud/hud_elements/hud_auxilliary.dm b/code/_onclick/hud/hud_elements/hud_auxilliary.dm index 42ae7a89178..bcf8503f5a4 100644 --- a/code/_onclick/hud/hud_elements/hud_auxilliary.dm +++ b/code/_onclick/hud/hud_elements/hud_auxilliary.dm @@ -25,6 +25,9 @@ /decl/hud_element/attack elem_type = /obj/screen/default_attack_selector +/decl/hud_element/modifiers + elem_type = /obj/screen/mob_modifiers + /decl/hud_element/stamina elem_type = /obj/screen/stamina elem_updates_in_life = TRUE diff --git a/code/_onclick/hud/hud_types/_hud.dm b/code/_onclick/hud/hud_types/_hud.dm index d0a95fe197f..f0d9c880d61 100644 --- a/code/_onclick/hud/hud_types/_hud.dm +++ b/code/_onclick/hud/hud_types/_hud.dm @@ -29,7 +29,7 @@ /datum/hud /// A reference to our owning mob. - var/mob/mymob + VAR_PRIVATE/weakref/owner /// Used for the HUD toggle (F12) VAR_PRIVATE/hud_shown = TRUE // Used for showing or hiding the equipment buttons on the left. @@ -79,7 +79,8 @@ /decl/hud_element/oxygen, /decl/hud_element/toxins, /decl/hud_element/bodytemp, - /decl/hud_element/pressure + /decl/hud_element/pressure, + /decl/hud_element/modifiers ) /// /decl/hud_element types to be inserted into hud_elements_to_create during init. VAR_PROTECTED/list/additional_hud_elements @@ -100,9 +101,10 @@ VAR_PRIVATE/obj/screen/gun/radio/gun_radio_use_toggle -/datum/hud/New(mob/owner) - mymob = owner - instantiate() +/datum/hud/New(mob/_owner) + if(istype(_owner)) + owner = weakref(_owner) + instantiate(_owner) ..() /datum/hud/Destroy() @@ -117,10 +119,11 @@ LAZYCLEARLIST(hud_elem_decl_to_object) QDEL_NULL_LIST(all_hud_elements) - if(mymob) + var/mob/mymob = owner?.resolve() + if(istype(mymob)) if(mymob.hud_used == src) mymob.hud_used = null - mymob = null + QDEL_NULL(owner) /datum/hud/proc/is_hud_shown() return hud_shown @@ -133,8 +136,10 @@ return elem?.update_icon() || FALSE /datum/hud/proc/refresh_hud_icons() - for(var/obj/screen/elem in mymob?.client?.screen) - elem.queue_icon_update() + var/mob/mymob = owner?.resolve() + if(istype(mymob) && mymob.client) + for(var/obj/screen/elem in mymob.client.screen) + elem.queue_icon_update() /datum/hud/proc/is_inventory_shown() return inventory_shown @@ -142,29 +147,39 @@ /datum/hud/proc/hide_inventory() inventory_shown = FALSE if(LAZYLEN(hud_elements_hidable)) - mymob?.client?.screen -= hud_elements_hidable + var/mob/mymob = owner?.resolve() + if(istype(mymob) && mymob.client) + mymob.client.screen -= hud_elements_hidable hidden_inventory_update() persistent_inventory_update() /datum/hud/proc/show_inventory() inventory_shown = TRUE if(LAZYLEN(hud_elements_hidable)) - mymob?.client?.screen += hud_elements_hidable + var/mob/mymob = owner?.resolve() + if(istype(mymob) && mymob.client) + mymob.client.screen += hud_elements_hidable hidden_inventory_update() persistent_inventory_update() /datum/hud/proc/hidden_inventory_update() - var/decl/species/species = mymob?.get_species() + var/mob/mymob = owner?.resolve() + var/decl/species/species = istype(mymob) && mymob.get_species() if(istype(species?.species_hud)) refresh_inventory_slots(species.species_hud.hidden_slots, (inventory_shown && hud_shown)) /datum/hud/proc/persistent_inventory_update() - var/decl/species/species = mymob?.get_species() + var/mob/mymob = owner?.resolve() + var/decl/species/species = istype(mymob) && mymob.get_species() if(istype(species?.species_hud)) refresh_inventory_slots(species.species_hud.persistent_slots, hud_shown) /datum/hud/proc/refresh_inventory_slots(var/list/checking_slots, var/show_hud) + var/mob/mymob = owner?.resolve() + if(!istype(mymob)) + return FALSE + for(var/slot in checking_slots) var/datum/inventory_slot/inv_slot = mymob.get_inventory_slot_datum(slot) @@ -183,18 +198,36 @@ else inv_slot.show_slot() -/datum/hud/proc/instantiate() - if(ismob(mymob) && mymob.client) - finalize_instantiation() + return TRUE + +/datum/hud/proc/instantiate(mob/_owner) + if(ismob(_owner) && _owner.client) + finalize_instantiation(_owner) refresh_hud_icons() return TRUE return FALSE /datum/hud/proc/handle_life_hud_update() + + var/mob/mymob = owner?.resolve() + if(!istype(mymob)) + return FALSE + + if(mymob.buckled || mymob.restrained()) + mymob.add_mob_modifier(/decl/mob_modifier/restrained, source = mymob) + else + mymob.remove_mob_modifier(/decl/mob_modifier/restrained, source = mymob) + + if(mymob.current_posture?.prone) + mymob.add_mob_modifier(/decl/mob_modifier/prone, source = mymob) + else + mymob.remove_mob_modifier(/decl/mob_modifier/prone, source = mymob) + for(var/obj/screen/elem as anything in hud_elements_update_in_life) elem.update_icon() + return TRUE -/datum/hud/proc/finalize_instantiation() +/datum/hud/proc/finalize_instantiation(mob/_owner) SHOULD_CALL_PARENT(TRUE) @@ -215,11 +248,11 @@ //Handle the gun settings buttons if(!gun_mode_toggle && gun_mode_toggle_type) - gun_mode_toggle = new gun_mode_toggle_type(null, mymob, ui_style, ui_color, ui_alpha, HUD_FIRE_INTENT) + gun_mode_toggle = new gun_mode_toggle_type(null, _owner, ui_style, ui_color, ui_alpha, HUD_FIRE_INTENT) LAZYADD(hud_elements_auxilliary, gun_mode_toggle) - gun_item_use_toggle = new(null, mymob, ui_style, ui_color, ui_alpha, HUD_FIRE_INTENT) - gun_move_toggle = new(null, mymob, ui_style, ui_color, ui_alpha, HUD_FIRE_INTENT) - gun_radio_use_toggle = new(null, mymob, ui_style, ui_color, ui_alpha, HUD_FIRE_INTENT) + gun_item_use_toggle = new(null, _owner, ui_style, ui_color, ui_alpha, HUD_FIRE_INTENT) + gun_move_toggle = new(null, _owner, ui_style, ui_color, ui_alpha, HUD_FIRE_INTENT) + gun_radio_use_toggle = new(null, _owner, ui_style, ui_color, ui_alpha, HUD_FIRE_INTENT) build_inventory_ui() build_hands_ui() @@ -239,16 +272,17 @@ all_hud_elements |= hud_elements_auxilliary UNSETEMPTY(all_hud_elements) - if(mymob.client) - mymob.client.screen = list() + if(_owner.client) + _owner.client.screen = list() if(LAZYLEN(all_hud_elements)) - mymob.client.screen |= all_hud_elements + _owner.client.screen |= all_hud_elements hide_inventory() /datum/hud/proc/get_ui_style_data() RETURN_TYPE(/decl/ui_style) - . = GET_DECL(mymob?.client?.prefs?.UI_style) || GET_DECL(default_ui_style) + var/mob/mymob = owner?.resolve() + . = (istype(mymob) && GET_DECL(mymob.client?.prefs?.UI_style)) || GET_DECL(default_ui_style) if(!.) var/list/available_styles = get_ui_styles() if(length(available_styles)) @@ -258,13 +292,19 @@ var/decl/ui_style/ui_style = get_ui_style_data() if(!ui_style?.use_ui_color) return COLOR_WHITE - return mymob?.client?.prefs?.UI_style_color || COLOR_WHITE + var/mob/mymob = owner?.resolve() + return (istype(mymob) && mymob.client?.prefs?.UI_style_color) || COLOR_WHITE /datum/hud/proc/get_ui_alpha() - return mymob?.client?.prefs?.UI_style_alpha || 255 + var/mob/mymob = owner?.resolve() + return (istype(mymob) && mymob.client?.prefs?.UI_style_alpha) || 255 /datum/hud/proc/rebuild_hands() + var/mob/mymob = owner?.resolve() + if(!istype(mymob)) + return FALSE + var/decl/ui_style/ui_style = get_ui_style_data() var/ui_color = get_ui_color() var/ui_alpha = get_ui_alpha() @@ -355,8 +395,14 @@ if(mymob.client) mymob.client.screen |= swap_elem + return TRUE + /datum/hud/proc/build_inventory_ui() + var/mob/mymob = owner?.resolve() + if(!istype(mymob)) + return FALSE + var/decl/ui_style/ui_style = get_ui_style_data() var/ui_color = get_ui_color() var/ui_alpha = get_ui_alpha() @@ -392,11 +438,17 @@ if(has_hidden_gear) hud_elements_auxilliary += new /obj/screen/toggle(null, mymob, ui_style, ui_color, ui_alpha, HUD_INVENTORY) + return TRUE + /datum/hud/proc/build_hands_ui() + var/mob/mymob = owner?.resolve() + if(!istype(mymob)) + return FALSE + var/list/held_slots = mymob.get_held_item_slots() if(length(held_slots) <= 0) - return + return FALSE var/decl/ui_style/ui_style = get_ui_style_data() var/ui_color = get_ui_color() @@ -414,6 +466,7 @@ // Actual hand elems. rebuild_hands() + return TRUE /datum/hud/proc/toggle_show_inventory() if(inventory_shown) @@ -427,57 +480,63 @@ return action_buttons_hidden /datum/hud/proc/toggle_minimize(var/full) - if(hud_shown) - hud_shown = FALSE - if(hud_elements_auxilliary) - mymob?.client?.screen -= hud_elements_auxilliary - if(hud_elements_hidable) - mymob?.client?.screen -= hud_elements_hidable - if(hud_elements_hotkeys) - mymob?.client?.screen -= hud_elements_hotkeys - if(!full) - if(LAZYLEN(hud_elements_hands)) - mymob?.client?.screen += hud_elements_hands // we want the hands to be visible - if(LAZYLEN(hud_elements_swap)) - mymob?.client?.screen += hud_elements_swap // we want the hands swap thingy to be visible - else - hud_shown = TRUE - if(LAZYLEN(hud_elements_auxilliary)) - mymob?.client?.screen |= hud_elements_auxilliary - if(LAZYLEN(hud_elements_hidable) && inventory_shown) - mymob?.client?.screen |= hud_elements_hidable - if(LAZYLEN(hud_elements_hotkeys) && !hotkey_ui_hidden) - mymob?.client?.screen |= hud_elements_hotkeys + hud_shown = !hud_shown + var/mob/mymob = owner?.resolve() + if(istype(mymob) && mymob.client) + if(hud_shown) + if(LAZYLEN(hud_elements_auxilliary)) + mymob.client.screen |= hud_elements_auxilliary + if(LAZYLEN(hud_elements_hidable) && inventory_shown) + mymob.client.screen |= hud_elements_hidable + if(LAZYLEN(hud_elements_hotkeys) && !hotkey_ui_hidden) + mymob.client.screen |= hud_elements_hotkeys + else + if(hud_elements_auxilliary) + mymob.client.screen -= hud_elements_auxilliary + if(hud_elements_hidable) + mymob.client.screen -= hud_elements_hidable + if(hud_elements_hotkeys) + mymob.client.screen -= hud_elements_hotkeys + if(!full) + if(LAZYLEN(hud_elements_hands)) + mymob.client.screen += hud_elements_hands // we want the hands to be visible + if(LAZYLEN(hud_elements_swap)) + mymob.client.screen += hud_elements_swap // we want the hands swap thingy to be visible + hidden_inventory_update() persistent_inventory_update() + return TRUE /datum/hud/proc/toggle_zoom_hud() - if(hud_shown) - hud_shown = FALSE - if(LAZYLEN(hud_elements_auxilliary)) - mymob?.client?.screen -= hud_elements_auxilliary - if(LAZYLEN(hud_elements_hidable)) - mymob?.client?.screen -= hud_elements_hidable - if(LAZYLEN(hud_elements_hotkeys)) - mymob?.client?.screen -= hud_elements_hotkeys - else - hud_shown = TRUE - if(LAZYLEN(hud_elements_auxilliary)) - mymob?.client?.screen += hud_elements_auxilliary - if(LAZYLEN(hud_elements_hidable) && inventory_shown) - mymob?.client?.screen += hud_elements_hidable - if(LAZYLEN(hud_elements_hotkeys) && !hotkey_ui_hidden) - mymob?.client?.screen += hud_elements_hotkeys + hud_shown = !hud_shown + var/mob/mymob = owner?.resolve() + if(istype(mymob) && mymob.client) + if(hud_shown) + if(LAZYLEN(hud_elements_auxilliary)) + mymob.client.screen += hud_elements_auxilliary + if(LAZYLEN(hud_elements_hidable) && inventory_shown) + mymob.client.screen += hud_elements_hidable + if(LAZYLEN(hud_elements_hotkeys) && !hotkey_ui_hidden) + mymob.client.screen += hud_elements_hotkeys + else + if(LAZYLEN(hud_elements_auxilliary)) + mymob.client.screen -= hud_elements_auxilliary + if(LAZYLEN(hud_elements_hidable)) + mymob.client.screen -= hud_elements_hidable + if(LAZYLEN(hud_elements_hotkeys)) + mymob.client.screen -= hud_elements_hotkeys + hidden_inventory_update() persistent_inventory_update() /datum/hud/proc/toggle_hotkeys() - if(hotkey_ui_hidden) - mymob?.client?.screen += hud_elements_hotkeys - hotkey_ui_hidden = 0 - else - mymob?.client?.screen -= hud_elements_hotkeys - hotkey_ui_hidden = TRUE + hotkey_ui_hidden = !hotkey_ui_hidden + var/mob/mymob = owner?.resolve() + if(istype(mymob) && mymob.client) + if(hotkey_ui_hidden) + mymob.client.screen -= hud_elements_hotkeys + else + mymob.client.screen += hud_elements_hotkeys /mob/verb/toggle_hotkey_verbs() set category = "OOC" @@ -537,13 +596,15 @@ // This can runtime if someone manages to throw a gun out of their hand before the proc is called. if(!gun_item_use_toggle) return TRUE - if(mymob?.client) + var/mob/mymob = owner?.resolve() + if(istype(mymob) && mymob.client) mymob.client.screen |= gun_item_use_toggle mymob.client.screen |= gun_move_toggle mymob.client.screen |= gun_radio_use_toggle /datum/hud/proc/remove_gun_icons() - if(mymob?.client) + var/mob/mymob = owner?.resolve() + if(istype(mymob) && mymob.client) mymob.client.screen -= gun_item_use_toggle mymob.client.screen -= gun_move_toggle mymob.client.screen -= gun_radio_use_toggle @@ -574,8 +635,11 @@ gun_radio_use_toggle.update_icon() /datum/hud/proc/create_and_register_element(decl/hud_element/ui_elem, decl/ui_style/ui_style, ui_color, ui_alpha) - if(!istype(ui_elem) || !ui_elem.elem_type) + + var/mob/mymob = owner?.resolve() + if(!istype(mymob) || !istype(ui_elem) || !ui_elem.elem_type) return FALSE + var/obj/screen/elem = new ui_elem.elem_type(null, mymob, ui_style, ui_color, ui_alpha, ui_elem.elem_reference_type) if(ui_elem.elem_is_hotkey) LAZYDISTINCTADD(hud_elements_hotkeys, elem) diff --git a/code/_onclick/hud/hud_types/robot.dm b/code/_onclick/hud/hud_types/robot.dm index 9dd085ffe9c..051484a4acd 100644 --- a/code/_onclick/hud/hud_types/robot.dm +++ b/code/_onclick/hud/hud_types/robot.dm @@ -11,50 +11,47 @@ return 255 // TODO: Convert robots to use inventory slots. -/datum/hud/robot/finalize_instantiation() - var/mob/living/silicon/robot/R = mymob - if(!istype(R)) +/datum/hud/robot/finalize_instantiation(mob/_owner) + var/mob/living/silicon/robot/robit = _owner + if(!istype(robit)) return ..() - R.inv1 = new(null, mymob) - R.inv2 = new(null, mymob) - R.inv3 = new(null, mymob) + robit.inv1 = new(null, _owner) + robit.inv2 = new(null, _owner) + robit.inv3 = new(null, _owner) LAZYINITLIST(hud_elements_auxilliary) - hud_elements_auxilliary += R.inv1 - hud_elements_auxilliary += R.inv2 - hud_elements_auxilliary += R.inv3 + hud_elements_auxilliary += robit.inv1 + hud_elements_auxilliary += robit.inv2 + hud_elements_auxilliary += robit.inv3 ..() /datum/hud/proc/toggle_show_robot_modules() - if(!isrobot(mymob)) - return - var/mob/living/silicon/robot/r = mymob - r.shown_robot_modules = !r.shown_robot_modules - update_robot_modules_display() - + var/mob/living/silicon/robot/robit = owner?.resolve() + if(istype(robit)) + robit.shown_robot_modules = !robit.shown_robot_modules + update_robot_modules_display() /datum/hud/proc/update_robot_modules_display() - if(!isrobot(mymob) || !mymob.client) + var/mob/living/silicon/robot/robit = owner?.resolve() + if(!istype(robit) || !robit.client) return - var/mob/living/silicon/robot/R = mymob - - if(R.shown_robot_modules) - if(R.active_storage) - R.active_storage.close(R) //Closes the inventory ui. + if(robit.shown_robot_modules) + if(robit.active_storage) + robit.active_storage.close(robit) //Closes the inventory ui. - if(!R.module) - to_chat(R, SPAN_WARNING("No module selected.")) + if(!robit.module) + to_chat(robit, SPAN_WARNING("No module selected.")) return - if(!R.module.equipment) - to_chat(R, SPAN_WARNING("Selected module has no equipment available.")) + if(!robit.module.equipment) + to_chat(robit, SPAN_WARNING("Selected module has no equipment available.")) return - if(!R.robot_modules_background) + if(!robit.robot_modules_background) return - var/display_rows = ceil(R.module.equipment.len / 8) - R.robot_modules_background.screen_loc = "CENTER-4:16,BOTTOM+1:7 to CENTER+3:16,BOTTOM+[display_rows]:7" - R.client.screen += R.robot_modules_background + var/display_rows = ceil(robit.module.equipment.len / 8) + robit.robot_modules_background.screen_loc = "CENTER-4:16,BOTTOM+1:7 to CENTER+3:16,BOTTOM+[display_rows]:7" + robit.client.screen += robit.robot_modules_background var/x = -4 //Start at CENTER-4,SOUTH+1 var/y = 1 @@ -62,17 +59,17 @@ //Unfortunately adding the emag module to the list of modules has to be here. This is because a borg can //be emagged before they actually select a module. - or some situation can cause them to get a new module // - or some situation might cause them to get de-emagged or something. - if(R.emagged) - if(!(R.module.emag in R.module.equipment)) - R.module.equipment.Add(R.module.emag) + if(robit.emagged) + if(!(robit.module.emag in robit.module.equipment)) + robit.module.equipment.Add(robit.module.emag) else - if(R.module.emag in R.module.equipment) - R.module.equipment.Remove(R.module.emag) + if(robit.module.emag in robit.module.equipment) + robit.module.equipment.Remove(robit.module.emag) - for(var/atom/movable/A in R.module.equipment) - if( (A != R.module_state_1) && (A != R.module_state_2) && (A != R.module_state_3) ) + for(var/atom/movable/A in robit.module.equipment) + if( (A != robit.module_state_1) && (A != robit.module_state_2) && (A != robit.module_state_3) ) //Module is not currently active - R.client.screen += A + robit.client.screen += A if(x < 0) A.screen_loc = "CENTER[x]:[WORLD_ICON_SIZE/2],BOTTOM+[y]:7" else @@ -86,9 +83,9 @@ else //Modules display is hidden - for(var/atom/A in R.module.equipment) - if( (A != R.module_state_1) && (A != R.module_state_2) && (A != R.module_state_3) ) + for(var/atom/A in robit.module.equipment) + if( (A != robit.module_state_1) && (A != robit.module_state_2) && (A != robit.module_state_3) ) //Module is not currently active - R.client.screen -= A - R.shown_robot_modules = 0 - R.client.screen -= R.robot_modules_background + robit.client.screen -= A + robit.shown_robot_modules = 0 + robit.client.screen -= robit.robot_modules_background diff --git a/code/_onclick/hud/screen/screen_mob_modifier.dm b/code/_onclick/hud/screen/screen_mob_modifier.dm new file mode 100644 index 00000000000..da38d783020 --- /dev/null +++ b/code/_onclick/hud/screen/screen_mob_modifier.dm @@ -0,0 +1,155 @@ +/obj/screen/mob_modifiers + screen_loc = "CENTER,TOP" + icon_state = "blank" + requires_ui_style = FALSE + + // Disable these due to vis_contents behaving oddly with them. + use_supplied_ui_color = FALSE + use_supplied_ui_alpha = FALSE + + // TODO: consider pooling these. + var/list/elements + var/const/modifier_size = 18 + +/obj/screen/mob_modifiers/Initialize(mapload, mob/_owner, decl/ui_style/ui_style, ui_color, ui_alpha, ui_cat) + . = ..() + START_PROCESSING(SSprocessing, src) + +/obj/screen/mob_modifiers/Destroy() + STOP_PROCESSING(SSprocessing, src) + QDEL_NULL_LIST(elements) + return ..() + +/obj/screen/mob_modifiers/Process() + if(QDELETED(src)) + return PROCESS_KILL + var/mob/living/owner = owner_ref?.resolve() + if(!istype(owner)) + return PROCESS_KILL + for(var/obj/screen/mob_modifier/element in elements) + var/expire_time = MOB_MODIFIER_INDEFINITE + for(var/datum/mob_modifier/modifier in LAZYACCESS(owner._mob_modifiers, element.archetype)) + if(modifier.expire_time == MOB_MODIFIER_INDEFINITE) + expire_time = MOB_MODIFIER_INDEFINITE + break + expire_time = max(expire_time, modifier.expire_time) + if(istype(element)) + element.update_maptext(expire_time == MOB_MODIFIER_INDEFINITE ? MOB_MODIFIER_INDEFINITE : (expire_time - world.time)) + +/obj/screen/mob_modifiers/on_update_icon() + + if(QDELETED(src)) + return + + var/mob/living/owner = owner_ref?.resolve() + if(!istype(owner) || !istype(owner.hud_used)) + return + + var/list/seen_archetypes + var/list/elements_to_keep + var/list/elements_to_add + var/list/elements_to_remove + + // Track deltas for keeping/removing existing elements. + for(var/obj/screen/mob_modifier/element in elements) + var/list/modifiers = LAZYACCESS(owner._mob_modifiers, element.archetype) + if(length(modifiers)) + LAZYADD(elements_to_keep, element) + else + LAZYADD(elements_to_remove, element) + LAZYDISTINCTADD(seen_archetypes, element.archetype) + + var/decl/ui_style/ui_style = owner.hud_used.get_ui_style_data() + var/ui_color = owner.hud_used.get_ui_color() + var/ui_alpha = owner.hud_used.get_ui_alpha() + + // Create elements for new modifiers. + for(var/decl/mob_modifier/archetype in owner._mob_modifiers) + if(archetype in seen_archetypes) + continue + var/obj/screen/mob_modifier/element = new(null, owner, ui_style, ui_color, ui_alpha, HUD_MODIFIERS) + element.archetype = archetype + element.holder = src + element.pixel_y = 32 + element.alpha = 0 + element.update_icon() + LAZYADD(elements_to_add, element) + + // Fade out and delete expired markers. + if(LAZYLEN(elements_to_remove)) + LAZYREMOVE(elements, elements_to_remove) + for(var/obj/screen/mob_modifier/element in elements_to_remove) + animate(element, alpha = 0, pixel_y = 32, time = 5) + QDEL_IN(element, 5) + + // Add our new records. + if(LAZYLEN(elements_to_add)) + LAZYADD(elements, elements_to_add) + add_vis_contents(elements_to_add) + + // Adjust positions and fade in new elements. + if(length(elements)) + var/offset_x = -(((length(elements)-1) * modifier_size) / 2) + for(var/obj/screen/element in elements) + if(element in elements_to_add) + pixel_x = offset_x + animate(element, alpha = 255, pixel_x = offset_x, pixel_y = 0, time = 5) + offset_x += modifier_size + +/obj/screen/mob_modifier + alpha = 0 + screen_loc = null // not handled via screen loc, but via vis contents of the holder object. + maptext_x = -8 + maptext_y = -3 + icon_state = "modifier_base" + var/decl/mob_modifier/archetype + var/obj/screen/mob_modifiers/holder + +/obj/screen/mob_modifier/Destroy() + if(holder) + LAZYREMOVE(holder.elements, src) + holder.remove_vis_contents(src) + holder = null + return ..() + +/obj/screen/mob_modifier/rebuild_screen_overlays() + . = ..() + if(archetype) + add_overlay(overlay_image(archetype.hud_icon, archetype.hud_icon_state, COLOR_WHITE, RESET_COLOR)) + +/obj/screen/mob_modifier/proc/update_maptext(duration) + if(archetype.hide_expiry) + maptext = null + return + + if(duration == MOB_MODIFIER_INDEFINITE) + if(archetype.show_indefinite_duration) + maptext = STYLE_SMALLFONTS_OUTLINE("
", 12, COLOR_WHITE, COLOR_BLACK) + else + maptext = null + else if(duration <= 0) + maptext = STYLE_SMALLFONTS_OUTLINE("
0
", 7, COLOR_WHITE, COLOR_BLACK) + else + maptext = STYLE_SMALLFONTS_OUTLINE("
[ticks2shortreadable(duration) || 0]
", 7, COLOR_WHITE, COLOR_BLACK) + +/obj/screen/mob_modifier/handle_click(mob/user, params) + if((. = ..())) + var/mob/living/owner = owner_ref?.resolve() + if(istype(owner) && archetype) + var/list/modifiers = LAZYACCESS(owner._mob_modifiers, archetype) + for(var/datum/mob_modifier/modifier in modifiers) + modifier.on_modifier_click(params) + return + +/obj/screen/mob_modifier/MouseEntered(location, control, params) + if(archetype && (archetype.name || archetype.desc)) + openToolTip(user = usr, tip_src = src, params = params, title = archetype.name, content = archetype.desc) + ..() + +/obj/screen/mob_modifier/MouseDown() + closeToolTip(usr) + ..() + +/obj/screen/mob_modifier/MouseExited() + closeToolTip(usr) + ..() diff --git a/code/_onclick/item_attack.dm b/code/_onclick/item_attack.dm index b92356b4a14..f60ad5c1ca4 100644 --- a/code/_onclick/item_attack.dm +++ b/code/_onclick/item_attack.dm @@ -154,7 +154,8 @@ avoid code duplication. This includes items that may sometimes act as a standard user.setClickCooldown(attack_cooldown + w_class) if(animate) user.do_attack_animation(target) - if(!user.aura_check(AURA_TYPE_WEAPON, src, user)) + + if(target.mob_modifiers_block_attack(MM_ATTACK_TYPE_WEAPON, user, src)) return FALSE var/hit_zone = target.resolve_item_attack(src, user, user.get_target_zone()) diff --git a/code/datums/cinematic.dm b/code/datums/cinematic.dm index 86ddc55b91f..bf03370505e 100644 --- a/code/datums/cinematic.dm +++ b/code/datums/cinematic.dm @@ -27,7 +27,7 @@ var/global/datum/cinematic/cinematic = new if(M.client) M.client.screen += cinematic_screen //show every client the cinematic viewers[M.client] = GET_STATUS(M, STAT_STUN) - M.set_status(STAT_STUN, 8000) + M.set_status_condition(STAT_STUN, 8000) override.nuke_act(cinematic_screen, station_missed) //cinematic happens here, as does mob death. //If it's actually the end of the round, wait for it to end. @@ -36,6 +36,6 @@ var/global/datum/cinematic/cinematic = new for(var/client/C in viewers) if(C.mob) - C.mob.set_status(STAT_STUN, viewers[C]) + C.mob.set_status_condition(STAT_STUN, viewers[C]) C.screen -= cinematic_screen QDEL_NULL(cinematic_screen) \ No newline at end of file diff --git a/code/datums/wires/camera.dm b/code/datums/wires/camera.dm index 09046ea83f1..c1e09d29280 100644 --- a/code/datums/wires/camera.dm +++ b/code/datums/wires/camera.dm @@ -42,7 +42,7 @@ var/global/const/CAMERA_WIRE_ALARM = 8 if(CAMERA_WIRE_POWER) C.cut_power = !mended - C.set_status(mended, usr) + C.set_camera_status(mended, usr) if(CAMERA_WIRE_LIGHT) C.light_disabled = !mended diff --git a/code/game/atoms.dm b/code/game/atoms.dm index cf302e4faad..a77f10b831c 100644 --- a/code/game/atoms.dm +++ b/code/game/atoms.dm @@ -145,7 +145,7 @@ /atom/proc/try_on_reagent_change() SHOULD_NOT_OVERRIDE(TRUE) set waitfor = FALSE - if(QDELETED(src) ||_reagent_update_started >= world.time) + if(QDELETED(src) || _reagent_update_started >= world.time) return FALSE _reagent_update_started = world.time sleep(0) // Defer to end of tick so we don't drop subsequent reagent updates. diff --git a/code/game/atoms_movable.dm b/code/game/atoms_movable.dm index 73011d93026..4ba136ff11a 100644 --- a/code/game/atoms_movable.dm +++ b/code/game/atoms_movable.dm @@ -603,3 +603,5 @@ return TRUE return FALSE +/atom/movable/proc/get_cryogenic_power() + return 0 diff --git a/code/game/gamemodes/endgame/ftl_jump/ftl_jump.dm b/code/game/gamemodes/endgame/ftl_jump/ftl_jump.dm index 77f57911383..8f8d2f43e3c 100644 --- a/code/game/gamemodes/endgame/ftl_jump/ftl_jump.dm +++ b/code/game/gamemodes/endgame/ftl_jump/ftl_jump.dm @@ -53,14 +53,14 @@ if(M.client) to_chat(M,"You feel oddly light, and somewhat disoriented as everything around you shimmers and warps ever so slightly.") M.overlay_fullscreen("wormhole", /obj/screen/fullscreen/wormhole_overlay) - M.set_status(STAT_CONFUSE, 20) + M.set_status_condition(STAT_CONFUSE, 20) bluegoasts += new/obj/effect/bluegoast/(get_turf(M),M) /datum/universal_state/jump/proc/clear_duplicated(var/mob/living/M) if(M.client) to_chat(M,"You feel rooted in material world again.") M.clear_fullscreen("wormhole") - M.set_status(STAT_CONFUSE, 0) + M.set_status_condition(STAT_CONFUSE, 0) for(var/mob/goast in global.ghost_mob_list) goast.mouse_opacity = initial(goast.mouse_opacity) goast.set_invisibility(initial(goast.invisibility)) diff --git a/code/game/machinery/Sleeper.dm b/code/game/machinery/Sleeper.dm index 24e826c1739..00b91ddfdc7 100644 --- a/code/game/machinery/Sleeper.dm +++ b/code/game/machinery/Sleeper.dm @@ -42,6 +42,9 @@ add_reagent_canister(null, new /obj/item/chems/chem_disp_cartridge/antitoxins()) add_reagent_canister(null, new /obj/item/chems/chem_disp_cartridge/oxy_meds()) +/obj/machinery/sleeper/get_cryogenic_power() + return stasis + /obj/machinery/sleeper/Destroy() QDEL_NULL(beaker) QDEL_NULL_LIST(loaded_canisters) @@ -168,7 +171,7 @@ toggle_lavage() if(isliving(occupant) && stasis > 1) - occupant.set_stasis(stasis) + occupant.add_mob_modifier(/decl/mob_modifier/stasis, 2 SECONDS, source = src) /obj/machinery/sleeper/on_update_icon() cut_overlays() diff --git a/code/game/machinery/_machines_base/stock_parts/_stock_parts.dm b/code/game/machinery/_machines_base/stock_parts/_stock_parts.dm index c8fdd39f53b..38cc9bbe24d 100644 --- a/code/game/machinery/_machines_base/stock_parts/_stock_parts.dm +++ b/code/game/machinery/_machines_base/stock_parts/_stock_parts.dm @@ -15,7 +15,7 @@ return FALSE // Can potentially add uninstall code here, but not currently supported. return ..() -/obj/item/stock_parts/proc/set_status(var/obj/machinery/machine, var/flag) +/obj/item/stock_parts/proc/set_component_status(var/obj/machinery/machine, var/flag) var/old_stat = status status |= flag if(old_stat != status) @@ -34,7 +34,7 @@ machine.component_stat_change(src, old_stat, flag) /obj/item/stock_parts/proc/on_install(var/obj/machinery/machine) - set_status(machine, PART_STAT_INSTALLED) + set_component_status(machine, PART_STAT_INSTALLED) /obj/item/stock_parts/proc/on_uninstall(var/obj/machinery/machine, var/temporary = FALSE) unset_status(machine, PART_STAT_INSTALLED) @@ -48,7 +48,7 @@ if(istype(machine)) LAZYDISTINCTADD(machine.processing_parts, src) START_PROCESSING_MACHINE(machine, MACHINERY_PROCESS_COMPONENTS) - set_status(machine, PART_STAT_PROCESSING) + set_component_status(machine, PART_STAT_PROCESSING) /obj/item/stock_parts/proc/stop_processing(var/obj/machinery/machine) if(istype(machine)) diff --git a/code/game/machinery/_machines_base/stock_parts/power/battery.dm b/code/game/machinery/_machines_base/stock_parts/power/battery.dm index c78b358aea6..c3f9cadf208 100644 --- a/code/game/machinery/_machines_base/stock_parts/power/battery.dm +++ b/code/game/machinery/_machines_base/stock_parts/power/battery.dm @@ -49,7 +49,7 @@ if(istype(machine)) machine.power_change() machine.queue_icon_update() - set_status(machine, PART_STAT_CONNECTED) + set_component_status(machine, PART_STAT_CONNECTED) update_icon() return cell @@ -112,7 +112,7 @@ /obj/item/stock_parts/power/battery/can_provide_power(var/obj/machinery/machine) if(is_functional() && cell && cell.check_charge(CELLRATE * machine.get_power_usage())) machine.update_power_channel(LOCAL) - set_status(machine, PART_STAT_ACTIVE) + set_component_status(machine, PART_STAT_ACTIVE) return TRUE return FALSE diff --git a/code/game/machinery/_machines_base/stock_parts/power/terminal.dm b/code/game/machinery/_machines_base/stock_parts/power/terminal.dm index 732d90839c9..40447334b20 100644 --- a/code/game/machinery/_machines_base/stock_parts/power/terminal.dm +++ b/code/game/machinery/_machines_base/stock_parts/power/terminal.dm @@ -48,7 +48,7 @@ //Is willing to provide power if the wired contribution is nonnegligible and there is enough total local power to run the machine. /obj/item/stock_parts/power/terminal/can_provide_power(var/obj/machinery/machine) if(is_functional() && terminal && terminal.surplus() && machine.can_use_power_oneoff(machine.get_power_usage(), LOCAL) <= 0) - set_status(machine, PART_STAT_ACTIVE) + set_component_status(machine, PART_STAT_ACTIVE) machine.update_power_channel(LOCAL) return TRUE return FALSE @@ -76,7 +76,7 @@ terminal.queue_icon_update() set_extension(src, /datum/extension/event_registration/shuttle_stationary, GET_DECL(/decl/observ/moved), machine, PROC_REF(machine_moved), get_area(src)) - set_status(machine, PART_STAT_CONNECTED) + set_component_status(machine, PART_STAT_CONNECTED) start_processing(machine) /obj/item/stock_parts/power/terminal/proc/machine_moved(var/obj/machinery/machine, var/turf/old_loc, var/turf/new_loc) diff --git a/code/game/machinery/camera/camera.dm b/code/game/machinery/camera/camera.dm index 98bac3c1fd3..6f6b8ec4596 100644 --- a/code/game/machinery/camera/camera.dm +++ b/code/game/machinery/camera/camera.dm @@ -86,7 +86,7 @@ set_extension(src, /datum/extension/network_device/camera, null, null, null, TRUE, preset_channels, c_tag, cameranet_enabled, requires_connection) /obj/machinery/camera/Destroy() - set_status(0) //kick anyone viewing out + set_camera_status(0) //kick anyone viewing out return ..() /obj/machinery/camera/Process() @@ -227,7 +227,7 @@ //sparks spark_at(loc, amount=5) -/obj/machinery/camera/proc/set_status(var/newstatus, var/mob/user) +/obj/machinery/camera/proc/set_camera_status(var/newstatus, var/mob/user) if (status != newstatus && (!cut_power || status == TRUE)) status = newstatus // The only way for AI to reactivate cameras are malf abilities, this gives them different messages. @@ -337,7 +337,7 @@ ) /obj/machinery/camera/proc/toggle_status() - set_status(!status) + set_camera_status(!status) /decl/public_access/public_method/toggle_camera name = "toggle camera" diff --git a/code/game/machinery/cryopod.dm b/code/game/machinery/cryopod.dm index 1892189e038..059d35045c0 100644 --- a/code/game/machinery/cryopod.dm +++ b/code/game/machinery/cryopod.dm @@ -299,11 +299,14 @@ if (occupant && user.Adjacent(src)) . += occupant.get_examine_strings(user, distance, infix, suffix) +/obj/machinery/cryopod/get_cryogenic_power() + return applies_stasis ? 1 : 0 + //Lifted from Unity stasis.dm and refactored. /obj/machinery/cryopod/Process() if(occupant) if(applies_stasis && (world.time > time_entered + 20 SECONDS)) - occupant.set_stasis(2) + occupant.add_mob_modifier(/decl/mob_modifier/stasis, 2 SECONDS, source = src) //Allow a ten minute gap between entering the pod and actually despawning. // Only provide the gap if the occupant hasn't ghosted diff --git a/code/game/machinery/doors/airlock_interactions.dm b/code/game/machinery/doors/airlock_interactions.dm index 2ad96280a52..2406735f21a 100644 --- a/code/game/machinery/doors/airlock_interactions.dm +++ b/code/game/machinery/doors/airlock_interactions.dm @@ -59,8 +59,8 @@ for(var/i in 1 to round(crush_damage/AIRLOCK_CRUSH_INCREMENT, 1)) apply_damage(AIRLOCK_CRUSH_INCREMENT, BRUTE) - set_status(STAT_STUN, round(crush_damage / 8, 1)) - set_status(STAT_WEAK, round(crush_damage / 8, 1)) + set_status_condition(STAT_STUN, round(crush_damage / 8, 1)) + set_status_condition(STAT_WEAK, round(crush_damage / 8, 1)) var/turf/T = loc if(!istype(T)) diff --git a/code/game/machinery/jukebox.dm b/code/game/machinery/jukebox.dm index 1fb6b7666b7..1f9777dfac9 100644 --- a/code/game/machinery/jukebox.dm +++ b/code/game/machinery/jukebox.dm @@ -126,7 +126,7 @@ var/mob/living/human/H = M if(H.get_sound_volume_multiplier() < 0.2) continue - M.set_status(STAT_ASLEEP, 0) + M.set_status_condition(STAT_ASLEEP, 0) ADJ_STATUS(M, STAT_STUTTER, 20) SET_STATUS_MAX(M, STAT_DEAF, 30) SET_STATUS_MAX(M, STAT_WEAK, 3) @@ -134,7 +134,7 @@ SET_STATUS_MAX(M, STAT_STUN, 10) SET_STATUS_MAX(M, STAT_PARA, 4) else - M.set_status(STAT_JITTER, 400) + M.set_status_condition(STAT_JITTER, 400) spawn(15) explode() diff --git a/code/game/objects/auras/aura.dm b/code/game/objects/auras/aura.dm deleted file mode 100644 index 5de18f3adf6..00000000000 --- a/code/game/objects/auras/aura.dm +++ /dev/null @@ -1,58 +0,0 @@ -/*Auras are simple: They are simple overriders for attackbys, bullet_act, damage procs, etc. They also tick after their respective mob. -They should be used for undeterminate mob effects, like for instance a toggle-able forcefield, or indestructability as long as you don't move. -They should also be used for when you want to effect the ENTIRE mob, like having an armor buff or showering candy everytime you walk. -*/ - -/obj/aura - var/mob/living/user - -/obj/aura/Initialize() - . = ..() - if(isliving(loc)) - added_to(loc) - user.add_aura(src) - -/obj/aura/Destroy() - if(user) - user.remove_aura(src) - removed() - return ..() - -/obj/aura/proc/added_to(var/mob/living/target) - user = target - -/obj/aura/proc/removed() - user = null - -/obj/aura/proc/life_tick() - return 0 - -/obj/aura/attackby(var/obj/item/I, var/mob/user) - return 0 - -/obj/aura/bullet_act(var/obj/item/projectile/P, var/def_zone) - return 0 - -/obj/aura/hitby() - SHOULD_CALL_PARENT(FALSE) - return FALSE - -/obj/aura/debug - var/returning = FALSE - -/obj/aura/debug/attackby(var/obj/item/I, var/mob/user) - log_debug("Attackby for \ref[src]: [I], [user]") - return returning - -/obj/aura/debug/bullet_act(var/obj/item/projectile/P, var/def_zone) - log_debug("Bullet Act for \ref[src]: [P], [def_zone]") - return returning - -/obj/aura/debug/life_tick() - log_debug("Life tick") - return returning - -/obj/aura/debug/hitby(var/atom/movable/M, var/datum/thrownthing/TT) - SHOULD_CALL_PARENT(FALSE) - log_debug("Hit By for \ref[src]: [M], [TT.speed]") - return returning \ No newline at end of file diff --git a/code/game/objects/auras/personal_shields/personal_shield.dm b/code/game/objects/auras/personal_shields/personal_shield.dm deleted file mode 100644 index 934005ceb4f..00000000000 --- a/code/game/objects/auras/personal_shields/personal_shield.dm +++ /dev/null @@ -1,34 +0,0 @@ -/obj/aura/personal_shield - name = "personal shield" - -/obj/aura/personal_shield/added_to(var/mob/living/L) - ..() - playsound(user,'sound/weapons/flash.ogg',35,1) - to_chat(user,"You feel your body prickle as \the [src] comes online.") - -/obj/aura/personal_shield/bullet_act(var/obj/item/projectile/P, var/def_zone) - user.visible_message("\The [user]'s [src.name] flashes before \the [P] can hit them!") - new /obj/effect/temporary(get_turf(src), 2 SECONDS,'icons/obj/machines/shielding.dmi',"shield_impact") - playsound(user,'sound/effects/basscannon.ogg',35,1) - return AURA_FALSE|AURA_CANCEL - -/obj/aura/personal_shield/removed() - to_chat(user,"\The [src] goes offline!") - playsound(user,'sound/mecha/internaldmgalarm.ogg',25,1) - ..() - -/obj/aura/personal_shield/device - var/obj/item/personal_shield/shield - -/obj/aura/personal_shield/device/bullet_act() - . = ..() - if(shield) - shield.take_charge() - -/obj/aura/personal_shield/device/Initialize(mapload, var/user_shield) - . = ..() - shield = user_shield - -/obj/aura/personal_shield/device/Destroy() - shield = null - return ..() \ No newline at end of file diff --git a/code/game/objects/auras/radiant_aura.dm b/code/game/objects/auras/radiant_aura.dm deleted file mode 100644 index d25cfa807b9..00000000000 --- a/code/game/objects/auras/radiant_aura.dm +++ /dev/null @@ -1,20 +0,0 @@ -/obj/aura/radiant_aura - name = "radiant aura" - icon = 'icons/effects/effects.dmi' - icon_state = "fire_goon" - layer = ABOVE_WINDOW_LAYER - -/obj/aura/radiant_aura/added_to(var/mob/living/L) - ..() - to_chat(L,"A bubble of light appears around you, exuding protection and warmth.") - set_light(6, 6, "#e09d37") - -/obj/aura/radiant_aura/removed() - to_chat(user, "Your protective aura dissipates, leaving you feeling cold and unsafe.") - ..() - -/obj/aura/radiant_aura/bullet_act(var/obj/item/projectile/P, var/def_zone) - if(P.damage_flags() & DAM_LASER) - user.visible_message("\The [P] refracts, bending into \the [user]'s aura.") - return AURA_FALSE - return 0 diff --git a/code/game/objects/auras/regenerating_aura.dm b/code/game/objects/auras/regenerating_aura.dm deleted file mode 100644 index 7c313fc2d1c..00000000000 --- a/code/game/objects/auras/regenerating_aura.dm +++ /dev/null @@ -1,121 +0,0 @@ -/obj/aura/regenerating - name = "regenerating aura" - var/brute_mult = 1 - var/fire_mult = 1 - var/tox_mult = 1 - -/obj/aura/regenerating/life_tick() - user.heal_damage(BRUTE, brute_mult, do_update_health = FALSE) - user.heal_damage(BURN, fire_mult, do_update_health = FALSE) - user.heal_damage(TOX, tox_mult) - -/obj/aura/regenerating/human - var/nutrition_damage_mult = 1 //How much nutrition it takes to heal regular damage - var/external_nutrition_mult = 50 // How much nutrition it takes to regrow a limb - var/organ_mult = 2 - var/regen_message = "Your body throbs as you feel your ORGAN regenerate." - var/grow_chance = 0 - var/grow_threshold = 0 - var/ignore_tag = BP_BRAIN //organ tag to ignore - var/last_nutrition_warning = 0 - var/innate_heal = TRUE // Whether the aura is on, basically. - - -/obj/aura/regenerating/human/proc/external_regeneration_effect(var/obj/item/organ/external/O, var/mob/living/human/H) - return - -/obj/aura/regenerating/human/life_tick() - var/mob/living/human/H = user - if(!istype(H)) - . = 0 - CRASH("Someone gave [user.type] a [src.type] aura. This is invalid.") - if(!innate_heal || H.is_in_stasis() || H.stat == DEAD) - return 0 - if(H.nutrition < nutrition_damage_mult) - low_nut_warning() - return 0 - - var/update_health = FALSE - var/organ_regen = get_config_value(/decl/config/num/health_organ_regeneration_multiplier) - if(brute_mult && H.get_damage(BRUTE)) - update_health = TRUE - H.heal_damage(BRUTE, brute_mult * organ_regen, do_update_health = FALSE) - H.adjust_nutrition(-nutrition_damage_mult) - if(fire_mult && H.get_damage(BURN)) - update_health = TRUE - H.heal_damage(BURN, fire_mult * organ_regen, do_update_health = FALSE) - H.adjust_nutrition(-nutrition_damage_mult) - if(tox_mult && H.get_damage(TOX)) - update_health = TRUE - H.heal_damage(TOX, tox_mult * organ_regen, do_update_health = FALSE) - H.adjust_nutrition(-nutrition_damage_mult) - if(update_health) - H.update_health() - - if(!can_regenerate_organs()) - return 1 - if(organ_mult) - if(prob(10) && H.nutrition >= 150 && !H.get_damage(BRUTE) && !H.get_damage(BURN)) - var/obj/item/organ/external/D = GET_EXTERNAL_ORGAN(H, BP_HEAD) - if (D.status & ORGAN_DISFIGURED) - if (H.nutrition >= 20) - D.status &= ~ORGAN_DISFIGURED - H.adjust_nutrition(-20) - else - low_nut_warning(BP_HEAD) - - var/list/organs = H.get_internal_organs() - for(var/obj/item/organ/internal/regen_organ in shuffle(organs.Copy())) - if(BP_IS_PROSTHETIC(regen_organ) || regen_organ.organ_tag == ignore_tag) - continue - if(istype(regen_organ)) - if(regen_organ.get_organ_damage() > 0 && !(regen_organ.status & ORGAN_DEAD)) - if (H.nutrition >= organ_mult) - regen_organ.adjust_organ_damage(-(organ_mult)) - H.adjust_nutrition(-organ_mult) - if(prob(5)) - to_chat(H, replacetext(regen_message,"ORGAN", regen_organ.name)) - else - low_nut_warning(regen_organ.name) - - if(prob(grow_chance)) - var/decl/bodytype/root_bodytype = H.get_bodytype() - for(var/limb_type in root_bodytype.has_limbs) - var/obj/item/organ/external/E = GET_EXTERNAL_ORGAN(H, limb_type) - if(E && E.organ_tag != BP_HEAD && !E.is_vital_to_owner() && !E.is_usable()) //Skips heads and vital bits... - if (H.nutrition > grow_threshold) - H.remove_organ(E) //...because no one wants their head to explode to make way for a new one. - qdel(E) - E= null - else - low_nut_warning(E.name) - if(!E) - var/list/organ_data = root_bodytype.has_limbs[limb_type] - var/limb_path = organ_data["path"] - var/obj/item/organ/external/O = new limb_path(H) - external_regeneration_effect(O,H) - H.adjust_nutrition(-external_nutrition_mult) - organ_data["descriptor"] = O.name - H.update_body() - return - else if (H.nutrition > grow_threshold) //We don't subtract any nut here, but let's still only heal wounds when we have nut. - for(var/datum/wound/W in E.wounds) - if(W.wound_damage() == 0 && prob(50)) - qdel(W) - return 1 - -/obj/aura/regenerating/human/proc/low_nut_warning(var/wound_type) - if (last_nutrition_warning + 1 MINUTE < world.time) - to_chat(user, "You need more energy to regenerate your [wound_type || "wounds"].") - last_nutrition_warning = world.time - return 1 - return 0 - -/obj/aura/regenerating/human/proc/toggle() - innate_heal = !innate_heal - -/obj/aura/regenerating/human/proc/can_toggle() - return TRUE - -/obj/aura/regenerating/human/proc/can_regenerate_organs() - return TRUE diff --git a/code/game/objects/items/cryobag.dm b/code/game/objects/items/cryobag.dm index f045c550ad9..87d328458c7 100644 --- a/code/game/objects/items/cryobag.dm +++ b/code/game/objects/items/cryobag.dm @@ -14,6 +14,9 @@ ) var/stasis_power +/obj/item/bodybag/cryobag/get_cryogenic_power() + return stasis_power + /obj/item/bodybag/cryobag/attack_self(mob/user) var/obj/structure/closet/body_bag/cryobag/R = new /obj/structure/closet/body_bag/cryobag(user.loc) if(stasis_power) @@ -92,9 +95,7 @@ stasis_power = round(0.75 * stasis_power) animate(src, color = color_matrix_saturation(get_saturation()), time = 10) update_icon() - - if(LAZYACCESS(patient.stasis_sources, STASIS_CRYOBAG) != stasis_power) - patient.set_stasis(stasis_power, STASIS_CRYOBAG) + patient.add_mob_modifier(/decl/mob_modifier/stasis, 2 SECONDS, source = src) /obj/structure/closet/body_bag/cryobag/return_air() //Used to make stasis bags protect from vacuum. if(airtank) diff --git a/code/game/objects/items/devices/personal_shield.dm b/code/game/objects/items/devices/personal_shield.dm index c83b7522cc8..c88b59712e9 100644 --- a/code/game/objects/items/devices/personal_shield.dm +++ b/code/game/objects/items/devices/personal_shield.dm @@ -11,36 +11,45 @@ /decl/material/solid/metal/uranium = MATTER_AMOUNT_TRACE, ) var/uses = 5 - var/obj/aura/personal_shield/device/shield + var/shield_effect_type = /decl/mob_modifier/shield/device /obj/item/personal_shield/attack_self(var/mob/user) - if(uses && !shield) - shield = new(user,src) - else - QDEL_NULL(shield) + if(loc == user && isliving(user)) + var/mob/living/holder = user + if(holder.has_mob_modifier(shield_effect_type, source = src)) + holder.remove_mob_modifier(shield_effect_type, source = src) + else if(uses && shield_effect_type) + holder.add_mob_modifier(shield_effect_type, source = src) + else + return ..() + return TRUE + return ..() /obj/item/personal_shield/Move() - QDEL_NULL(shield) - return ..() + var/mob/living/holder = loc + . = ..() + if(. && istype(holder) && holder.has_mob_modifier(shield_effect_type, source = src)) + holder.remove_mob_modifier(shield_effect_type, source = src) /obj/item/personal_shield/forceMove() - QDEL_NULL(shield) - return ..() + var/mob/living/holder = loc + . = ..() + if(. && istype(holder) && holder.has_mob_modifier(shield_effect_type, source = src)) + holder.remove_mob_modifier(shield_effect_type, source = src) -/obj/item/personal_shield/proc/take_charge() - if(!--uses) - QDEL_NULL(shield) - to_chat(loc,"\The [src] begins to spark as it breaks!") +/obj/item/personal_shield/proc/expend_charge() + if(uses <= 0) + return FALSE + uses-- + if(uses <= 0 && ismob(loc)) + var/mob/living/holder = loc + if(istype(holder) && holder.has_mob_modifier(shield_effect_type, source = src)) + holder.remove_mob_modifier(shield_effect_type, source = src) + to_chat(holder, SPAN_DANGER("\The [src] begins to spark as it breaks!")) update_icon() - return + return TRUE /obj/item/personal_shield/on_update_icon() . = ..() if(uses) - icon_state = "batterer" - else - icon_state = "battererburnt" - -/obj/item/personal_shield/Destroy() - QDEL_NULL(shield) - return ..() \ No newline at end of file + add_overlay("[icon_state]-on") \ No newline at end of file diff --git a/code/game/objects/items/robot/robot_items.dm b/code/game/objects/items/robot/robot_items.dm index 16d7f1eddcd..cbe87ec2d29 100644 --- a/code/game/objects/items/robot/robot_items.dm +++ b/code/game/objects/items/robot/robot_items.dm @@ -7,15 +7,15 @@ ***********************************************************************/ /obj/item/borg/overdrive name = "overdrive" - icon = 'icons/obj/decals.dmi' + icon = 'icons/obj/signs/warnings.dmi' icon_state = "shock" /********************************************************************** HUD/SIGHT things ***********************************************************************/ /obj/item/borg/sight - icon = 'icons/obj/decals.dmi' - icon_state = "securearea" + icon = 'icons/obj/signs/warnings.dmi' + icon_state = "secureareaold" var/sight_mode = null var/glasses_hud_type diff --git a/code/game/objects/items/weapons/stunbaton.dm b/code/game/objects/items/weapons/stunbaton.dm index 4a176ec5298..7b661c24a28 100644 --- a/code/game/objects/items/weapons/stunbaton.dm +++ b/code/game/objects/items/weapons/stunbaton.dm @@ -35,7 +35,7 @@ /obj/item/baton/infinite/Initialize(var/ml, var/material_key, var/loaded_cell_type) . = ..(ml, material_key, loaded_cell_type = /obj/item/cell/device/infinite) - set_status(1, null) + set_cell_status(1, null) /obj/item/baton/proc/update_status() var/obj/item/cell/cell = get_cell() @@ -66,10 +66,10 @@ set_light(0) /obj/item/baton/attack_self(mob/user) - set_status(!status, user) + set_cell_status(!status, user) add_fingerprint(user) -/obj/item/baton/proc/set_status(var/newstatus, mob/user) +/obj/item/baton/proc/set_cell_status(var/newstatus, mob/user) var/obj/item/cell/cell = get_cell() if(cell?.charge >= hitcost) if(status != newstatus) diff --git a/code/game/objects/structures/mineral_bath.dm b/code/game/objects/structures/mineral_bath.dm index 3180e095a76..0129a5e61f7 100644 --- a/code/game/objects/structures/mineral_bath.dm +++ b/code/game/objects/structures/mineral_bath.dm @@ -108,18 +108,17 @@ if(occupant.has_body_flag(BODY_FLAG_CRYSTAL_REFORM) && prob(10)) var/decl/bodytype/root_bodytype = occupant.get_bodytype() for(var/limb_type in root_bodytype.has_limbs) - var/obj/item/organ/external/E = GET_EXTERNAL_ORGAN(occupant, limb_type) - if(E && !E.is_usable() && !(E.limb_flags & ORGAN_FLAG_HEALS_OVERKILL)) - occupant.remove_organ(E) - qdel(E) - E = null - if(!E) + var/obj/item/organ/external/limb = GET_EXTERNAL_ORGAN(occupant, limb_type) + if(limb && !limb.is_usable() && !(limb.limb_flags & ORGAN_FLAG_HEALS_OVERKILL)) + occupant.remove_organ(limb) + qdel(limb) + limb = null + if(!limb) var/list/organ_data = root_bodytype.has_limbs[limb_type] var/limb_path = organ_data["path"] - E = new limb_path(occupant) - organ_data["descriptor"] = E.name - to_chat(occupant, SPAN_NOTICE("You feel your [E.name] reform in the crystal bath.")) - occupant.update_body() + limb = new limb_path(occupant) + occupant.add_organ(limb, GET_EXTERNAL_ORGAN(occupant, limb.parent_organ), FALSE, FALSE) + to_chat(occupant, SPAN_NOTICE("You feel your [limb.name] reform in the crystal bath.")) repaired_organ = TRUE break @@ -133,18 +132,18 @@ // Repair robotic external organs. if(!repaired_organ && prob(25)) - for(var/obj/item/organ/external/E in occupant.get_external_organs()) - if(BP_IS_PROSTHETIC(E)) - for(var/obj/implanted_object in E.implants) + for(var/obj/item/organ/external/limb in occupant.get_external_organs()) + if(BP_IS_PROSTHETIC(limb)) + for(var/obj/implanted_object in limb.implants) if(!istype(implanted_object,/obj/item/implant) && !istype(implanted_object,/obj/item/organ/internal/augment) && prob(25)) // We don't want to remove REAL implants. Just shrapnel etc. - LAZYREMOVE(E.implants, implanted_object) + LAZYREMOVE(limb.implants, implanted_object) to_chat(occupant, SPAN_NOTICE("The mineral-rich bath dissolves the [implanted_object.name].")) qdel(implanted_object) - if(E.brute_dam || E.burn_dam) - E.heal_damage(rand(3,5), rand(3,5), robo_repair = 1) + if(limb.brute_dam || limb.burn_dam) + limb.heal_damage(rand(3,5), rand(3,5), robo_repair = 1) if(prob(25)) - to_chat(occupant, SPAN_NOTICE("The mineral-rich bath mends your [E.name].")) - if(!BP_IS_CRYSTAL(E) && !BP_IS_BRITTLE(E)) - E.status |= ORGAN_BRITTLE + to_chat(occupant, SPAN_NOTICE("The mineral-rich bath mends your [limb.name].")) + if(!BP_IS_CRYSTAL(limb) && !BP_IS_BRITTLE(limb)) + limb.status |= ORGAN_BRITTLE to_chat(occupant, SPAN_WARNING("It feels a bit brittle, though...")) break diff --git a/code/game/objects/structures/signs.dm b/code/game/objects/structures/signs.dm index d5fcfd51455..22861d9d861 100644 --- a/code/game/objects/structures/signs.dm +++ b/code/game/objects/structures/signs.dm @@ -87,7 +87,7 @@ ///A wall mountable sign structure /obj/structure/sign name = "sign" - icon = 'icons/obj/decals.dmi' + icon = 'icons/obj/signs/warnings.dmi' anchored = TRUE opacity = FALSE density = FALSE diff --git a/code/modules/abstract/_abstract.dm b/code/modules/abstract/_abstract.dm index 11d081248ec..9f944be9cb3 100644 --- a/code/modules/abstract/_abstract.dm +++ b/code/modules/abstract/_abstract.dm @@ -1,20 +1,22 @@ /obj/abstract - name = "" - icon = 'icons/effects/landmarks.dmi' - icon_state = "x2" - simulated = FALSE - density = FALSE - anchored = TRUE - abstract_type = /obj/abstract - invisibility = INVISIBILITY_ABSTRACT + name = "" + icon = 'icons/effects/landmarks.dmi' + icon_state = "x2" + simulated = FALSE + density = FALSE + anchored = TRUE + abstract_type = /obj/abstract + invisibility = INVISIBILITY_ABSTRACT + var/hide_on_init = TRUE /obj/abstract/Initialize() . = ..() verbs.Cut() - //Let mappers see the damn thing by just making them invisible here opacity = FALSE - alpha = 0 - mouse_opacity = MOUSE_OPACITY_UNCLICKABLE + //Let mappers see the damn thing by just making them invisible here + if(hide_on_init) + alpha = 0 + mouse_opacity = MOUSE_OPACITY_UNCLICKABLE /obj/abstract/explosion_act() SHOULD_CALL_PARENT(FALSE) diff --git a/code/modules/abstract/follower.dm b/code/modules/abstract/follower.dm new file mode 100644 index 00000000000..42611d1131d --- /dev/null +++ b/code/modules/abstract/follower.dm @@ -0,0 +1,18 @@ +// Simple obj for following another obj around (for light effects or such that need a physical reference) +/obj/abstract/follower + anchored = TRUE + simulated = FALSE + invisibility = INVISIBILITY_ABSTRACT + +/obj/abstract/follower/Initialize() + . = ..() + name = "" + verbs.Cut() + +/obj/abstract/follower/proc/follow_owner(atom/movable/owner) + if(istype(owner) && !QDELETED(owner)) + set_dir(owner.dir) + if(owner.loc) + forceMove(owner.loc) + else + forceMove(null) diff --git a/code/modules/admin/admin.dm b/code/modules/admin/admin.dm index c211f274d60..9594f9dd3dd 100644 --- a/code/modules/admin/admin.dm +++ b/code/modules/admin/admin.dm @@ -1415,10 +1415,10 @@ var/global/BSACooldown = 0 SPAN_OCCULT("OOC: \The [M] has been paralyzed by a staff member. Please hold all interactions with them until staff have finished with them."), SPAN_OCCULT("OOC: You have been paralyzed by a staff member. Please refer to your currently open admin help ticket or, if you don't have one, admin help for assistance.") ) - M.set_status(STAT_PARA, 8000) + M.set_status_condition(STAT_PARA, 8000) M.admin_paralyzed = TRUE else - M.set_status(STAT_PARA, 0) + M.set_status_condition(STAT_PARA, 0) M.admin_paralyzed = FALSE M.visible_message(SPAN_OCCULT("OOC: \The [M] has been released from paralysis by staff. You may resume interactions with them.")) to_chat(M, SPAN_OCCULT("OOC: You have been released from paralysis by staff and can return to your game.")) diff --git a/code/modules/admin/topic.dm b/code/modules/admin/topic.dm index c9e2798773b..45976fa2381 100644 --- a/code/modules/admin/topic.dm +++ b/code/modules/admin/topic.dm @@ -992,7 +992,7 @@ M.take_damage(min(99, M.current_health - 1)) SET_STATUS_MAX(M, STAT_STUN, 20) SET_STATUS_MAX(M, STAT_WEAK, 20) - M.set_status(STAT_STUTTER, 20) + M.set_status_condition(STAT_STUTTER, 20) else if(href_list["CentcommReply"]) var/mob/living/L = locate(href_list["CentcommReply"]) diff --git a/code/modules/admin/view_variables/helpers.dm b/code/modules/admin/view_variables/helpers.dm index 7b7155b8391..77e8826c5a9 100644 --- a/code/modules/admin/view_variables/helpers.dm +++ b/code/modules/admin/view_variables/helpers.dm @@ -62,8 +62,8 @@ /mob/living/get_view_variables_options() return ..() + {" - - + + diff --git a/code/modules/admin/view_variables/topic.dm b/code/modules/admin/view_variables/topic.dm index 971e7a394bc..114f3bd5510 100644 --- a/code/modules/admin/view_variables/topic.dm +++ b/code/modules/admin/view_variables/topic.dm @@ -590,26 +590,6 @@ var/datum/called_proc = locate(href_list["call_proc"]) if(istype(called_proc) || istype(called_proc, /client)) // can call on clients too, not just datums callproc_targetpicked(1, called_proc) - else if(href_list["addaura"]) - if(!check_rights(R_DEBUG|R_ADMIN|R_FUN)) return - var/mob/living/victim = locate(href_list["addaura"]) - if(!istype(victim)) - return - var/choice = input("Please choose an aura to add", "Auras", null) as null|anything in typesof(/obj/aura) - if(!choice || !victim) - return - var/obj/new_aura = new choice(victim) - log_and_message_admins("added \the [new_aura] to \the [victim]") - else if(href_list["removeaura"]) - if(!check_rights(R_DEBUG|R_ADMIN|R_FUN)) return - var/mob/living/victim = locate(href_list["removeaura"]) - if(!istype(victim)) - return - var/choice = input("Please choose an aura to remove", "Auras", null) as null|anything in victim.auras - if(!choice || !victim) - return - log_and_message_admins("removed \the [choice] to \the [victim]") - qdel(choice) else if(href_list["addstressor"]) if(!check_rights(R_DEBUG)) @@ -658,7 +638,7 @@ return if(amt < 0) amt += GET_STATUS(victim, selected_condition.type) - victim.set_status(selected_condition.type, amt) + victim.set_status_condition(selected_condition.type, amt) log_and_message_admins("set [selected_condition.name] to [amt] on \the [victim].") else if(href_list["setmaterial"]) @@ -705,6 +685,44 @@ else to_chat(usr, SPAN_WARNING("Failed to remove [ability] from [target]!")) + else if (href_list["add_mob_modifier"]) + var/mob/living/target = locate(href_list["add_mob_modifier"]) + if(!istype(target) || QDELETED(target)) + to_chat(usr, SPAN_WARNING("Only /mob/living mobs can have mob modifiers.")) + else + var/list/modifiers = list() + for(var/decl/mob_modifier/modifier in decls_repository.get_decls_of_type_unassociated(/decl/mob_modifier)) + if(modifier.can_be_admin_granted) + modifiers += modifier + // Evil pyramid due to apparently not being able to return early in this Topic() + var/decl/mob_modifier/modifier = input(usr, "Which modifier do you wish to give?", "Add Mob Modifier") as null|anything in modifiers + if(istype(modifier) && !QDELETED(target)) + var/duration = input(usr, "How long do you wish this modifier to last, in seconds? Enter -1 for a permanent modifier.", "Add Mob Modifier") as num|null + if(!isnull(duration)) + if(duration != MOB_MODIFIER_INDEFINITE) + duration = max(0, duration SECONDS) + if(duration != 0 && !QDELETED(target)) + if(target.add_mob_modifier(modifier, duration, source = target)) + to_chat(usr, SPAN_NOTICE("Added [modifier] to [target] for [duration] second\s.")) + else + to_chat(usr, SPAN_WARNING("Failed to add [modifier] to [target].")) + + else if (href_list["remove_mob_modifier"]) + var/mob/living/target = locate(href_list["remove_mob_modifier"]) + if(!istype(target) && !QDELETED(target)) + to_chat(usr, SPAN_WARNING("Only /mob/living mobs can have mob modifiers.")) + else + var/list/modifiers = list() + for(var/decl/mob_modifier/modifier in target._mob_modifiers) + if(modifier.can_be_admin_granted) + modifiers += modifier + var/decl/mob_modifier/modifier = input(usr, "Which modifier do you wish to remove?", "Remove Mob Modifier") as null|anything in modifiers + if(istype(modifier)) + if(target.remove_mob_modifier(modifier, source = target)) + to_chat(usr, SPAN_NOTICE("Removed [modifier] from [target].")) + else + to_chat(usr, SPAN_WARNING("Failed to remove [modifier] from [target].")) + if(href_list["datumrefresh"]) var/datum/datum_to_refresh = locate(href_list["datumrefresh"]) if(istype(datum_to_refresh, /datum) || istype(datum_to_refresh, /client)) diff --git a/code/modules/augment/passive/nanoaura.dm b/code/modules/augment/passive/nanoaura.dm index b18920b72e8..751ed5541ab 100644 --- a/code/modules/augment/passive/nanoaura.dm +++ b/code/modules/augment/passive/nanoaura.dm @@ -1,13 +1,3 @@ -//This handy augment protects you to a degree, keeping it online after critical damage however is bad - -/obj/aura/nanoaura - name = "Nanoaura" - var/obj/item/organ/internal/augment/active/nanounit/unit = null - var/active = 0 - - -//The organ itself - /obj/item/organ/internal/augment/active/nanounit name = "nanite MCU" allowed_organs = list(BP_AUGMENT_CHEST_ACTIVE) @@ -16,7 +6,8 @@ action_button_name = "Toggle Nanomachines" material = /decl/material/solid/metal/steel origin_tech = @'{"materials":4,"magnets":4,"engineering":5,"biotech":3}' - var/obj/aura/nanoaura/aura = null + var/active = FALSE + var/modifier_archetype = /decl/mob_modifier/nanoswarm var/charges = 4 /obj/item/organ/internal/augment/active/nanounit/reset_matter() @@ -28,58 +19,39 @@ /obj/item/organ/internal/augment/active/nanounit/on_add_effects() . = ..() - if(owner) - aura = new /obj/aura/nanoaura(owner, src) + if(owner && modifier_archetype) + owner.add_mob_modifier(modifier_archetype, source = src) /obj/item/organ/internal/augment/active/nanounit/on_remove_effects(mob/living/last_owner) - QDEL_NULL(aura) + if(istype(last_owner) && modifier_archetype) + last_owner.remove_mob_modifier(modifier_archetype, source = src) . = ..() /obj/item/organ/internal/augment/active/nanounit/proc/catastrophic_failure() playsound(owner,'sound/mecha/internaldmgalarm.ogg',25,1) + charges = -1 + active = FALSE owner.visible_message(SPAN_WARNING("The nanites attempt to harden. But they seem... brittle.")) for(var/obj/item/organ/external/E in owner.get_external_organs()) if(prob(25)) E.status |= ORGAN_BRITTLE //Some nanites are not responding and you're out of luck to_chat(owner, SPAN_DANGER("Your [E.name] feels cold and rigid.")) - QDEL_NULL(aura) + owner.remove_mob_modifier(modifier_archetype, source = src) /obj/item/organ/internal/augment/active/nanounit/activate() - if(!aura || !can_activate()) + if(!owner || !modifier_archetype || !can_activate()) return - if(aura.active) - aura.active = 0 + if(owner.has_mob_modifier(modifier_archetype, source = src)) + active = FALSE to_chat(owner,SPAN_NOTICE("Nanites entering sleep mode.")) - else - aura.active = 1 + owner.remove_mob_modifier(modifier_archetype, source = src) + else if(charges > 0) to_chat(owner,SPAN_NOTICE("Activation sequence in progress.")) + active = TRUE + owner.add_mob_modifier(modifier_archetype, source = src) playsound(owner,'sound/weapons/flash.ogg',35,1) - /obj/item/organ/internal/augment/active/nanounit/Destroy() + if(owner && modifier_archetype) + owner.remove_mob_modifier(modifier_archetype, source = src) . = ..() - QDEL_NULL(aura) - -/obj/aura/nanoaura/Initialize(var/maploading, var/obj/item/organ/internal/augment/active/nanounit/holder) - . = ..() - unit = holder - playsound(loc,'sound/weapons/flash.ogg',35,1) - to_chat(loc,SPAN_NOTICE("Your skin tingles as the nanites spread over your body.")) - -/obj/aura/nanoaura/bullet_act(var/obj/item/projectile/P, var/def_zone) - if(!active) - return - if(unit.charges > 0) - user.visible_message(SPAN_WARNING("The nanomachines harden as a response to physical trauma!")) - playsound(user,'sound/effects/basscannon.ogg',35,1) - unit.charges -= 1 - if(unit.charges <= 0) - to_chat(user, SPAN_DANGER("Warning: Critical damage threshold passed. Shut down unit to avoid further damage.")) - return AURA_FALSE|AURA_CANCEL - else unit.catastrophic_failure() - - -/obj/aura/nanoaura/Destroy() - to_chat(user, SPAN_WARNING("The nanites dissolve!")) - unit = null - return ..() diff --git a/code/modules/client/ui_styles/_ui_style.dm b/code/modules/client/ui_styles/_ui_style.dm index 808709107dc..a1a4664efe0 100644 --- a/code/modules/client/ui_styles/_ui_style.dm +++ b/code/modules/client/ui_styles/_ui_style.dm @@ -29,7 +29,8 @@ (HUD_UP_HINT) = 'icons/mob/screen/styles/midnight/uphint.dmi', (HUD_ZONE_SELECT) = 'icons/mob/screen/styles/midnight/zone_selector.dmi', (HUD_CHARGE) = 'icons/mob/screen/styles/charge.dmi', - (HUD_INTENT) = 'icons/screen/intents.dmi' + (HUD_INTENT) = 'icons/screen/intents.dmi', + (HUD_MODIFIERS) = 'icons/mob/screen/styles/midnight/modifiers.dmi' ) /// A subset of UI keys to icon files used to override the above. var/list/override_icons diff --git a/code/modules/client/ui_styles/_ui_style_states.dm b/code/modules/client/ui_styles/_ui_style_states.dm index 95f6558e61a..6a060e6dbde 100644 --- a/code/modules/client/ui_styles/_ui_style_states.dm +++ b/code/modules/client/ui_styles/_ui_style_states.dm @@ -20,7 +20,8 @@ var/global/list/_ui_all_keys = list( (HUD_CHARGE), (HUD_THROW), (HUD_MANEUVER), - (HUD_INTENT) + (HUD_INTENT), + (HUD_MODIFIERS) ) var/global/list/_ui_expected_states @@ -175,6 +176,10 @@ var/global/list/_ui_expected_states (HUD_THROW) = list( "act_throw_on", "act_throw_off" + ), + (HUD_MODIFIERS) = list( + "blank", + "modifier_base" ) ) diff --git a/code/modules/client/ui_styles/ui_style_subtypes.dm b/code/modules/client/ui_styles/ui_style_subtypes.dm index 7de6cc1183c..e37aef4a9ab 100644 --- a/code/modules/client/ui_styles/ui_style_subtypes.dm +++ b/code/modules/client/ui_styles/ui_style_subtypes.dm @@ -17,7 +17,8 @@ (HUD_INVENTORY) = 'icons/mob/screen/styles/orange/inventory.dmi', (HUD_MOVEMENT) = 'icons/mob/screen/styles/orange/movement.dmi', (HUD_UP_HINT) = 'icons/mob/screen/styles/orange/uphint.dmi', - (HUD_ZONE_SELECT) = 'icons/mob/screen/styles/orange/zone_selector.dmi' + (HUD_ZONE_SELECT) = 'icons/mob/screen/styles/orange/zone_selector.dmi', + (HUD_MODIFIERS) = 'icons/mob/screen/styles/orange/modifiers.dmi' ) /decl/ui_style/old @@ -34,7 +35,8 @@ (HUD_INVENTORY) = 'icons/mob/screen/styles/old/inventory.dmi', (HUD_MOVEMENT) = 'icons/mob/screen/styles/old/movement.dmi', (HUD_UP_HINT) = 'icons/mob/screen/styles/old/uphint.dmi', - (HUD_ZONE_SELECT) = 'icons/mob/screen/styles/old/zone_selector.dmi' + (HUD_ZONE_SELECT) = 'icons/mob/screen/styles/old/zone_selector.dmi', + (HUD_MODIFIERS) = 'icons/mob/screen/styles/old/modifiers.dmi' ) /decl/ui_style/old_noborder @@ -51,7 +53,8 @@ (HUD_INVENTORY) = 'icons/mob/screen/styles/old_noborder/inventory.dmi', (HUD_MOVEMENT) = 'icons/mob/screen/styles/old/movement.dmi', (HUD_UP_HINT) = 'icons/mob/screen/styles/old_noborder/uphint.dmi', - (HUD_ZONE_SELECT) = 'icons/mob/screen/styles/old_noborder/zone_selector.dmi' + (HUD_ZONE_SELECT) = 'icons/mob/screen/styles/old_noborder/zone_selector.dmi', + (HUD_MODIFIERS) = 'icons/mob/screen/styles/old_noborder/modifiers.dmi' ) /decl/ui_style/white @@ -68,7 +71,8 @@ (HUD_INVENTORY) = 'icons/mob/screen/styles/white/inventory.dmi', (HUD_MOVEMENT) = 'icons/mob/screen/styles/white/movement.dmi', (HUD_UP_HINT) = 'icons/mob/screen/styles/white/uphint.dmi', - (HUD_ZONE_SELECT) = 'icons/mob/screen/styles/white/zone_selector.dmi' + (HUD_ZONE_SELECT) = 'icons/mob/screen/styles/white/zone_selector.dmi', + (HUD_MODIFIERS) = 'icons/mob/screen/styles/white/modifiers.dmi' ) use_overlay_color = TRUE use_ui_color = TRUE @@ -87,7 +91,8 @@ (HUD_INVENTORY) = 'icons/mob/screen/styles/minimalist/inventory.dmi', (HUD_MOVEMENT) = 'icons/mob/screen/styles/minimalist/movement.dmi', (HUD_UP_HINT) = 'icons/mob/screen/styles/minimalist/uphint.dmi', - (HUD_ZONE_SELECT) = 'icons/mob/screen/styles/minimalist/zone_selector.dmi' + (HUD_ZONE_SELECT) = 'icons/mob/screen/styles/minimalist/zone_selector.dmi', + (HUD_MODIFIERS) = 'icons/mob/screen/styles/minimalist/modifiers.dmi' ) use_overlay_color = TRUE use_ui_color = TRUE @@ -106,7 +111,8 @@ (HUD_INVENTORY) = 'icons/mob/screen/styles/underworld/inventory.dmi', (HUD_MOVEMENT) = 'icons/mob/screen/styles/underworld/movement.dmi', (HUD_UP_HINT) = 'icons/mob/screen/styles/underworld/uphint.dmi', - (HUD_ZONE_SELECT) = 'icons/mob/screen/styles/underworld/zone_selector.dmi' + (HUD_ZONE_SELECT) = 'icons/mob/screen/styles/underworld/zone_selector.dmi', + (HUD_MODIFIERS) = 'icons/mob/screen/styles/underworld/modifiers.dmi' ) use_overlay_color = TRUE use_ui_color = TRUE diff --git a/code/modules/clothing/_clothing.dm b/code/modules/clothing/_clothing.dm index 64d08080a01..588c193fbd9 100644 --- a/code/modules/clothing/_clothing.dm +++ b/code/modules/clothing/_clothing.dm @@ -71,7 +71,7 @@ /obj/item/clothing/Destroy() if(is_accessory()) - on_removed() + on_accessory_removed() return ..() /obj/item/clothing/get_fallback_slot(slot) diff --git a/code/modules/clothing/_clothing_accessories.dm b/code/modules/clothing/_clothing_accessories.dm index 0469f605d01..d958fc571e7 100644 --- a/code/modules/clothing/_clothing_accessories.dm +++ b/code/modules/clothing/_clothing_accessories.dm @@ -91,7 +91,7 @@ /obj/item/clothing/proc/remove_accessory(mob/user, obj/item/clothing/accessory) if(!accessory || !(accessory in accessories) || !accessory.accessory_removable || !accessory.canremove) return - accessory.on_removed(user) + accessory.on_accessory_removed(user) update_icon() /obj/item/clothing/proc/removetie_verb() @@ -178,7 +178,7 @@ return TRUE return FALSE -/obj/item/clothing/proc/on_removed(var/mob/user) +/obj/item/clothing/proc/on_accessory_removed(var/mob/user) var/obj/item/clothing/holder = loc if(istype(holder)) if(user) diff --git a/code/modules/clothing/gloves/jewelry/rings/ring_aura.dm b/code/modules/clothing/gloves/jewelry/rings/ring_aura.dm deleted file mode 100644 index 2a6c167d7fe..00000000000 --- a/code/modules/clothing/gloves/jewelry/rings/ring_aura.dm +++ /dev/null @@ -1,29 +0,0 @@ -/obj/item/clothing/gloves/ring/aura_ring - icon = 'icons/clothing/accessories/jewelry/rings/ring_band_thick.dmi' - can_inscribe = FALSE - material = /decl/material/solid/metal/silver - abstract_type = /obj/item/clothing/gloves/ring/aura_ring - material_alteration = MAT_FLAG_ALTERATION_COLOR - var/obj/aura/granted_aura - -/obj/item/clothing/gloves/ring/aura_ring/update_name() - return - -/obj/item/clothing/gloves/ring/aura_ring/Initialize() - if(ispath(granted_aura)) - granted_aura = new granted_aura - . = ..() - -/obj/item/clothing/gloves/ring/aura_ring/Destroy() - QDEL_NULL(granted_aura) - . = ..() - -/obj/item/clothing/gloves/ring/aura_ring/equipped(var/mob/living/L, var/slot) - ..() - if(istype(granted_aura) && slot == slot_gloves_str) - L.add_aura(granted_aura) - -/obj/item/clothing/gloves/ring/aura_ring/dropped(var/mob/living/L) - ..() - if(istype(granted_aura)) - L.remove_aura(granted_aura) diff --git a/code/modules/clothing/gloves/jewelry/rings/ring_effect.dm b/code/modules/clothing/gloves/jewelry/rings/ring_effect.dm new file mode 100644 index 00000000000..cf46a141cce --- /dev/null +++ b/code/modules/clothing/gloves/jewelry/rings/ring_effect.dm @@ -0,0 +1,18 @@ +/obj/item/clothing/gloves/ring/effect + icon = 'icons/clothing/accessories/jewelry/rings/ring_band_thick.dmi' + can_inscribe = FALSE + material = /decl/material/solid/metal/silver + abstract_type = /obj/item/clothing/gloves/ring/effect + material_alteration = MAT_FLAG_ALTERATION_COLOR + var/granted_effect + +/obj/item/clothing/gloves/ring/effect/update_name() + return + +/obj/item/clothing/gloves/ring/effect/Initialize() + if(granted_effect) + add_item_effect(granted_effect, list( + (IE_CAT_EXAMINE), + (IE_CAT_WIELDED) + )) + . = ..() diff --git a/code/modules/clothing/head/fated_key.dm b/code/modules/clothing/head/fated_key.dm index 626126d50c9..7b0052e2238 100644 --- a/code/modules/clothing/head/fated_key.dm +++ b/code/modules/clothing/head/fated_key.dm @@ -26,7 +26,7 @@ if(istype(starbearer) && !canremove) name = "halo of starfire" desc = "Beware the fire of the star-bearers; it is too terrible to touch." - starbearer.add_aura(new /obj/aura/regenerating(starbearer)) + starbearer.add_mob_modifier(/decl/mob_modifier/regeneration, source = src) body_parts_covered = SLOT_UPPER_BODY|SLOT_LOWER_BODY|SLOT_LEGS|SLOT_ARMS|SLOT_HEAD|SLOT_FACE|SLOT_EYES|SLOT_HANDS|SLOT_FEET|SLOT_TAIL item_flags |= ITEM_FLAG_AIRTIGHT diff --git a/code/modules/clothing/sensors/vitals_sensor.dm b/code/modules/clothing/sensors/vitals_sensor.dm index 706d9b99dd2..396dc1dfc18 100644 --- a/code/modules/clothing/sensors/vitals_sensor.dm +++ b/code/modules/clothing/sensors/vitals_sensor.dm @@ -44,7 +44,7 @@ . = ..() update_removable() -/obj/item/clothing/sensor/vitals/on_removed(mob/user) +/obj/item/clothing/sensor/vitals/on_accessory_removed(mob/user) . = ..() update_removable() diff --git a/code/modules/clothing/spacesuits/rig/modules/infiltration.dm b/code/modules/clothing/spacesuits/rig/modules/infiltration.dm index 59df2f32fcb..0fe76208c17 100644 --- a/code/modules/clothing/spacesuits/rig/modules/infiltration.dm +++ b/code/modules/clothing/spacesuits/rig/modules/infiltration.dm @@ -46,7 +46,7 @@ var/mob/living/human/H = holder.wearer - if(H.add_cloaking_source(src)) + if(H.add_mob_modifier(/decl/mob_modifier/cloaked, source = src)) anim(H, 'icons/effects/effects.dmi', "electricity",null,20,null) /obj/item/rig_module/stealth_field/deactivate() @@ -56,7 +56,7 @@ var/mob/living/human/H = holder.wearer - if(H.remove_cloaking_source(src)) + if(H.remove_mob_modifier(/decl/mob_modifier/cloaked, source = src)) anim(H,'icons/mob/mob.dmi',,"uncloak",,H.dir) anim(H, 'icons/effects/effects.dmi', "electricity",null,20,null) diff --git a/code/modules/clothing/spacesuits/rig/rig.dm b/code/modules/clothing/spacesuits/rig/rig.dm index 0eeb19c3a57..a132830f78d 100644 --- a/code/modules/clothing/spacesuits/rig/rig.dm +++ b/code/modules/clothing/spacesuits/rig/rig.dm @@ -565,7 +565,7 @@ for(var/obj/item/thing in list(chest, boots, gloves, helmet)) thing.update_icon() - if(equipment_overlay_icon && LAZYLEN(installed_modules)) + if(equipment_overlay_icon && LAZYLEN(installed_modules) && istype(chest, /obj/item)) for(var/obj/item/rig_module/module in installed_modules) if(module.suit_overlay) chest.add_overlay(image("icon" = equipment_overlay_icon, "icon_state" = "[module.suit_overlay]", "dir" = SOUTH)) diff --git a/code/modules/clothing/spacesuits/spacesuits.dm b/code/modules/clothing/spacesuits/spacesuits.dm index 95b0612b4f9..bf3381bca6e 100644 --- a/code/modules/clothing/spacesuits/spacesuits.dm +++ b/code/modules/clothing/spacesuits/spacesuits.dm @@ -60,10 +60,10 @@ if(ispath(camera)) camera = new camera(src) - camera.set_status(0) + camera.set_camera_status(0) if(camera) - camera.set_status(!camera.status) + camera.set_camera_status(!camera.status) if(camera.status) camera.c_tag = user.get_id_name() to_chat(user, "User scanned as [camera.c_tag]. Camera activated.") diff --git a/code/modules/clothing/webbing/holster.dm b/code/modules/clothing/webbing/holster.dm index c607d16c13e..9269f35844e 100644 --- a/code/modules/clothing/webbing/holster.dm +++ b/code/modules/clothing/webbing/holster.dm @@ -36,7 +36,7 @@ if(istype(holder)) holder.verbs |= /atom/proc/holster_verb -/obj/item/clothing/webbing/holster/on_removed(mob/user) +/obj/item/clothing/webbing/holster/on_accessory_removed(mob/user) var/obj/item/clothing/holder = loc if(istype(holder)) var/remove_verb = TRUE diff --git a/code/modules/events/ailments.dm b/code/modules/events/ailments.dm index a1d6fc894e8..cf49cd2110d 100644 --- a/code/modules/events/ailments.dm +++ b/code/modules/events/ailments.dm @@ -1,7 +1,7 @@ /datum/event/ailments/start() var/list/candidates = list() for(var/mob/living/human/H in global.living_mob_list_) - if(H.client && !length(H.stasis_sources)) + if(H.client && !H.has_mob_modifier(/decl/mob_modifier/stasis)) candidates += H if(!length(candidates)) return diff --git a/code/modules/hydroponics/seed_mobs.dm b/code/modules/hydroponics/seed_mobs.dm index 852c7eaae74..6f12b930e6e 100644 --- a/code/modules/hydroponics/seed_mobs.dm +++ b/code/modules/hydroponics/seed_mobs.dm @@ -7,7 +7,7 @@ spawn(15 SECONDS) if(!host.ckey && !host.client) - host.death() // This seems redundant, but a lot of mobs don't + host.death() // This seems redundant, but a lot of mobs don't host.set_stat(DEAD) // handle death() properly. Better safe than etc. host.visible_message("\The [host] is malformed and unable to survive. It expires pitifully, leaving behind some seeds.") diff --git a/code/modules/implants/implant_types/adrenaline.dm b/code/modules/implants/implant_types/adrenaline.dm index e93b99158db..ec6f6166e42 100644 --- a/code/modules/implants/implant_types/adrenaline.dm +++ b/code/modules/implants/implant_types/adrenaline.dm @@ -26,9 +26,9 @@ uses-- to_chat(imp_in, "You feel a sudden surge of energy!") - imp_in.set_status(STAT_STUN, 0) - imp_in.set_status(STAT_WEAK, 0) - imp_in.set_status(STAT_PARA, 0) + imp_in.set_status_condition(STAT_STUN, 0) + imp_in.set_status_condition(STAT_WEAK, 0) + imp_in.set_status_condition(STAT_PARA, 0) /obj/item/implant/adrenalin/implanted(mob/source) source.StoreMemory("\A [src] can be activated by using the pale emote, say *pale to attempt to activate.", /decl/memory_options/system) diff --git a/code/modules/item_effects/item_effect_aura.dm b/code/modules/item_effects/item_effect_aura.dm deleted file mode 100644 index c30e3a36461..00000000000 --- a/code/modules/item_effects/item_effect_aura.dm +++ /dev/null @@ -1,28 +0,0 @@ -/decl/item_effect/aura - abstract_type = /decl/item_effect/aura - var/aura_type - -/decl/item_effect/aura/can_do_wielded_effect(mob/user, obj/item/item, list/parameters) - return !!aura_type -/decl/item_effect/aura/do_wielded_effect(mob/user, obj/item/item, list/parameters) - if(!user.has_aura(aura_type)) - user.add_aura(aura_type) - return TRUE - -/decl/item_effect/aura/can_do_unwielded_effect(mob/user, obj/item/item, list/parameters) - return !!aura_type -/decl/item_effect/aura/do_unwielded_effect(mob/user, obj/item/item, list/parameters) - if(user.has_aura(aura_type)) - user.remove_aura(aura_type) - return TRUE - -/decl/item_effect/aura/on_examined(obj/item/item, mob/user) - var/obj/aura/aura = aura_type - to_chat(user, SPAN_NOTICE("\The [item] grants \a [initial(aura.name)] to the wielder.")) - -// Example effect; applies a regeneration aura. -/decl/item_effect/aura/regeneration - aura_type = /obj/aura/regenerating/item - -// Distinct type to avoid removing the wrong type on unwield. -/obj/aura/regenerating/item diff --git a/code/modules/item_effects/item_effect_debug.dm b/code/modules/item_effects/item_effect_debug.dm index 1533abda483..ae834c4bf2c 100644 --- a/code/modules/item_effects/item_effect_debug.dm +++ b/code/modules/item_effects/item_effect_debug.dm @@ -58,7 +58,7 @@ (IE_CAT_EXAMINE), (IE_CAT_RANGED) = list(IE_PAR_USES = 5) )) - add_item_effect(/decl/item_effect/aura/regeneration, list( + add_item_effect(/decl/item_effect/mob_modifier/regeneration, list( (IE_CAT_EXAMINE), (IE_CAT_WIELDED) )) diff --git a/code/modules/item_effects/item_effect_modifier.dm b/code/modules/item_effects/item_effect_modifier.dm new file mode 100644 index 00000000000..4535ccf073a --- /dev/null +++ b/code/modules/item_effects/item_effect_modifier.dm @@ -0,0 +1,27 @@ +/decl/item_effect/mob_modifier + abstract_type = /decl/item_effect/mob_modifier + var/modifier_archetype + +/decl/item_effect/mob_modifier/can_do_wielded_effect(mob/user, obj/item/item, list/parameters) + return !!modifier_archetype + +/decl/item_effect/mob_modifier/do_wielded_effect(mob/user, obj/item/item, list/parameters) + if(!user.has_mob_modifier(modifier_archetype, source = src)) + user.add_mob_modifier(modifier_archetype, source = item) + return TRUE + +/decl/item_effect/mob_modifier/can_do_unwielded_effect(mob/user, obj/item/item, list/parameters) + return !!modifier_archetype + +/decl/item_effect/mob_modifier/do_unwielded_effect(mob/user, obj/item/item, list/parameters) + if(user.has_mob_modifier(modifier_archetype, source = src)) + user.remove_mob_modifier(modifier_archetype, source = src) + return TRUE + +/decl/item_effect/mob_modifier/on_examined(obj/item/item, mob/user) + var/decl/mob_modifier/archetype = GET_DECL(modifier_archetype) + to_chat(user, SPAN_NOTICE("\The [item] grants \a [archetype] to the wielder.")) + +// Example effect; applies a regeneration modifier. +/decl/item_effect/mob_modifier/regeneration + modifier_archetype = /decl/mob_modifier/regeneration/item diff --git a/code/modules/mechs/equipment/combat.dm b/code/modules/mechs/equipment/combat.dm index fbc24657a60..e0fece6b512 100644 --- a/code/modules/mechs/equipment/combat.dm +++ b/code/modules/mechs/equipment/combat.dm @@ -62,8 +62,6 @@ /decl/material/solid/metal/silver = MATTER_AMOUNT_REINFORCEMENT, /decl/material/solid/metal/gold = MATTER_AMOUNT_TRACE ) - - var/obj/aura/mechshield/aura = null var/max_charge = 150 var/charge = 150 var/last_recharge = 0 @@ -72,10 +70,12 @@ /obj/item/mech_equipment/shields/installed(var/mob/living/exosuit/_owner) . = ..() - aura = new(owner, src) + if(owner) + owner.add_mob_modifier(/decl/mob_modifier/mechshield, source = src) /obj/item/mech_equipment/shields/uninstalled() - QDEL_NULL(aura) + if(owner) + owner.remove_mob_modifier(/decl/mob_modifier/mechshield, source = src) . = ..() /obj/item/mech_equipment/shields/attack_self(var/mob/user) @@ -91,23 +91,27 @@ if(difference > 0) for(var/mob/pilot in owner.pilots) - to_chat(pilot, SPAN_DANGER("Warning: Deflector shield failure detect, shutting down!")) + to_chat(pilot, SPAN_DANGER("Warning: Deflector shield failure detected, shutting down!")) toggle() playsound(owner.loc,'sound/mecha/internaldmgalarm.ogg',35,1) return difference else return 0 /obj/item/mech_equipment/shields/proc/toggle() - if(!aura) - return - aura.toggle() + + if(owner?.has_mob_modifier(/decl/mob_modifier/mechshield, source = src)) + owner.remove_mob_modifier(/decl/mob_modifier/mechshield, source = src) + else if(owner) + owner.add_mob_modifier(/decl/mob_modifier/mechshield, source = src) + + active = owner?.has_mob_modifier(/decl/mob_modifier/mechshield, source = src) + playsound(owner,'sound/weapons/flash.ogg',35,1) update_icon() - if(aura.active) + if(active) START_PROCESSING(SSobj, src) else STOP_PROCESSING(SSobj, src) - active = aura.active passive_power_use = active ? 1 KILOWATTS : 0 owner.update_icon() @@ -118,9 +122,7 @@ /obj/item/mech_equipment/shields/on_update_icon() . = ..() - if(!aura) - return - if(aura.active) + if(owner?.has_mob_modifier(/decl/mob_modifier/mechshield, source = src)) icon_state = "shield_droid_a" else icon_state = "shield_droid" @@ -141,91 +143,7 @@ return charge / max_charge /obj/item/mech_equipment/shields/get_hardpoint_maptext() - return "[(aura && aura.active) ? "ONLINE" : "OFFLINE"]: [round((charge / max_charge) * 100)]%" - -/obj/aura/mechshield - icon = 'icons/mecha/shield.dmi' - name = "mechshield" - var/obj/item/mech_equipment/shields/shields = null - var/active = 0 - layer = ABOVE_HUMAN_LAYER - var/north_layer = MECH_UNDER_LAYER - plane = DEFAULT_PLANE - pixel_x = 8 - pixel_y = 4 - mouse_opacity = MOUSE_OPACITY_UNCLICKABLE - -/obj/aura/mechshield/Initialize(var/maploading, var/obj/item/mech_equipment/shields/holder) - . = ..() - shields = holder - -/obj/aura/mechshield/added_to(var/mob/living/target) - . = ..() - target.add_vis_contents(src) - set_dir(target.dir) - events_repository.register(/decl/observ/dir_set, user, src, TYPE_PROC_REF(/obj/aura/mechshield, update_dir)) - -/obj/aura/mechshield/proc/update_dir(var/user, var/old_dir, var/dir) - set_dir(dir) - -/obj/aura/mechshield/set_dir(new_dir) - . = ..() - if(dir == NORTH) - layer = north_layer - else layer = initial(layer) - -/obj/aura/mechshield/Destroy() - if(user) - events_repository.unregister(/decl/observ/dir_set, user, src, TYPE_PROC_REF(/obj/aura/mechshield, update_dir)) - user.remove_vis_contents(src) - shields = null - . = ..() - -/obj/aura/mechshield/proc/toggle() - active = !active - - update_icon() - - if(active) - flick("shield_raise", src) - else - flick("shield_drop", src) - - -/obj/aura/mechshield/on_update_icon() - . = ..() - if(active) - icon_state = "shield" - else - icon_state = "shield_null" - -/obj/aura/mechshield/bullet_act(var/obj/item/projectile/P, var/def_zone) - if(!active) - return - if(shields) - if(shields.charge) - P.damage = shields.stop_damage(P.damage) - user.visible_message(SPAN_WARNING("\The [shields.owner]'s shields flash and crackle.")) - flick("shield_impact", src) - playsound(user,'sound/effects/basscannon.ogg',35,1) - //light up the night. - new /obj/effect/effect/smoke/illumination(user.loc, 5, 4, 1, "#ffffff") - if(P.damage <= 0) - return AURA_FALSE|AURA_CANCEL - - spark_at(user, amount=5) - -/obj/aura/mechshield/hitby(atom/movable/M, var/datum/thrownthing/TT) - . = ..() - if(.) - if(!active) - return - if(shields.charge && TT.speed <= 5) - user.visible_message(SPAN_WARNING("\The [shields.owner]'s shields flash briefly as they deflect \the [M].")) - flick("shield_impact", src) - playsound(user,'sound/effects/basscannon.ogg',10,1) - return AURA_FALSE|AURA_CANCEL - //Too fast! + return "[owner?.has_mob_modifier(/decl/mob_modifier/mechshield, source = src) ? "ONLINE" : "OFFLINE"]: [round((charge / max_charge) * 100)]%" //Melee! As a general rule I would recommend using regular objects and putting logic in them. /obj/item/mech_equipment/mounted_system/melee @@ -287,11 +205,10 @@ /obj/item/mech_equipment/ballistic_shield name = "exosuit ballistic shield" desc = "This formidable line of defense, sees widespread use in planetary peacekeeping operations and military formations alike." - icon_state = "mech_shield" //Rendering is handled by aura due to layering issues: TODO, figure out a better way to do this + icon_state = "mech_shield" restricted_hardpoints = list(HARDPOINT_LEFT_HAND, HARDPOINT_RIGHT_HAND) restricted_software = list(MECH_SOFTWARE_UTILITY) origin_tech = @'{"materials":2,"engineering":2}' - var/obj/aura/mech_ballistic/aura = null var/last_push = 0 var/chance = 60 //For attacks from the front, diminishing returns var/last_max_block = 0 //Blocking during a perfect block window resets this, else there is an anti spam @@ -300,10 +217,10 @@ /obj/item/mech_equipment/ballistic_shield/installed(mob/living/exosuit/_owner) . = ..() - aura = new(owner, src) + owner?.add_mob_modifier(/decl/mob_modifier/mech_ballistic, source = src) /obj/item/mech_equipment/ballistic_shield/uninstalled() - QDEL_NULL(aura) + owner?.remove_mob_modifier(/decl/mob_modifier/mech_ballistic, source = src) . = ..() /obj/item/mech_equipment/ballistic_shield/afterattack(atom/target, mob/living/user, inrange, params) @@ -379,70 +296,6 @@ //Reset timer for maximum chainblocks last_max_block = 0 -/obj/aura/mech_ballistic - icon = 'icons/mecha/ballistic_shield.dmi' - name = "mech_ballistic_shield" - var/obj/item/mech_equipment/ballistic_shield/shield = null - layer = MECH_UNDER_LAYER - plane = DEFAULT_PLANE - mouse_opacity = MOUSE_OPACITY_UNCLICKABLE - -/obj/aura/mech_ballistic/Initialize(maploading, obj/item/mech_equipment/ballistic_shield/holder) - . = ..() - shield = holder - - //Get where we are attached so we know what icon to use - if (holder && holder.owner) - var/mob/living/exosuit/E = holder.owner - for (var/hardpoint in E.hardpoints) - var/obj/item/mech_equipment/hardpoint_object = E.hardpoints[hardpoint] - if (holder == hardpoint_object) - icon_state = "mech_shield_[hardpoint]" - var/image/I = image(icon, "[icon_state]_over") - I.layer = ABOVE_HUMAN_LAYER - overlays.Add(I) - -/obj/aura/mech_ballistic/added_to(mob/living/target) - . = ..() - target.add_vis_contents(src) - set_dir(target.dir) - global.events_repository.register(/decl/observ/dir_set, user, src, TYPE_PROC_REF(/obj/aura/mech_ballistic, update_dir)) - -/obj/aura/mech_ballistic/proc/update_dir(user, old_dir, dir) - set_dir(dir) - -/obj/aura/mech_ballistic/Destroy() - if (user) - global.events_repository.unregister(/decl/observ/dir_set, user, src, TYPE_PROC_REF(/obj/aura/mech_ballistic, update_dir)) - user.remove_vis_contents(src) - shield = null - . = ..() - -/obj/aura/mech_ballistic/bullet_act(obj/item/projectile/P, def_zone) - . = ..() - if (shield && prob(shield.block_chance(P.damage, P.armor_penetration, source = P))) - user.visible_message(SPAN_WARNING("\The [P] is blocked by \the [user]'s [shield.name].")) - user.bullet_impact_visuals(P, def_zone, 0) - shield.on_block_attack() - return AURA_FALSE|AURA_CANCEL - -/obj/aura/mech_ballistic/hitby(atom/movable/AM, datum/thrownthing/TT) - . = ..() - if (. && shield) - var/throw_damage = AM.get_thrown_attack_force() * (TT.speed/THROWFORCE_SPEED_DIVISOR) - if (prob(shield.block_chance(throw_damage, 0, source = AM, attacker = TT.thrower))) - user.visible_message(SPAN_WARNING("\The [AM] bounces off \the [user]'s [shield].")) - playsound(user.loc, 'sound/weapons/Genhit.ogg', 50, 1) - shield.on_block_attack() - return AURA_FALSE|AURA_CANCEL - -/obj/aura/mech_ballistic/attackby(obj/item/I, mob/user) - . = ..() - if (shield && prob(shield.block_chance(I.get_attack_force(), I.armor_penetration, source = I, attacker = user))) - user.visible_message(SPAN_WARNING("\The [I] is blocked by \the [user]'s [shield.name].")) - playsound(user.loc, 'sound/weapons/Genhit.ogg', 50, 1) - return AURA_FALSE|AURA_CANCEL - /obj/item/mech_equipment/flash name = "exosuit flash" icon_state = "mech_flash" diff --git a/code/modules/mechs/mech_damage_immunity.dm b/code/modules/mechs/mech_damage_immunity.dm index 067c613d56d..01a8ef4a0f1 100644 --- a/code/modules/mechs/mech_damage_immunity.dm +++ b/code/modules/mechs/mech_damage_immunity.dm @@ -5,7 +5,7 @@ STAT_PARA ) -/mob/living/exosuit/set_status(condition, amount) +/mob/living/exosuit/set_status_condition(condition, amount) . = !(condition in ignore_status_conditions) && ..() /mob/living/exosuit/getOxyLoss() diff --git a/code/modules/mob/death.dm b/code/modules/mob/death.dm index 0ae0efae943..65c207b4ec7 100644 --- a/code/modules/mob/death.dm +++ b/code/modules/mob/death.dm @@ -92,7 +92,7 @@ reset_plane_and_layer() update_posture() if(!gibbed) - clear_status_effects() + clear_status_conditions() set_sight(sight|SEE_TURFS|SEE_MOBS|SEE_OBJS) set_see_in_dark(8) diff --git a/code/modules/mob/grab/grab_object.dm b/code/modules/mob/grab/grab_object.dm index f8237442c7b..b62c44ff123 100644 --- a/code/modules/mob/grab/grab_object.dm +++ b/code/modules/mob/grab/grab_object.dm @@ -203,7 +203,7 @@ /obj/item/grab/proc/action_used() if(ishuman(assailant)) var/mob/living/human/H = assailant - H.remove_cloaking_source(H.species) + H.remove_mob_modifier(/decl/mob_modifier/cloaked, source = H.species) last_action = world.time leave_forensic_traces() diff --git a/code/modules/mob/living/bot/bot.dm b/code/modules/mob/living/bot/bot.dm index 9f3089994e6..339769eea84 100644 --- a/code/modules/mob/living/bot/bot.dm +++ b/code/modules/mob/living/bot/bot.dm @@ -56,9 +56,9 @@ /mob/living/bot/handle_regular_status_updates() . = ..() if(.) - set_status(STAT_WEAK, 0) - set_status(STAT_STUN, 0) - set_status(STAT_PARA, 0) + set_status_condition(STAT_WEAK, 0) + set_status_condition(STAT_STUN, 0) + set_status_condition(STAT_PARA, 0) /mob/living/bot/get_life_damage_types() var/static/list/life_damage_types = list( diff --git a/code/modules/mob/living/bot/secbot.dm b/code/modules/mob/living/bot/secbot.dm index faca3a286c2..e612a4e3d72 100644 --- a/code/modules/mob/living/bot/secbot.dm +++ b/code/modules/mob/living/bot/secbot.dm @@ -51,11 +51,11 @@ /mob/living/bot/secbot/turn_on() ..() - stun_baton.set_status(on, null) + stun_baton.set_cell_status(on, null) /mob/living/bot/secbot/turn_off() ..() - stun_baton.set_status(on, null) + stun_baton.set_cell_status(on, null) /mob/living/bot/secbot/on_update_icon() ..() diff --git a/code/modules/mob/living/human/human.dm b/code/modules/mob/living/human/human.dm index 2efb51f3b3c..e6c920019aa 100644 --- a/code/modules/mob/living/human/human.dm +++ b/code/modules/mob/living/human/human.dm @@ -496,7 +496,6 @@ //Handle old species transition if(species) - species.remove_base_auras(src) species.remove_inherent_verbs(src) //Update our species diff --git a/code/modules/mob/living/human/human_attackhand.dm b/code/modules/mob/living/human/human_attackhand.dm index 00c8a932b86..747a1d5439c 100644 --- a/code/modules/mob/living/human/human_attackhand.dm +++ b/code/modules/mob/living/human/human_attackhand.dm @@ -232,7 +232,7 @@ /mob/living/human/attack_hand(mob/user) - remove_cloaking_source(species) + remove_mob_modifier(/decl/mob_modifier/cloaked, source = species) if(!user.check_intent(I_FLAG_GRAB)) for (var/obj/item/grab/grab as anything in user.get_active_grabs()) if(grab.assailant == user && grab.affecting == src && grab.resolve_openhand_attack()) diff --git a/code/modules/mob/living/human/human_grabs.dm b/code/modules/mob/living/human/human_grabs.dm index c9fadf93e18..38987122e3b 100644 --- a/code/modules/mob/living/human/human_grabs.dm +++ b/code/modules/mob/living/human/human_grabs.dm @@ -25,4 +25,4 @@ /mob/living/human/make_grab(atom/movable/target, grab_tag = /decl/grab/simple, defer_hand = FALSE, force_grab_tag = FALSE) . = ..() if(.) - remove_cloaking_source(species) + remove_mob_modifier(/decl/mob_modifier/cloaked, source = species) diff --git a/code/modules/mob/living/human/human_helpers.dm b/code/modules/mob/living/human/human_helpers.dm index 90035988c32..39847bceef8 100644 --- a/code/modules/mob/living/human/human_helpers.dm +++ b/code/modules/mob/living/human/human_helpers.dm @@ -181,72 +181,6 @@ SET_STATUS_MAX(src, STAT_BLURRY, 5) add_genetic_condition(GENE_COND_NEARSIGHTED, 10 SECONDS) -/mob/living/human - var/list/cloaking_sources - -// Returns true if, and only if, the human has gone from uncloaked to cloaked -/mob/living/human/proc/add_cloaking_source(var/datum/cloaking_source) - var/has_uncloaked = clean_cloaking_sources() - LAZYDISTINCTADD(cloaking_sources, weakref(cloaking_source)) - - // We don't present the cloaking message if the human was already cloaked just before cleanup. - if(!has_uncloaked && LAZYLEN(cloaking_sources) == 1) - update_icon() - src.visible_message("\The [src] seems to disappear before your eyes!", "You feel completely invisible.") - return TRUE - return FALSE - -#define CLOAK_APPEAR_OTHER "\The [src] appears from thin air!" -#define CLOAK_APPEAR_SELF "You have re-appeared." - -// Returns true if, and only if, the human has gone from cloaked to uncloaked -/mob/living/human/proc/remove_cloaking_source(var/datum/cloaking_source) - var/was_cloaked = LAZYLEN(cloaking_sources) - clean_cloaking_sources() - LAZYREMOVE(cloaking_sources, weakref(cloaking_source)) - - if(was_cloaked && !LAZYLEN(cloaking_sources)) - update_icon() - visible_message(CLOAK_APPEAR_OTHER, CLOAK_APPEAR_SELF) - return TRUE - return FALSE - -// Returns true if the human is cloaked, otherwise false (technically returns the number of cloaking sources) -/mob/proc/is_cloaked() - return FALSE - -/mob/living/human/is_cloaked() - if(clean_cloaking_sources()) - update_icon() - visible_message(CLOAK_APPEAR_OTHER, CLOAK_APPEAR_SELF) - return LAZYLEN(cloaking_sources) - -#undef CLOAK_APPEAR_OTHER -#undef CLOAK_APPEAR_SELF - -// Returns true if the human is cloaked by the given source -/mob/living/human/proc/is_cloaked_by(var/cloaking_source) - return LAZYISIN(cloaking_sources, weakref(cloaking_source)) - -// Returns true if this operation caused the mob to go from cloaked to uncloaked -/mob/living/human/proc/clean_cloaking_sources() - if(!cloaking_sources) - return FALSE - - var/list/rogue_entries = list() - for(var/entry in cloaking_sources) - var/weakref/W = entry - if(!W.resolve()) - cloaking_sources -= W - rogue_entries += W - - if(rogue_entries.len) // These entries did not cleanup after themselves before being destroyed - var/rogue_entries_as_string = jointext(map(rogue_entries, /proc/log_info_line), ", ") - PRINT_STACK_TRACE("[log_info_line(src)] - Following cloaking entries were removed during cleanup: [rogue_entries_as_string]") - - UNSETEMPTY(cloaking_sources) - return !cloaking_sources // If cloaking_sources wasn't initially null but is now, we've uncloaked - /mob/living/human/proc/has_meson_effect() var/datum/global_hud/global_hud = get_global_hud() return (global_hud.meson in equipment_overlays) diff --git a/code/modules/mob/living/human/life.dm b/code/modules/mob/living/human/life.dm index 5beb8833681..f3d113743d5 100644 --- a/code/modules/mob/living/human/life.dm +++ b/code/modules/mob/living/human/life.dm @@ -125,8 +125,8 @@ vision = GET_INTERNAL_ORGAN(src, vision_organ_tag) if(!vision_organ_tag) // Presumably if a species has no vision organs, they see via some other means. - set_status(STAT_BLIND, 0) - set_status(STAT_BLURRY, 0) + set_status_condition(STAT_BLIND, 0) + set_status_condition(STAT_BLURRY, 0) else if(!vision || (vision && !vision.is_usable())) // Vision organs cut out or broken? Permablind. SET_STATUS_MAX(src, STAT_BLIND, 2) SET_STATUS_MAX(src, STAT_BLURRY, 1) @@ -224,7 +224,7 @@ burn_dam = COLD_DAMAGE_LEVEL_2 else burn_dam = COLD_DAMAGE_LEVEL_3 - set_stasis(get_cryogenic_factor(bodytemperature), STASIS_COLD) + add_mob_modifier(/decl/mob_modifier/stasis, 2 SECONDS, source = src) if(!has_chemical_effect(CE_CRYO, 1)) take_overall_damage(burn=burn_dam, used_weapon = "Low Body Temperature") SET_HUD_ALERT_MAX(src, HUD_FIRE, 1) diff --git a/code/modules/mob/living/human/update_icons.dm b/code/modules/mob/living/human/update_icons.dm index ff824d2389b..07d4bbbf6b9 100644 --- a/code/modules/mob/living/human/update_icons.dm +++ b/code/modules/mob/living/human/update_icons.dm @@ -340,7 +340,7 @@ Please contact me on #coderbus IRC. ~Carn x /mob/living/human/update_hair(var/update_icons=1) var/obj/item/organ/external/head/head_organ = get_organ(BP_HEAD, /obj/item/organ/external/head) - var/list/new_accessories = head_organ?.get_mob_overlays() + var/list/new_accessories = head_organ?.get_limb_mob_overlays() set_current_mob_overlay(HO_HAIR_LAYER, new_accessories, update_icons) /mob/living/human/proc/update_skin(var/update_icons=1) diff --git a/code/modules/mob/living/life.dm b/code/modules/mob/living/life.dm index 7c8dd1bf7c8..0715ea9f3dd 100644 --- a/code/modules/mob/living/life.dm +++ b/code/modules/mob/living/life.dm @@ -25,12 +25,9 @@ if(QDELETED(src)) // Destroyed by fire or pressure damage in handle_environment() return PROCESS_KILL handle_regular_status_updates() // Status & health update, are we dead or alive etc. - handle_stasis() - if(stat != DEAD) - if(!is_in_stasis()) - . = handle_living_non_stasis_processes() - aura_check(AURA_TYPE_LIFE) + if(stat != DEAD && !has_mob_modifier(/decl/mob_modifier/stasis)) + . = handle_living_non_stasis_processes() for(var/obj/item/grab/grab as anything in get_active_grabs()) grab.Process() @@ -42,7 +39,8 @@ handle_grasp() handle_stance() handle_regular_hud_updates() - handle_status_effects() + handle_status_conditions() + handle_mob_modifiers() return 1 /mob/living/proc/handle_grasp() @@ -445,6 +443,7 @@ //this handles hud updates. Calls update_vision() and handle_hud_icons() /mob/living/proc/handle_regular_hud_updates() + SHOULD_CALL_PARENT(TRUE) if(!should_do_hud_updates()) return FALSE diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index a2bb5d26fa2..03966f65b00 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -233,8 +233,8 @@ default behaviour is: if(stat != DEAD && should_be_dead()) death() if(!QDELETED(src)) // death() may delete or remove us - set_status(STAT_BLIND, 1) - set_status(STAT_SILENCE, 0) + set_status_condition(STAT_BLIND, 1) + set_status_condition(STAT_SILENCE, 0) return TRUE //This proc is used for mobs which are affected by pressure to calculate the amount of pressure that actually @@ -330,17 +330,17 @@ default behaviour is: set_damage(OXY, 0) set_damage(CLONE, 0) set_damage(BRAIN, 0) - set_status(STAT_PARA, 0) - set_status(STAT_STUN, 0) - set_status(STAT_WEAK, 0) + set_status_condition(STAT_PARA, 0) + set_status_condition(STAT_STUN, 0) + set_status_condition(STAT_WEAK, 0) // shut down ongoing problems radiation = 0 bodytemperature = get_species()?.body_temperature || initial(bodytemperature) reset_genetic_conditions() - // fix all status conditions including blind/deaf - clear_status_effects() + // clear all status conditions including blind/deaf + clear_status_conditions() heal_overall_damage(get_damage(BRUTE), get_damage(BURN)) @@ -745,48 +745,14 @@ default behaviour is: to_chat(src, "Remember to stay in character for a mob of this type!") return 1 -/mob/proc/add_aura(var/obj/aura/aura, skip_icon_update = FALSE) - return FALSE - -/mob/living/add_aura(var/obj/aura/aura, skip_icon_update = FALSE) - if(ispath(aura)) - aura = new aura(src) - if(!istype(aura)) - return FALSE - LAZYDISTINCTADD(auras,aura) - if(!skip_icon_update) - update_icon() - return TRUE - -/mob/proc/has_aura(aura_type) - return FALSE - -/mob/living/has_aura(aura_type) - return length(auras) && (locate(aura_type) in auras) - -/mob/proc/remove_aura(var/obj/aura/aura, skip_icon_update = FALSE) - return FALSE - -/mob/living/remove_aura(var/obj/aura/aura, skip_icon_update = FALSE) - if(ispath(aura)) - aura = locate() in auras - if(!istype(aura)) - return FALSE - LAZYREMOVE(auras,aura) - if(!skip_icon_update) - update_icon() - return TRUE - /mob/living/Destroy() + clear_mob_modifiers() QDEL_NULL(aiming) QDEL_NULL_LIST(_hallucinations) QDEL_NULL_LIST(aimed_at_by) LAZYCLEARLIST(smell_cooldown) if(stressors) // Do not QDEL_NULL, keys are managed instances. stressors = null - if(auras) - for(var/a in auras) - remove_aura(a) // done in this order so that icon updates aren't triggered once all our organs are obliterated delete_inventory(TRUE) delete_organs() @@ -889,7 +855,7 @@ default behaviour is: if(!HAS_STATUS(src, STAT_PARA) && stat == CONSCIOUS) visible_message(SPAN_DANGER("\The [src] starts having a seizure!")) SET_STATUS_MAX(src, STAT_PARA, rand(8,16)) - set_status(STAT_JITTER, rand(150,200)) + set_status_condition(STAT_JITTER, rand(150,200)) take_damage(rand(50, 60), PAIN) /mob/living/proc/get_digestion_product() @@ -2024,3 +1990,5 @@ default behaviour is: pulling_punches = !pulling_punches to_chat(src, SPAN_NOTICE("You are now [pulling_punches ? "pulling your punches" : "not pulling your punches"].")) +/mob/living/is_cloaked() + return has_mob_modifier(/decl/mob_modifier/cloaked) diff --git a/code/modules/mob/living/living_appearance.dm b/code/modules/mob/living/living_appearance.dm index ea2bb37147e..0b34b88f140 100644 --- a/code/modules/mob/living/living_appearance.dm +++ b/code/modules/mob/living/living_appearance.dm @@ -10,17 +10,6 @@ SHOULD_CALL_PARENT(TRUE) ..() cut_overlays() - if(auras) - var/decl/bodytype/my_bodytype = get_bodytype() - for(var/obj/aura/aura as anything in auras) - var/image/A = new() - A.appearance = aura - if(my_bodytype) - if(my_bodytype.pixel_offset_x) - A.pixel_x += -(my_bodytype.pixel_offset_x) - if(my_bodytype.pixel_offset_y) - A.pixel_y += -(my_bodytype.pixel_offset_y) - add_overlay(A) try_refresh_visible_overlays() /mob/living/proc/set_organ_sprite_accessory(var/accessory_type, var/accessory_category, var/accessory_metadata, var/organ_tag, var/skip_update = FALSE) @@ -77,3 +66,24 @@ /mob/living/get_current_mob_underlay(var/underlay_layer) return mob_underlays[underlay_layer] + +/mob/living/refresh_visible_overlays() + . = ..() + var/list/modifier_overlays = null + for(var/decl/mob_modifier/archetype in _mob_modifiers) + var/image/status_overlay = archetype.get_modifier_mob_overlay(src) + if(status_overlay) + LAZYADD(modifier_overlays, status_overlay) + set_current_mob_overlay(HO_EFFECT_LAYER, modifier_overlays, FALSE) + +/decl/mob_modifier/proc/get_modifier_mob_overlay(mob/living/_owner) + if(!mob_overlay_icon || !mob_overlay_state || !istype(_owner)) + return null + var/image/mob_overlay = overlay_image(mob_overlay_icon, mob_overlay_state, COLOR_WHITE, RESET_COLOR) + var/decl/bodytype/owner_bodytype = _owner.get_bodytype() + if(owner_bodytype) + if(owner_bodytype.pixel_offset_x) + mob_overlay.pixel_x += -(owner_bodytype.pixel_offset_x) + if(owner_bodytype.pixel_offset_y) + mob_overlay.pixel_y += -(owner_bodytype.pixel_offset_y) + return mob_overlay diff --git a/code/modules/mob/living/living_defense.dm b/code/modules/mob/living/living_defense.dm index f6b7d220a18..88842cb634e 100644 --- a/code/modules/mob/living/living_defense.dm +++ b/code/modules/mob/living/living_defense.dm @@ -60,28 +60,6 @@ /mob/living/get_bullet_impact_effect_type(var/def_zone) return BULLET_IMPACT_MEAT -/mob/living/proc/aura_check(var/type) - if(!auras) - return TRUE - . = TRUE - var/list/newargs = args - args[1] - for(var/obj/aura/aura as anything in auras) - var/result = 0 - switch(type) - if(AURA_TYPE_WEAPON) - result = aura.attackby(arglist(newargs)) - if(AURA_TYPE_BULLET) - result = aura.bullet_act(arglist(newargs)) - if(AURA_TYPE_THROWN) - result = aura.hitby(arglist(newargs)) - if(AURA_TYPE_LIFE) - result = aura.life_tick() - if(result & AURA_FALSE) - . = FALSE - if(result & AURA_CANCEL) - break - - //Handles the effects of "stun" weapons /mob/living/proc/stun_effect_act(stun_amount, agony_amount, def_zone, used_weapon) flash_pain() @@ -139,7 +117,7 @@ if(31 to INFINITY) SET_STATUS_MAX(src, STAT_WEAK, 10) //This should work for now, more is really silly and makes you lay there forever - set_status(STAT_JITTER, min(shock_damage*5, 200)) + set_status_condition(STAT_JITTER, min(shock_damage*5, 200)) spark_at(loc, amount=5, cardinal_only = TRUE) @@ -192,7 +170,7 @@ SET_STATUS_MAX(M, STAT_WEAK, rand(4,8)) M.visible_message(SPAN_DANGER("\The [M] collides with \the [src]!")) - if(!aura_check(AURA_TYPE_THROWN, AM, TT.speed)) + if(mob_modifiers_block_attack(MM_ATTACK_TYPE_THROWN, AM, TT.speed)) return FALSE if(istype(AM, /obj)) @@ -402,3 +380,13 @@ if(shield.handle_shield(src, damage, damage_source, attacker, def_zone, attack_text)) return TRUE return FALSE + +/mob/living/mob_modifiers_block_attack(attack_type, atom/movable/attacker, additional_data) + . = FALSE + if(length(_mob_modifiers)) + for(var/decl/mob_modifier/archetype in _mob_modifiers) + var/result = archetype.check_modifiers_block_attack(src, _mob_modifiers[archetype], attack_type, attacker, additional_data) + if(result & MM_ATTACK_RESULT_DEFLECTED) + . = TRUE + if(result & MM_ATTACK_RESULT_BLOCKED) + break diff --git a/code/modules/mob/living/living_defines.dm b/code/modules/mob/living/living_defines.dm index 4d894ca4fa9..2268376300d 100644 --- a/code/modules/mob/living/living_defines.dm +++ b/code/modules/mob/living/living_defines.dm @@ -37,7 +37,6 @@ var/possession_candidate // Can be possessed by ghosts if unplayed. var/job = null//Living - var/list/obj/aura/auras = null //Basically a catch-all aura/force-field thing. var/last_resist = 0 var/admin_paralyzed = FALSE @@ -55,8 +54,6 @@ var/list/stressors var/life_tick - var/list/stasis_sources - var/stasis_value var/nutrition = 400 var/hydration = 400 diff --git a/code/modules/mob/living/living_status.dm b/code/modules/mob/living/living_status.dm index 645b5323448..179412f6a7a 100644 --- a/code/modules/mob/living/living_status.dm +++ b/code/modules/mob/living/living_status.dm @@ -1,9 +1,13 @@ -/mob // Defined on /mob to avoid having to pass args to every single attack_foo() proc. +// Defined on /mob to avoid having to pass args to every single attack_foo() proc. +/mob + // A STATUS CONDITION is a counter on an general incapacitating effect like sleep or blindness. + // STATUS CONDITION TRACKERS: var/list/status_counters var/list/pending_status_counters var/datum/status_marker_holder/status_markers -/mob/living/set_status(var/condition, var/amount) +// Status condition procs: +/mob/living/set_status_condition(var/condition, var/amount) if(QDELETED(src)) return FALSE if(!ispath(condition, /decl/status_condition)) @@ -57,7 +61,7 @@ var/decl/status_condition/status = GET_DECL(condition) status.handle_changed_amount(src, new_amount, last_amount) -/mob/living/handle_status_effects() +/mob/living/handle_status_conditions() . = ..() var/refresh_icon = FALSE for(var/condition in status_counters) @@ -66,13 +70,18 @@ if(GET_STATUS(src, condition) <= 0) status_counters -= condition refresh_icon = TRUE + if(status.associated_mob_modifier) + remove_mob_modifier(status.associated_mob_modifier, source = src) + else if(status.associated_mob_modifier) + add_mob_modifier(status.associated_mob_modifier, source = src) + if(refresh_icon) update_icon() -/mob/living/clear_status_effects() +/mob/living/clear_status_conditions() var/had_counters = !!LAZYLEN(status_counters) for(var/stype in status_counters) - set_status(stype, 0) + set_status_condition(stype, 0) status_counters = null pending_status_counters = null if(had_counters) diff --git a/code/modules/mob/living/silicon/login.dm b/code/modules/mob/living/silicon/login.dm index 3ff4653c93d..9f5a88f6cd1 100644 --- a/code/modules/mob/living/silicon/login.dm +++ b/code/modules/mob/living/silicon/login.dm @@ -1,3 +1,3 @@ /mob/living/silicon/Login() ..() - set_status(STAT_ASLEEP, 0) + set_status_condition(STAT_ASLEEP, 0) diff --git a/code/modules/mob/living/silicon/pai/software.dm b/code/modules/mob/living/silicon/pai/software.dm index b53b8a9cfe2..058e882d06b 100644 --- a/code/modules/mob/living/silicon/pai/software.dm +++ b/code/modules/mob/living/silicon/pai/software.dm @@ -38,16 +38,15 @@ var/global/list/default_pai_software = list() /mob/living/silicon/pai/ui_interact(mob/user, ui_key = "main", datum/nanoui/ui = null, force_open = 1) if(user != src || !istype(card)) - if(ui) - ui.set_status(STATUS_CLOSE, 0) + ui?.set_nano_status(STATUS_CLOSE, 0) return if(ui_key != "main") var/datum/pai_software/S = software[ui_key] if(S && !S.toggle) S.on_ui_interact(src, ui, force_open) - else - if(ui) ui.set_status(STATUS_CLOSE, 0) + else if(ui) + ui.set_nano_status(STATUS_CLOSE, 0) return var/data[0] diff --git a/code/modules/mob/living/silicon/robot/life.dm b/code/modules/mob/living/silicon/robot/life.dm index ea41b012d30..765cf2b43f6 100644 --- a/code/modules/mob/living/silicon/robot/life.dm +++ b/code/modules/mob/living/silicon/robot/life.dm @@ -48,7 +48,7 @@ SHOULD_CALL_PARENT(FALSE) update_health() - set_status(STAT_PARA, min(GET_STATUS(src, STAT_PARA), 30)) + set_status_condition(STAT_PARA, min(GET_STATUS(src, STAT_PARA), 30)) if(HAS_STATUS(src, STAT_ASLEEP)) SET_STATUS_MAX(src, STAT_PARA, 3) @@ -68,7 +68,7 @@ SET_STATUS_MAX(src, STAT_BLIND, 2) if(has_genetic_condition(GENE_COND_DEAFENED)) - src.set_status(STAT_DEAF, 1) + src.set_status_condition(STAT_DEAF, 1) //update the state of modules and components here if (stat != CONSCIOUS) diff --git a/code/modules/mob/living/silicon/robot/robot_items.dm b/code/modules/mob/living/silicon/robot/robot_items.dm index c2fde015d1d..8787fc15696 100644 --- a/code/modules/mob/living/silicon/robot/robot_items.dm +++ b/code/modules/mob/living/silicon/robot/robot_items.dm @@ -192,7 +192,7 @@ /obj/item/borg/combat/shield name = "personal shielding" desc = "A powerful experimental module that turns aside or absorbs incoming attacks at the cost of charge." - icon = 'icons/obj/decals.dmi' + icon = 'icons/obj/signs/warnings.dmi' icon_state = "shock" var/shield_level = 0.5 //Percentage of damage absorbed by the shield. @@ -208,7 +208,7 @@ /obj/item/borg/combat/mobility name = "mobility module" desc = "By retracting limbs and tucking in its head, a combat android can roll at high speeds." - icon = 'icons/obj/decals.dmi' + icon = 'icons/obj/signs/warnings.dmi' icon_state = "shock" /obj/item/inflatable_dispenser diff --git a/code/modules/mob/living/stasis.dm b/code/modules/mob/living/stasis.dm index 76fda177df5..256e9802674 100644 --- a/code/modules/mob/living/stasis.dm +++ b/code/modules/mob/living/stasis.dm @@ -1,26 +1,3 @@ -/mob/living/proc/set_stasis(var/factor, var/source = "misc") - var/decl/bodytype/my_bodytype = get_bodytype() - if(my_bodytype?.body_flags & BODY_FLAG_NO_STASIS) - return - LAZYSET(stasis_sources, source, factor) - -/mob/living/proc/is_in_stasis() - return stasis_value ? !!(life_tick % stasis_value) : FALSE - -/mob/living/proc/handle_stasis() - stasis_value = 0 - if(stasis_sources) - var/decl/bodytype/my_bodytype = get_bodytype() - if(!(my_bodytype?.body_flags & BODY_FLAG_NO_STASIS)) - for(var/source in stasis_sources) - stasis_value += stasis_sources[source] - stasis_sources = null - - if(stasis_value > 1 && GET_STATUS(src, STAT_DROWSY) < stasis_value * 4) - ADJ_STATUS(src, STAT_DROWSY, min(stasis_value, 3)) - if(stat == CONSCIOUS && prob(1)) - to_chat(src, SPAN_NOTICE("You feel slow and sluggish...")) - /mob/living/proc/get_cryogenic_factor(var/bodytemperature) if(isSynthetic()) diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm index eafaddbed54..150c6a94dc9 100644 --- a/code/modules/mob/mob.dm +++ b/code/modules/mob/mob.dm @@ -1474,3 +1474,6 @@ if(istype(limb_unarmed_attacks, /decl/natural_attack) || (islist(limb_unarmed_attacks) && length(limb_unarmed_attacks))) LAZYDISTINCTADD(., limb_unarmed_attacks) +// Returns true if the mob is cloaked, otherwise false +/mob/proc/is_cloaked() + return FALSE diff --git a/code/modules/mob/mob_defines.dm b/code/modules/mob/mob_defines.dm index a383f3b30fc..e11b0ff37c6 100644 --- a/code/modules/mob/mob_defines.dm +++ b/code/modules/mob/mob_defines.dm @@ -92,7 +92,7 @@ //The last mob/living to push/drag/grab this mob (mostly used by slimes friend recognition) var/weakref/last_handled_by_mob - var/status_flags = CANSTUN|CANWEAKEN|CANPARALYSE|CANPUSH //bitflags defining which status effects can be inflicted (replaces canweaken, canstun, etc) + var/status_flags = CANSTUN|CANWEAKEN|CANPARALYSE|CANPUSH //bitflags defining which status conditions can be inflicted (replaces canweaken, canstun, etc) var/area/lastarea = null diff --git a/code/modules/mob/mob_status.dm b/code/modules/mob/mob_status.dm index 0e2c45822b9..5e08a530c40 100644 --- a/code/modules/mob/mob_status.dm +++ b/code/modules/mob/mob_status.dm @@ -1,9 +1,24 @@ // Stubs; see living_status.dm -/mob/proc/handle_status_effects() +/mob/proc/handle_status_conditions() SHOULD_CALL_PARENT(TRUE) -/mob/proc/clear_status_effects() +/mob/proc/clear_status_conditions() return -/mob/proc/set_status(var/condition, var/amount) +/mob/proc/set_status_condition(var/condition, var/amount) return + +/mob/proc/clear_mob_modifiers() + return FALSE + +/mob/proc/remove_mob_modifier(decl/mob_modifier/archetype, datum/source, skip_update = FALSE) + return FALSE + +/mob/proc/has_mob_modifier(decl/mob_modifier/archetype, datum/source) + return FALSE + +/mob/proc/add_mob_modifier(decl/mob_modifier/archetype, duration = MOB_MODIFIER_INDEFINITE, datum/source, skip_update = FALSE) + return FALSE + +/mob/proc/mob_modifiers_block_attack(...) + return FALSE // see living_defense.dm diff --git a/code/modules/mob/transform_procs.dm b/code/modules/mob/transform_procs.dm index 6ec207ea1b8..21e905f85a6 100644 --- a/code/modules/mob/transform_procs.dm +++ b/code/modules/mob/transform_procs.dm @@ -5,7 +5,7 @@ drop_from_inventory(W) try_refresh_visible_overlays() ADD_TRANSFORMATION_MOVEMENT_HANDLER(src) - set_status(STAT_STUN, 1) + set_status_condition(STAT_STUN, 1) icon = null set_invisibility(INVISIBILITY_ABSTRACT) for(var/t in get_external_organs()) @@ -18,7 +18,7 @@ //animation = null DEL_TRANSFORMATION_MOVEMENT_HANDLER(src) - set_status(STAT_STUN, 0) + set_status_condition(STAT_STUN, 0) update_posture() set_invisibility(initial(invisibility)) diff --git a/code/modules/mob_modifiers/_modifiers.dm b/code/modules/mob_modifiers/_modifiers.dm new file mode 100644 index 00000000000..677608454af --- /dev/null +++ b/code/modules/mob_modifiers/_modifiers.dm @@ -0,0 +1,89 @@ +// Notes on mob modifiers: +// - added/removed from mob with add_mob_modifier(/decl/mob_modifier/foo, DURATION IN DS, source = SOME ATOM) +// - decl will generate a decl/mob_modifier based on the source of the modifier +// - decl heartbeat logic (actual modifier) will run once per life tick regardless of number of sources, if you want +// stacking modifiers it has to be implemented within the decl. + +/// Instanced 'modifiers' that sit on top of a mob and can expire over time or linger until dispelled. +/// Some are purely visual, others have associated modifiers. +/decl/mob_modifier + abstract_type = /decl/mob_modifier + /// Tooltip name of this modifier. + var/name + /// Tooltip description of this modifier. + var/desc + /// Icon to use for the HUD element. + var/hud_icon = 'icons/screen/mob_modifiers.dmi' + /// State to use for the HUD element. + var/hud_icon_state + /// Icon to draw from for the mob overlay modifier is present. + var/mob_overlay_icon + /// State to draw over the mob when modifier is present. + var/mob_overlay_state + /// Metadata type to create for this status modifier. + var/modifier_type = /datum/mob_modifier + /// Message shown to the target when modifier begins. + var/on_add_message_1p + /// Message shown to the audience when modifier begins. + var/on_add_message_3p + /// Message shown to the target when modifier ends. + var/on_end_message_1p + /// Message shown to the audience when modifier ends. + var/on_end_message_3p + /// Whether or not this modifier can be granted by admin (source-ambivalent) + var/can_be_admin_granted = FALSE + /// Whether or not this modifier shows a lemniscate when set to indefinite duration. + var/show_indefinite_duration = TRUE + /// Whether or not this modifier shows remaining time before expiry. + var/hide_expiry= FALSE + +/decl/mob_modifier/validate() + . = ..() + if(!hud_icon) + . += "no hud_icon set" + if(!istext(hud_icon_state)) + . += "null or invalid hud_icon_state" + if(hud_icon && hud_icon_state && !check_state_in_icon(hud_icon_state, hud_icon)) + . += "hud_icon '[hud_icon]' missing hud_icon_state '[hud_icon_state]'" + + if(mob_overlay_icon) + if(istext(mob_overlay_state)) + if(!check_state_in_icon(mob_overlay_state, mob_overlay_icon)) + . += "mob_overlay_icon '[mob_overlay_icon]' missing mob_overlay_state '[mob_overlay_state]'" + else + . += "null or invalid mob_overlay_state" + else if(mob_overlay_state) + . += "mob_overlay_state set but mob_overlay_icon not set" + +/decl/mob_modifier/proc/replace_tokens(message, mob/user) + return capitalize(emote_replace_user_tokens(message, user)) + +/decl/mob_modifier/proc/on_modifier_datum_added(mob/living/_owner, datum/mob_modifier/modifier) + if(on_add_message_3p) + _owner.visible_message(replace_tokens(on_add_message_3p, _owner), replace_tokens((on_add_message_3p || on_add_message_1p), _owner)) + else if(on_add_message_1p) + to_chat(_owner, replace_tokens(on_add_message_1p, _owner)) + return TRUE + +/decl/mob_modifier/proc/on_modifier_datum_removed(mob/living/_owner, datum/mob_modifier/modifier) + if(on_end_message_3p) + _owner.visible_message(replace_tokens(on_end_message_3p, _owner), replace_tokens((on_end_message_3p || on_end_message_1p), _owner)) + else if(on_end_message_1p) + to_chat(_owner, replace_tokens(on_end_message_1p, _owner)) + return TRUE + +/decl/mob_modifier/proc/on_modifier_datum_expiry(mob/living/_owner, datum/mob_modifier/modifier) + return TRUE + +/decl/mob_modifier/proc/on_modifier_datum_mob_life(mob/living/_owner, list/modifiers) + SHOULD_CALL_PARENT(TRUE) + . = FALSE + for(var/datum/mob_modifier/modifier in modifiers) + if(modifier.on_modifier_mob_life()) + . = TRUE + +/decl/mob_modifier/proc/on_modifier_datum_click(mob/living/_owner, datum/mob_modifier/modifier, params) + return FALSE + +/decl/mob_modifier/proc/check_modifiers_block_attack(mob/living/_owner, list/modifiers, attack_type, atom/movable/attacker, additional_data) + return FALSE diff --git a/code/modules/mob_modifiers/definitions/modifiers_cloaked.dm b/code/modules/mob_modifiers/definitions/modifiers_cloaked.dm new file mode 100644 index 00000000000..5ac1889ce59 --- /dev/null +++ b/code/modules/mob_modifiers/definitions/modifiers_cloaked.dm @@ -0,0 +1,17 @@ +/decl/mob_modifier/cloaked + name = "Cloaked" + desc = "You are hidden from casual sight." + hud_icon_state = "cloaked" + on_add_message_1p = SPAN_NOTICE("You feel completely invisible.") + on_add_message_3p = SPAN_WARNING("$USER$ seems to disappear before your eyes!") + on_end_message_1p = SPAN_NOTICE("You have re-appeared.") + on_end_message_3p = SPAN_WARNING("$USER$ appears from thin air!") + can_be_admin_granted = TRUE + +// Not ideal, but existing cloaking code is iffy about removing cloaking sources appropriately (specifically rig modules) +/decl/mob_modifier/cloaked/on_modifier_datum_mob_life(mob/living/_owner, list/modifiers) + . = ..() + for(var/datum/mob_modifier/modifier in modifiers) + var/atom/source = modifier.source?.resolve() + if(istype(source) && source.get_recursive_loc_of_type(/mob/living) != _owner) + _owner.remove_mob_modifier(src, source = source) diff --git a/code/modules/mob_modifiers/definitions/modifiers_light.dm b/code/modules/mob_modifiers/definitions/modifiers_light.dm new file mode 100644 index 00000000000..9b352184cb7 --- /dev/null +++ b/code/modules/mob_modifiers/definitions/modifiers_light.dm @@ -0,0 +1,39 @@ +/datum/mob_modifier/object/light + var/light_range = 6 + var/light_power = 6 + var/light_color = COLOR_BEIGE + +/decl/mob_modifier/light + name = "Light Aura" + desc = "You are emitting a gentle radiance." + hud_icon_state = "light" + on_add_message_1p = SPAN_NOTICE("A gentle radiance emanates from your body.") + on_end_message_1p = SPAN_NOTICE("The light spilling from your body fades.") + modifier_type = /datum/mob_modifier/object/light + can_be_admin_granted = TRUE + +/datum/mob_modifier/object/light/on_modifier_added(skip_update) + . = ..() + if(istype(object) && (light_range || light_power || light_color)) + object.set_light(light_range, light_power, light_color) + +/decl/mob_modifier/light/radiant + name = "Radiant Aura" + desc = "You are guarded from laser weapons by a radiant aura." + mob_overlay_icon = 'icons/effects/effects.dmi' + mob_overlay_state = "fire_goon" + on_add_message_1p = SPAN_NOTICE("A bubble of light appears around you, exuding protection and warmth.") + on_end_message_1p = SPAN_DANGER("Your protective aura dissipates, leaving you feeling cold and unsafe.") + modifier_type = /datum/mob_modifier/object/light + +/datum/mob_modifier/object/light/radiant + light_color = "#e09d37" + +/decl/mob_modifier/light/radiant/check_modifiers_block_attack(mob/living/_owner, list/modifiers, attack_type, atom/movable/attacker, additional_data) + if(attack_type != MM_ATTACK_TYPE_PROJECTILE) + return ..() + var/obj/item/projectile/projectile = attacker + if(istype(projectile) && (projectile.damage_flags() & DAM_LASER)) + _owner.visible_message(SPAN_WARNING("\The [projectile] refracts, bending into \the [_owner]'s radiance.")) + return (MM_ATTACK_RESULT_BLOCKED|MM_ATTACK_RESULT_DEFLECTED) + return MM_ATTACK_RESULT_NONE diff --git a/code/modules/mob_modifiers/definitions/modifiers_mech_shields.dm b/code/modules/mob_modifiers/definitions/modifiers_mech_shields.dm new file mode 100644 index 00000000000..0c8d4112507 --- /dev/null +++ b/code/modules/mob_modifiers/definitions/modifiers_mech_shields.dm @@ -0,0 +1,166 @@ +/decl/mob_modifier/mechshield + name = "Mech Energy Shield" + hud_icon_state = "shield" + modifier_type = /datum/mob_modifier/object/mechshield + +/decl/mob_modifier/mechshield/on_modifier_datum_added(mob/living/_owner, datum/mob_modifier/modifier) + . = ..() + if(istype(modifier, /datum/mob_modifier/object)) + var/datum/mob_modifier/object/obj_modifier = modifier + if(istype(obj_modifier.object)) + flick("shield_raise", obj_modifier.object) + +/decl/mob_modifier/mechshield/on_modifier_datum_removed(mob/living/_owner, datum/mob_modifier/modifier) + if(istype(modifier, /datum/mob_modifier/object)) + var/datum/mob_modifier/object/obj_modifier = modifier + if(istype(obj_modifier.object)) + var/obj/effect/temporary/drop_shield = new(get_turf(_owner)) + drop_shield.appearance = obj_modifier.object + flick("shield_drop", drop_shield) + QDEL_IN(drop_shield, 1 SECOND) + return ..() + +/datum/mob_modifier/object/mechshield + object = /obj/abstract/follower/mechshield + +/obj/abstract/follower/mechshield + name = "mechshield" + layer = ABOVE_HUMAN_LAYER + plane = DEFAULT_PLANE + icon = 'icons/mecha/shield.dmi' + icon_state = "shield" + pixel_x = 8 + pixel_y = 4 + mouse_opacity = MOUSE_OPACITY_UNCLICKABLE + invisibility = INVISIBILITY_NONE + alpha = 255 + hide_on_init = FALSE + +/obj/abstract/follower/mechshield/follow_owner(atom/movable/owner) + . = ..() + layer = (dir == NORTH) ? MECH_UNDER_LAYER : initial(layer) + +/decl/mob_modifier/mechshield/check_modifiers_block_attack(mob/living/_owner, list/modifiers, attack_type, atom/movable/attacker, additional_data) + + if(attack_type == MM_ATTACK_TYPE_WEAPON) + return ..() + + . = MM_ATTACK_RESULT_NONE + var/shield_hit = FALSE + if(attack_type == MM_ATTACK_TYPE_PROJECTILE) + + var/obj/item/projectile/projectile = attacker + if(!istype(projectile)) + return + + for(var/datum/mob_modifier/modifier in modifiers) + var/obj/item/mech_equipment/shields/shield = modifier.source?.resolve() + if(!istype(shield) || !shield.charge) + continue + if(!shield_hit) + _owner.visible_message(SPAN_WARNING("\The [shield.owner]'s shields flash and crackle.")) + shield_hit = TRUE + new /obj/effect/effect/smoke/illumination(_owner.loc, 5, 4, 1, "#ffffff") + spark_at(_owner, amount=5) + projectile.damage = shield.stop_damage(projectile.damage) + if(projectile.damage <= 0) + . = (MM_ATTACK_RESULT_BLOCKED|MM_ATTACK_RESULT_DEFLECTED) + + else if(attack_type == MM_ATTACK_TYPE_THROWN) + + var/datum/thrownthing/thrown = additional_data + if(!istype(thrown) || thrown.speed > 5) + return + + for(var/datum/mob_modifier/modifier in modifiers) + var/obj/item/mech_equipment/shields/shield = modifier.source?.resolve() + if(istype(shield) && shield.charge) + _owner.visible_message(SPAN_WARNING("\The [shield.owner]'s shields flash briefly as they deflect \the [thrown.thrownthing].")) + shield_hit = TRUE + . = (MM_ATTACK_RESULT_BLOCKED|MM_ATTACK_RESULT_DEFLECTED) + break + + //light up the night. + if(shield_hit) + playsound(_owner,'sound/effects/basscannon.ogg', 20, 1) + for(var/datum/mob_modifier/object/mechshield/obj_modifier in modifiers) + if(obj_modifier.object) + flick("shield_impact", obj_modifier.object) + +/decl/mob_modifier/mech_ballistic + name = "Mech Ballistic Shield" + hud_icon_state = "nanomachines" + modifier_type = /datum/mob_modifier/object/mechshield_ballistic + +/datum/mob_modifier/object/mechshield_ballistic + object = /obj/abstract/follower/mechshield_ballistic + +/datum/mob_modifier/object/mechshield_ballistic/on_modifier_added(skip_update = FALSE) + . = ..() + var/obj/item/mech_equipment/source_atom = source?.resolve() + if(!istype(source_atom) || !istype(object) || !istype(owner, /mob/living/exosuit)) + return + var/mob/living/exosuit/mech = owner + for(var/hardpoint in mech.hardpoints) + var/obj/item/mech_equipment/hardpoint_object = mech.hardpoints[hardpoint] + if(source_atom != hardpoint_object) + continue + object.icon_state = "mech_shield_[hardpoint]" + var/image/mech_overlay = image(object.icon, "[object.icon_state]_over") + mech_overlay.layer = ABOVE_HUMAN_LAYER + object.add_overlay(mech_overlay, priority = TRUE) + +/obj/abstract/follower/mechshield_ballistic + icon = 'icons/mecha/ballistic_shield.dmi' + layer = MECH_UNDER_LAYER + plane = DEFAULT_PLANE + mouse_opacity = MOUSE_OPACITY_UNCLICKABLE + invisibility = INVISIBILITY_NONE + alpha = 255 + hide_on_init = FALSE + +/decl/mob_modifier/mech_ballistic/check_modifiers_block_attack(mob/living/_owner, list/modifiers, attack_type, atom/movable/attacker, additional_data) + + if(attack_type == MM_ATTACK_TYPE_PROJECTILE) + + var/obj/item/projectile/projectile = attacker + if(istype(projectile)) + + var/target_zone = BP_CHEST + if(isliving(attacker)) + var/mob/living/attacker_mob = attacker + target_zone = attacker_mob.get_target_zone() + + for(var/datum/mob_modifier/modifier in modifiers) + var/obj/item/mech_equipment/ballistic_shield/shield = modifier.source?.resolve() + if(istype(shield) && prob(shield.block_chance(projectile.damage, projectile.armor_penetration, source = projectile))) + _owner.visible_message(SPAN_WARNING("\The [projectile] is blocked by \the [_owner]'s [shield.name].")) + _owner.bullet_impact_visuals(projectile, target_zone, 0) + shield.on_block_attack() + return (MM_ATTACK_RESULT_BLOCKED|MM_ATTACK_RESULT_DEFLECTED) + + else if(attack_type == MM_ATTACK_TYPE_THROWN) + + var/datum/thrownthing/thrown = additional_data + if(istype(thrown)) + var/throw_damage = thrown.thrownthing.get_thrown_attack_force() * (thrown.speed/THROWFORCE_SPEED_DIVISOR) + for(var/datum/mob_modifier/modifier in modifiers) + var/obj/item/mech_equipment/ballistic_shield/shield = modifier.source?.resolve() + if(istype(shield) && prob(shield.block_chance(throw_damage, 0, source = thrown.thrownthing, attacker = thrown.thrower))) + _owner.visible_message(SPAN_WARNING("\The [thrown.thrownthing] bounces off \the [_owner]'s [shield].")) + playsound(_owner.loc, 'sound/weapons/Genhit.ogg', 50, 1) + shield.on_block_attack() + return (MM_ATTACK_RESULT_BLOCKED|MM_ATTACK_RESULT_DEFLECTED) + + else if(attack_type == MM_ATTACK_TYPE_WEAPON) + + var/obj/item/weapon = additional_data + if(istype(weapon)) + for(var/datum/mob_modifier/modifier in modifiers) + var/obj/item/mech_equipment/ballistic_shield/shield = modifier.source?.resolve() + if(shield && prob(shield.block_chance(weapon.get_attack_force(), weapon.armor_penetration, source = weapon, attacker = _owner))) + _owner.visible_message(SPAN_WARNING("\The [weapon] is blocked by \the [_owner]'s [shield.name].")) + playsound(_owner.loc, 'sound/weapons/Genhit.ogg', 50, 1) + return (MM_ATTACK_RESULT_BLOCKED|MM_ATTACK_RESULT_DEFLECTED) + + return ..() diff --git a/code/modules/mob_modifiers/definitions/modifiers_nanoswarm.dm b/code/modules/mob_modifiers/definitions/modifiers_nanoswarm.dm new file mode 100644 index 00000000000..ddb6d6023ea --- /dev/null +++ b/code/modules/mob_modifiers/definitions/modifiers_nanoswarm.dm @@ -0,0 +1,34 @@ +//This handy augment protects you to a degree, keeping it online after critical damage however is bad +/decl/mob_modifier/nanoswarm + name = "Defensive Nanoswarm" + desc = "You are surrounded by nanomachines that harden in response to projectiles." + hud_icon_state = "nanomachines" + on_add_message_1p = SPAN_NOTICE("Your skin tingles as the nanites spread over your body.") + on_end_message_1p = SPAN_WARNING("The nanites dissolve!") + +/decl/mob_modifier/nanoswarm/on_modifier_datum_added(mob/living/_owner, decl/mob_modifier/modifier) + . = ..() + playsound(_owner.loc,'sound/weapons/flash.ogg',35,1) + +/decl/mob_modifier/nanoswarm/check_modifiers_block_attack(mob/living/_owner, list/modifiers, attack_type, atom/movable/attacker, additional_data) + if(attack_type != MM_ATTACK_TYPE_PROJECTILE) + return ..() + + var/obj/item/organ/internal/augment/active/nanounit/unit + for(var/datum/mob_modifier/modifier in modifiers) + var/obj/item/organ/internal/augment/active/nanounit/implant = modifier.source?.resolve() + if(istype(implant) && implant.active && implant.charges >= 0) // active with 0 charges means it's about to critically fail. + unit = implant + break + + if(!istype(unit)) + return ..() + + _owner.visible_message(SPAN_WARNING("The nanomachines harden as a response to physical trauma!")) + playsound(_owner, 'sound/effects/basscannon.ogg',35,1) + unit.charges-- + if(unit.charges <= 0) + to_chat(_owner, SPAN_DANGER("Warning: Critical damage threshold passed. Shut down unit to avoid further damage.")) + else + unit.catastrophic_failure() + return MM_ATTACK_RESULT_BLOCKED|MM_ATTACK_RESULT_DEFLECTED diff --git a/code/modules/mob_modifiers/definitions/modifiers_object.dm b/code/modules/mob_modifiers/definitions/modifiers_object.dm new file mode 100644 index 00000000000..2904208d8c5 --- /dev/null +++ b/code/modules/mob_modifiers/definitions/modifiers_object.dm @@ -0,0 +1,19 @@ +/datum/mob_modifier/object + var/obj/object = /obj/abstract/follower + +/datum/mob_modifier/object/Destroy(force) + if(istype(object)) + if(owner) + events_repository.unregister(/decl/observ/moved, owner, object) + events_repository.unregister(/decl/observ/dir_set, owner, object) + QDEL_NULL(object) + return ..() + +/datum/mob_modifier/object/on_modifier_added(skip_update = FALSE) + . = ..() + if(istype(owner)) + if(ispath(object)) + object = new object(get_turf(owner)) + if(istype(object)) + events_repository.register(/decl/observ/moved, owner, object, TYPE_PROC_REF(/obj/abstract/follower, follow_owner)) + events_repository.register(/decl/observ/dir_set, owner, object, TYPE_PROC_REF(/obj/abstract/follower, follow_owner)) diff --git a/code/modules/mob_modifiers/definitions/modifiers_prone.dm b/code/modules/mob_modifiers/definitions/modifiers_prone.dm new file mode 100644 index 00000000000..caf5b30c53b --- /dev/null +++ b/code/modules/mob_modifiers/definitions/modifiers_prone.dm @@ -0,0 +1,10 @@ +/decl/mob_modifier/prone + name = "Prone" + desc = "You are lying prone and may need to stand up before taking action." + hud_icon_state = "prone" + show_indefinite_duration = FALSE + +/decl/mob_modifier/prone/on_modifier_datum_click(mob/living/_owner, decl/mob_modifier/modifier, params) + if(_owner.current_posture?.prone) + _owner.lay_down() + return TRUE diff --git a/code/modules/mob_modifiers/definitions/modifiers_regeneration.dm b/code/modules/mob_modifiers/definitions/modifiers_regeneration.dm new file mode 100644 index 00000000000..da18d3f8059 --- /dev/null +++ b/code/modules/mob_modifiers/definitions/modifiers_regeneration.dm @@ -0,0 +1,123 @@ +/decl/mob_modifier/regeneration + name = "Regeneration" + desc = "You are rapidly recovering from physical trauma and poisons." + hud_icon_state = "regeneration" + can_be_admin_granted = TRUE + + var/brute_mult = 1 + var/fire_mult = 1 + var/tox_mult = 1 + +/decl/mob_modifier/regeneration/on_modifier_datum_mob_life(mob/living/_owner, list/modifiers) + . = ..() + _owner.heal_damage(BRUTE, brute_mult, do_update_health = FALSE) + _owner.heal_damage(BURN, fire_mult, do_update_health = FALSE) + _owner.heal_damage(TOX, tox_mult) + +/decl/mob_modifier/regeneration/organ + name = "Organ Regeneration" + desc = "Your body is rapidly recovering from physical trauma and poisons, so long as you can feed it." + var/nutrition_damage_mult = 1 //How much nutrition it takes to heal regular damage + var/external_nutrition_mult = 50 // How much nutrition it takes to regrow a limb + var/organ_mult = 2 + var/regen_message = SPAN_WARNING("Your body throbs as you feel your ORGAN regenerate.") + var/grow_chance = 15 + var/grow_threshold = 200 + var/ignore_tag = BP_BRAIN //organ tag to ignore + var/last_nutrition_warning = 0 + var/innate_heal = TRUE // Whether the aura is on, basically. + +/decl/mob_modifier/regeneration/organ/proc/external_regeneration_effect(mob/living/_owner, obj/item/organ/external/limb) + return + +/decl/mob_modifier/regeneration/organ/on_modifier_datum_mob_life(mob/living/_owner, list/modifiers) + . = ..() + if(!length(_owner.get_external_organs())) + return + if(!innate_heal || _owner.has_mob_modifier(/decl/mob_modifier/stasis) || _owner.stat == DEAD) + return + if(_owner.get_nutrition() < nutrition_damage_mult) + low_nut_warning(_owner) + return + + var/update_health = FALSE + var/organ_regen = get_config_value(/decl/config/num/health_organ_regeneration_multiplier) + if(brute_mult && _owner.get_damage(BRUTE)) + update_health = TRUE + _owner.heal_damage(BRUTE, brute_mult * organ_regen, do_update_health = FALSE) + _owner.adjust_nutrition(-nutrition_damage_mult) + if(fire_mult && _owner.get_damage(BURN)) + update_health = TRUE + _owner.heal_damage(BURN, fire_mult * organ_regen, do_update_health = FALSE) + _owner.adjust_nutrition(-nutrition_damage_mult) + if(tox_mult && _owner.get_damage(TOX)) + update_health = TRUE + _owner.heal_damage(TOX, tox_mult * organ_regen, do_update_health = FALSE) + _owner.adjust_nutrition(-nutrition_damage_mult) + if(update_health) + _owner.update_health() + if(!can_regenerate_organs()) + return + if(organ_mult) + if(prob(10) && _owner.nutrition >= 150 && !_owner.get_damage(BRUTE) && !_owner.get_damage(BURN)) + var/obj/item/organ/external/D = GET_EXTERNAL_ORGAN(_owner, BP_HEAD) + if (D.status & ORGAN_DISFIGURED) + if (_owner.nutrition >= 20) + D.status &= ~ORGAN_DISFIGURED + _owner.adjust_nutrition(-20) + else + low_nut_warning(_owner, BP_HEAD) + + var/list/organs = _owner.get_internal_organs() + for(var/obj/item/organ/internal/regen_organ in shuffle(organs.Copy())) + if(BP_IS_PROSTHETIC(regen_organ) || regen_organ.organ_tag == ignore_tag) + continue + if(istype(regen_organ)) + if(regen_organ.get_organ_damage() > 0 && !(regen_organ.status & ORGAN_DEAD)) + if (_owner.nutrition >= organ_mult) + regen_organ.adjust_organ_damage(-(organ_mult)) + _owner.adjust_nutrition(-(organ_mult)) + if(prob(5)) + to_chat(_owner, replacetext(regen_message,"ORGAN", regen_organ.name)) + else + low_nut_warning(_owner, regen_organ.name) + + if(prob(grow_chance)) + var/decl/bodytype/root_bodytype = _owner.get_bodytype() + for(var/limb_type in root_bodytype.has_limbs) + var/obj/item/organ/external/limb = GET_EXTERNAL_ORGAN(_owner, limb_type) + if(limb && limb.organ_tag != BP_HEAD && !limb.is_vital_to_owner() && !limb.is_usable()) //Skips heads and vital bits... + if (_owner.nutrition > grow_threshold) + _owner.remove_organ(limb) //...because no one wants their head to explode to make way for a new one. + qdel(limb) + limb = null + else + low_nut_warning(_owner, limb.name) + if(!limb) + var/list/organ_data = root_bodytype.has_limbs[limb_type] + var/limb_path = organ_data["path"] + limb = new limb_path(_owner) + _owner.add_organ(limb, GET_EXTERNAL_ORGAN(_owner, limb.parent_organ), FALSE, FALSE) + _owner.adjust_nutrition(-external_nutrition_mult) + external_regeneration_effect(_owner, limb) + return + else if (_owner.nutrition > grow_threshold) //We don't subtract any nut here, but let's still only heal wounds when we have nut. + for(var/datum/wound/wound in limb.wounds) + if(wound.wound_damage() == 0 && prob(50)) + qdel(wound) + +/decl/mob_modifier/regeneration/organ/proc/low_nut_warning(mob/living/_owner, var/wound_type) + if (last_nutrition_warning + 1 MINUTE < world.time) + to_chat(_owner, SPAN_WARNING("You need more energy to regenerate your [wound_type || "wounds"].")) + last_nutrition_warning = world.time + return TRUE + return FALSE + +/decl/mob_modifier/regeneration/organ/proc/can_regenerate_organs() + return TRUE + +// Distinct type to avoid removing the wrong type on unwield. +/decl/mob_modifier/regeneration/item + name = "Regenerative Aura" + desc = "An item is helping your body heal physical damage and toxins." + can_be_admin_granted = FALSE \ No newline at end of file diff --git a/code/modules/mob_modifiers/definitions/modifiers_restrained.dm b/code/modules/mob_modifiers/definitions/modifiers_restrained.dm new file mode 100644 index 00000000000..6e281db036b --- /dev/null +++ b/code/modules/mob_modifiers/definitions/modifiers_restrained.dm @@ -0,0 +1,9 @@ +/decl/mob_modifier/restrained + name = "Restrained" + desc = "You are restrained and need to resist to get out of your bindings." + hud_icon_state = "restrained" + show_indefinite_duration = FALSE + +/decl/mob_modifier/restrained/on_modifier_datum_click(mob/living/_owner, decl/mob_modifier/modifier, params) + _owner.resist() + return TRUE diff --git a/code/modules/mob_modifiers/definitions/modifiers_shield.dm b/code/modules/mob_modifiers/definitions/modifiers_shield.dm new file mode 100644 index 00000000000..1dcda7a53e1 --- /dev/null +++ b/code/modules/mob_modifiers/definitions/modifiers_shield.dm @@ -0,0 +1,45 @@ +/decl/mob_modifier/shield + name = "Energy Shield" + desc = "You are protected from incoming projectiles." + hud_icon_state = "shield" + on_add_message_1p = SPAN_NOTICE("You feel your body prickle as your shield comes online.") + on_end_message_1p = SPAN_WARNING("Your shield goes offline!") + can_be_admin_granted = TRUE + +/decl/mob_modifier/shield/on_modifier_datum_added(mob/living/_owner, decl/mob_modifier/modifier) + . = ..() + if(. && _owner) + playsound(get_turf(_owner), 'sound/weapons/flash.ogg', 35, 1) + +/decl/mob_modifier/shield/on_modifier_datum_removed(mob/living/_owner, decl/mob_modifier/modifier) + . = ..() + if(. && _owner) + playsound(get_turf(_owner), 'sound/mecha/internaldmgalarm.ogg', 25,1) + +/decl/mob_modifier/shield/check_modifiers_block_attack(mob/living/_owner, list/modifiers, attack_type, atom/movable/attacker, additional_data) + if(attack_type != MM_ATTACK_TYPE_PROJECTILE) + return ..() + var/obj/item/projectile/projectile = attacker + if(istype(projectile)) + _owner.visible_message(SPAN_WARNING("\The [_owner]'s [src] flashes before \the [projectile] can hit them!")) + new /obj/effect/temporary(get_turf(_owner), 2 SECONDS, 'icons/obj/machines/shielding.dmi', "shield_impact") + playsound(_owner,'sound/effects/basscannon.ogg', 35, 1) + return (MM_ATTACK_RESULT_BLOCKED|MM_ATTACK_RESULT_DEFLECTED) + return MM_ATTACK_RESULT_NONE + +/decl/mob_modifier/shield/device + name = "Personal Shield" + desc = "You are protected from incoming projectiles by a personal shielding device - at least until it runs out of charges." + can_be_admin_granted = FALSE // Needs an item. + +/decl/mob_modifier/shield/device/check_modifiers_block_attack(mob/living/_owner, list/modifiers, attack_type, atom/movable/attacker, additional_data) + var/obj/item/projectile/projectile = attacker + if(!istype(projectile) || attack_type != MM_ATTACK_TYPE_PROJECTILE) + return ..() + var/found_shield = FALSE + for(var/datum/mob_modifier/modifier in modifiers) + var/obj/item/personal_shield/shield = modifier.source?.resolve() + if(istype(shield) && shield.expend_charge()) + found_shield = TRUE + break + return found_shield ? ..() : MM_ATTACK_RESULT_NONE diff --git a/code/modules/mob_modifiers/definitions/modifiers_stasis.dm b/code/modules/mob_modifiers/definitions/modifiers_stasis.dm new file mode 100644 index 00000000000..e855920a734 --- /dev/null +++ b/code/modules/mob_modifiers/definitions/modifiers_stasis.dm @@ -0,0 +1,26 @@ +/decl/mob_modifier/stasis + name = "Stasis" + desc = "Your life processes have been reduced or halted by stasis." + hud_icon_state = "stasis" + hide_expiry = TRUE + +/decl/mob_modifier/stasis/on_modifier_datum_mob_life(mob/living/_owner, list/modifiers) + . = ..() + + var/decl/bodytype/my_bodytype = _owner.get_bodytype() + if(my_bodytype?.body_flags & BODY_FLAG_NO_STASIS) + return + + var/stasis_power = 0 + for(var/datum/mob_modifier/modifier in modifiers) + var/atom/movable/source_atom = modifier.source?.resolve() + if(istype(source_atom)) + var/add_stasis = source_atom.get_cryogenic_power() + if(add_stasis) + stasis_power += add_stasis + to_chat(_owner, "[source_atom] gave [add_stasis]") + + if(stasis_power > 1 && GET_STATUS(_owner, STAT_DROWSY) < stasis_power * 4) + ADJ_STATUS(_owner, STAT_DROWSY, min(stasis_power, 3)) + if(_owner.stat == CONSCIOUS)// && prob(1)) + to_chat(_owner, SPAN_NOTICE("You feel slow and sluggish...")) diff --git a/code/modules/mob_modifiers/modifiers_datum.dm b/code/modules/mob_modifiers/modifiers_datum.dm new file mode 100644 index 00000000000..d7bc334dc52 --- /dev/null +++ b/code/modules/mob_modifiers/modifiers_datum.dm @@ -0,0 +1,75 @@ +// Subtype for tracking timer etc. No actual behavior associated with these. +/datum/mob_modifier + var/mob/living/owner + var/decl/mob_modifier/archetype + var/expire_time = MOB_MODIFIER_INDEFINITE + var/weakref/source + +/datum/mob_modifier/New(decl/mob_modifier/_archetype, mob/living/_owner, datum/_source) + archetype = istype(_archetype) ? _archetype : GET_DECL(_archetype) + owner = _owner + source = weakref(_source) + +/datum/mob_modifier/Destroy(force) + owner = null + return ..() + +// returns TRUE if the owner needs to run an update on mob modifiers following this run. +/datum/mob_modifier/proc/on_modifier_mob_life() + SHOULD_CALL_PARENT(TRUE) + . = FALSE + // We should not exist without an owner. + if(!istype(owner)) + qdel(src) + return TRUE + // Count down our timer, if necessary. + if(expire_time != MOB_MODIFIER_INDEFINITE) + . = TRUE + if(world.time >= expire_time) + on_modifier_expiry() + +/datum/mob_modifier/proc/on_modifier_removed(skip_update = FALSE) + SHOULD_CALL_PARENT(TRUE) + if(!istype(owner)) + return FALSE + var/list/modifiers = LAZYACCESS(owner._mob_modifiers, archetype) + if(!length(modifiers)) + return FALSE + modifiers -= src + // If this was our last modifier, clear the list. + if(!length(modifiers)) + LAZYREMOVE(owner._mob_modifiers, archetype) + archetype.on_modifier_datum_removed(owner, src) + if(!skip_update) + owner.refresh_hud_element(HUD_MODIFIERS) + if(archetype.mob_overlay_icon || archetype.mob_overlay_state) + owner.queue_icon_update() + qdel(src) + return TRUE + +/datum/mob_modifier/proc/on_modifier_added(skip_update = FALSE) + SHOULD_CALL_PARENT(TRUE) + if(!istype(owner)) + return FALSE + var/list/modifiers = LAZYACCESS(owner._mob_modifiers, archetype) + if(!modifiers) + modifiers = list() + LAZYSET(owner._mob_modifiers, archetype, modifiers) + if(src in modifiers) + return FALSE + modifiers += src + archetype.on_modifier_datum_added(owner, src) + if(!skip_update) + owner.refresh_hud_element(HUD_MODIFIERS) + if(archetype.mob_overlay_icon || archetype.mob_overlay_state) + owner.queue_icon_update() + return TRUE + +/datum/mob_modifier/proc/on_modifier_expiry() + SHOULD_CALL_PARENT(TRUE) + archetype.on_modifier_datum_expiry(owner, src) + return on_modifier_removed() + +/datum/mob_modifier/proc/on_modifier_click(params) + SHOULD_CALL_PARENT(TRUE) + archetype.on_modifier_datum_click(owner, src, params) diff --git a/code/modules/mob_modifiers/modifiers_helpers.dm b/code/modules/mob_modifiers/modifiers_helpers.dm new file mode 100644 index 00000000000..339ee093a85 --- /dev/null +++ b/code/modules/mob_modifiers/modifiers_helpers.dm @@ -0,0 +1,78 @@ + +/mob/living + // A modifier is a generalised effect on the mob, positive or negative, like buckling, healing or a curse. + var/list/_mob_modifiers + +/mob/living/proc/handle_mob_modifiers() + SHOULD_CALL_PARENT(TRUE) + for(var/decl/mob_modifier/archetype as anything in _mob_modifiers) + if(archetype.on_modifier_datum_mob_life(src, _mob_modifiers[archetype])) + . = TRUE + if(.) + refresh_hud_element(HUD_MODIFIERS) + +/mob/living/clear_mob_modifiers() + for(var/archetype as anything in _mob_modifiers) + for(var/datum/mob_modifier/modifier in _mob_modifiers[archetype]) + modifier.on_modifier_removed() + +/mob/living/remove_mob_modifier(decl/mob_modifier/archetype, datum/source, skip_update = FALSE) + + if(ispath(archetype)) + archetype = GET_DECL(archetype) + if(!istype(archetype)) + return FALSE + + // If we have no data, we can't clear it. + var/list/modifiers = LAZYACCESS(_mob_modifiers, archetype) + if(!length(modifiers)) + return FALSE + + // Source datum means we only remove an modifier that matches the source. + for(var/datum/mob_modifier/modifier as anything in modifiers) + if(!source || modifier.source?.resolve() == source) + modifier.on_modifier_removed() + . = TRUE + if(source) + return + + // We didn't find one to remove. Tragic. + return FALSE + +// If source is not provided, we only care that we have SOMETHING providing this modifier. +/mob/living/has_mob_modifier(decl/mob_modifier/archetype, datum/source) + if(ispath(archetype)) + archetype = GET_DECL(archetype) + if(!istype(archetype)) + return FALSE + var/list/modifiers = LAZYACCESS(_mob_modifiers, archetype) + if(!length(modifiers)) + return FALSE + if(!source) // We don't care about specifics. + return TRUE + for(var/datum/mob_modifier/modifier in modifiers) + if(modifier.source?.resolve() == source) + return TRUE + return FALSE + +/mob/living/add_mob_modifier(decl/mob_modifier/archetype, duration = MOB_MODIFIER_INDEFINITE, datum/source, skip_update = FALSE) + if(ispath(archetype)) + archetype = GET_DECL(archetype) + if(!istype(archetype) || !istype(source)) + return FALSE + + var/list/modifiers = LAZYACCESS(_mob_modifiers, archetype) + var/datum/mob_modifier/modifier + for(var/datum/mob_modifier/existing_modifier in modifiers) + if(existing_modifier.source?.resolve() == source) + modifier = existing_modifier + break + + if(!istype(modifier)) + modifier = new archetype.modifier_type(archetype, src, source) + if(duration != MOB_MODIFIER_INDEFINITE) + modifier.expire_time = world.time + duration + else + modifier.expire_time = MOB_MODIFIER_INDEFINITE + modifier.on_modifier_added(skip_update) + return TRUE diff --git a/code/modules/modular_computers/hardware/lan_port.dm b/code/modules/modular_computers/hardware/lan_port.dm index 8ffecb3d26a..c55d9da47a3 100644 --- a/code/modules/modular_computers/hardware/lan_port.dm +++ b/code/modules/modular_computers/hardware/lan_port.dm @@ -31,7 +31,7 @@ terminal = new(get_turf(parent)) set_extension(src, /datum/extension/event_registration/shuttle_stationary, GET_DECL(/decl/observ/moved), parent, PROC_REF(check_terminal_prox), get_area(src)) events_repository.register(/decl/observ/destroyed, terminal, src, PROC_REF(unset_terminal)) - set_status(parent, PART_STAT_CONNECTED) + set_component_status(parent, PART_STAT_CONNECTED) /obj/item/stock_parts/computer/lan_port/proc/unset_terminal() remove_extension(src, /datum/extension/event_registration/shuttle_stationary) diff --git a/code/modules/nano/nanoui.dm b/code/modules/nano/nanoui.dm index f2125ae38e3..c1dff1b5bf2 100644 --- a/code/modules/nano/nanoui.dm +++ b/code/modules/nano/nanoui.dm @@ -134,7 +134,7 @@ nanoui is used to open and update nano browser uis * * @return nothing */ -/datum/nanoui/proc/set_status(state, push_update) +/datum/nanoui/proc/set_nano_status(state, push_update) if (state != status) // Only update if it is different if (status == STATUS_DISABLED) status = state @@ -164,7 +164,7 @@ nanoui is used to open and update nano browser uis if(new_status == STATUS_CLOSE) close() return 1 - set_status(new_status, push_update) + set_nano_status(new_status, push_update) /** * Set the ui to auto update (every master_controller tick) diff --git a/code/modules/organs/external/_external_icons.dm b/code/modules/organs/external/_external_icons.dm index 61ed76c361c..e10a803445c 100644 --- a/code/modules/organs/external/_external_icons.dm +++ b/code/modules/organs/external/_external_icons.dm @@ -109,7 +109,7 @@ var/global/list/organ_icon_cache = list() global.organ_icon_cache[_icon_cache_key] = ret return ret -/obj/item/organ/external/proc/get_mob_overlays() +/obj/item/organ/external/proc/get_limb_mob_overlays() for(var/accessory_category in _sprite_accessories) var/list/draw_accessories = _sprite_accessories[accessory_category] for(var/accessory in draw_accessories) @@ -305,7 +305,7 @@ var/global/list/organ_icon_cache = list() icon = mob_icon // We may have some overlays of our own (hair, glowing eyes, layered markings) - var/list/additional_overlays = get_mob_overlays() + var/list/additional_overlays = get_limb_mob_overlays() if(length(additional_overlays)) for(var/new_overlay in additional_overlays) add_overlay(new_overlay) diff --git a/code/modules/organs/external/head.dm b/code/modules/organs/external/head.dm index e2d32062fb3..4b1886424b9 100644 --- a/code/modules/organs/external/head.dm +++ b/code/modules/organs/external/head.dm @@ -125,7 +125,7 @@ ret.Blend(eyes_icon, ICON_OVERLAY) return ret -/obj/item/organ/external/head/get_mob_overlays() +/obj/item/organ/external/head/get_limb_mob_overlays() . = ..() var/image/eye_glow = get_organ_eyes_overlay() if(eye_glow) diff --git a/code/modules/organs/internal/brain.dm b/code/modules/organs/internal/brain.dm index 0a83423de53..008ef91f52f 100644 --- a/code/modules/organs/internal/brain.dm +++ b/code/modules/organs/internal/brain.dm @@ -213,7 +213,7 @@ owner.custom_pain("Your head feels numb and painful.",10) if(is_bruised() && prob(1) && !HAS_STATUS(owner, STAT_BLURRY)) to_chat(owner, "It becomes hard to see for some reason.") - owner.set_status(STAT_BLURRY, 10) + owner.set_status_condition(STAT_BLURRY, 10) var/held = owner.get_active_held_item() if(_organ_damage >= 0.5*max_damage && prob(1) && held) to_chat(owner, "Your hand won't respond properly, and you drop what you are holding!") diff --git a/code/modules/organs/internal/heart.dm b/code/modules/organs/internal/heart.dm index 8930a70e6b9..785a2da4438 100644 --- a/code/modules/organs/internal/heart.dm +++ b/code/modules/organs/internal/heart.dm @@ -114,7 +114,7 @@ return //Dead or cryosleep people do not pump the blood. - if(!owner || owner.is_in_stasis() || owner.stat == DEAD || owner.bodytemperature < 170) + if(!owner || owner.has_mob_modifier(/decl/mob_modifier/stasis) || owner.stat == DEAD || owner.bodytemperature < 170) return if(pulse != PULSE_NONE || BP_IS_PROSTHETIC(src)) @@ -173,7 +173,7 @@ FONT_HUGE(SPAN_DANGER("Blood sprays out from your [spray_organ]!")) ) SET_STATUS_MAX(owner, STAT_STUN, 1) - owner.set_status(STAT_BLURRY, 2) + owner.set_status_condition(STAT_BLURRY, 2) //AB occurs every heartbeat, this only throttles the visible effect next_blood_squirt = world.time + 80 diff --git a/code/modules/projectiles/projectile.dm b/code/modules/projectiles/projectile.dm index 365338cf6ca..4feed2fd06c 100644 --- a/code/modules/projectiles/projectile.dm +++ b/code/modules/projectiles/projectile.dm @@ -227,7 +227,7 @@ var/result = PROJECTILE_FORCE_MISS if(hit_zone) def_zone = hit_zone //set def_zone, so if the projectile ends up hitting someone else later (to be implemented), it is more likely to hit the same part - if(!target_mob.aura_check(AURA_TYPE_BULLET, src,def_zone)) + if(target_mob.mob_modifiers_block_attack(MM_ATTACK_TYPE_PROJECTILE, src, def_zone)) return TRUE result = target_mob.bullet_act(src, def_zone) diff --git a/code/modules/reagents/chems/chems_drinks.dm b/code/modules/reagents/chems/chems_drinks.dm index b9ea85a8a9c..899ecf64a65 100644 --- a/code/modules/reagents/chems/chems_drinks.dm +++ b/code/modules/reagents/chems/chems_drinks.dm @@ -549,7 +549,7 @@ SET_STATUS_MAX(M, STAT_DIZZY, 20) ADJ_STATUS(M, STAT_DIZZY, 2) ADJ_STATUS(M, STAT_JITTER, 2) - M.set_status(STAT_DROWSY, 0) + M.set_status_condition(STAT_DROWSY, 0) /decl/material/liquid/drink/grenadine name = "grenadine syrup" diff --git a/code/modules/species/species.dm b/code/modules/species/species.dm index 82e201d287f..2e8495de0a8 100644 --- a/code/modules/species/species.dm +++ b/code/modules/species/species.dm @@ -174,8 +174,6 @@ var/global/const/DEFAULT_SPECIES_HEALTH = 200 var/pass_flags = 0 var/breathing_sound = 'sound/voice/monkey.ogg' - var/list/base_auras - var/job_skill_buffs = list() // A list containing jobs (/datum/job), with values the extra points that job receives. var/standing_jump_range = 2 @@ -412,21 +410,6 @@ var/global/const/DEFAULT_SPECIES_HEALTH = 200 /decl/species/proc/get_manual_dexterity(var/mob/living/human/H) . = manual_dexterity -/decl/species/proc/add_base_auras(var/mob/living/human/H) - if(base_auras) - for(var/type in base_auras) - H.add_aura(new type(H), skip_icon_update = TRUE) - -/decl/species/proc/remove_base_auras(var/mob/living/human/H) - if(base_auras) - var/list/bcopy = base_auras.Copy() - for(var/a in H.auras) - var/obj/aura/A = a - if(is_type_in_list(a, bcopy)) - bcopy -= A.type - H.remove_aura(A) - qdel(A) - /decl/species/proc/remove_inherent_verbs(var/mob/living/human/H) if(inherent_verbs) for(var/verb_path in inherent_verbs) @@ -441,7 +424,6 @@ var/global/const/DEFAULT_SPECIES_HEALTH = 200 /decl/species/proc/handle_post_spawn(var/mob/living/human/H) //Handles anything not already covered by basic species assignment. add_inherent_verbs(H) - add_base_auras(H) handle_movement_flags_setup(H) /decl/species/proc/handle_pre_spawn(var/mob/living/human/H) diff --git a/code/modules/status_conditions/_status.dm b/code/modules/status_conditions/_status_condition.dm similarity index 67% rename from code/modules/status_conditions/_status.dm rename to code/modules/status_conditions/_status_condition.dm index 49750b10a03..285748a63b8 100644 --- a/code/modules/status_conditions/_status.dm +++ b/code/modules/status_conditions/_status_condition.dm @@ -1,15 +1,31 @@ var/global/list/status_marker_holders = list() -// Check code/modules/mob/mob_status.dm code/modules/mob/living/living_status.dm -// for the procs that check/set/process these status conditions. +// Check code/modules/mob/mob_status.dm code/modules/mob/living/living_status.dm +// for the procs that check/set/process these status conditions. /decl/status_condition var/name var/check_flags = 0 var/list/victim_data + + var/hud_icon + var/hud_state + + var/decl/mob_modifier/associated_mob_modifier + var/status_marker_icon = 'icons/effects/status.dmi' var/status_marker_state var/status_marker_private = FALSE +/decl/status_condition/Initialize() + . = ..() + if(ispath(associated_mob_modifier)) + associated_mob_modifier = GET_DECL(associated_mob_modifier) + +/decl/status_condition/validate() + . = ..() + if(associated_mob_modifier && !istype(associated_mob_modifier)) + . += "invalid associated_mob_modifier '[associated_mob_modifier]'" + /decl/status_condition/proc/handle_changed_amount(var/mob/living/victim, var/new_amount, var/last_amount) set waitfor = FALSE diff --git a/code/modules/status_conditions/_status_markers.dm b/code/modules/status_conditions/_status_markers.dm index 9731e1881e6..c6e0f8ec8e5 100644 --- a/code/modules/status_conditions/_status_markers.dm +++ b/code/modules/status_conditions/_status_markers.dm @@ -1,3 +1,12 @@ +var/global/list/_status_marker_decls +/proc/get_status_marker_decls() + if(!global._status_marker_decls) + global._status_marker_decls = list() + for(var/decl/status_condition/cond as anything in decls_repository.get_decls_of_subtype_unassociated(/decl/status_condition)) + if(cond.status_marker_icon && cond.status_marker_state) + global._status_marker_decls += cond + return global._status_marker_decls + /obj/status_marker name = "" mouse_opacity = MOUSE_OPACITY_UNCLICKABLE @@ -58,18 +67,14 @@ mob_image_personal.layer = POINTER_LAYER animate(mob_image_personal, pixel_z = 1, time = 3, easing = (SINE_EASING | EASE_OUT), loop = -1) - animate( pixel_z = -1, time = 6, easing = SINE_EASING, loop = -1) - animate( pixel_z = 0, time = 3, easing = (SINE_EASING | EASE_IN), loop = -1) + animate( pixel_z = -1, time = 6, easing = SINE_EASING, loop = -1) + animate( pixel_z = 0, time = 3, easing = (SINE_EASING | EASE_IN), loop = -1) - var/list/all_status = decls_repository.get_decls_of_subtype(/decl/status_condition) - for(var/status_type in all_status) - var/decl/status_condition/status = all_status[status_type] + for(var/decl/status_condition/status in get_status_marker_decls()) if(status.status_marker_icon && status.status_marker_state) - var/obj/status_marker/marker = new(null, status) mob_image.add_vis_contents(marker) LAZYSET(markers, status, marker) - marker = new(null, status) mob_image_personal.add_vis_contents(marker) LAZYSET(markers_personal, status, marker) diff --git a/code/modules/status_conditions/status_dizzy.dm b/code/modules/status_conditions/definitions/status_dizzy.dm similarity index 100% rename from code/modules/status_conditions/status_dizzy.dm rename to code/modules/status_conditions/definitions/status_dizzy.dm diff --git a/code/modules/status_conditions/status_jittery.dm b/code/modules/status_conditions/definitions/status_jittery.dm similarity index 100% rename from code/modules/status_conditions/status_jittery.dm rename to code/modules/status_conditions/definitions/status_jittery.dm diff --git a/code/modules/status_conditions/status_paralyzed.dm b/code/modules/status_conditions/definitions/status_paralyzed.dm similarity index 100% rename from code/modules/status_conditions/status_paralyzed.dm rename to code/modules/status_conditions/definitions/status_paralyzed.dm diff --git a/code/modules/status_conditions/status_sleeping.dm b/code/modules/status_conditions/definitions/status_sleeping.dm similarity index 100% rename from code/modules/status_conditions/status_sleeping.dm rename to code/modules/status_conditions/definitions/status_sleeping.dm diff --git a/code/modules/status_conditions/status_stunned.dm b/code/modules/status_conditions/definitions/status_stunned.dm similarity index 100% rename from code/modules/status_conditions/status_stunned.dm rename to code/modules/status_conditions/definitions/status_stunned.dm diff --git a/code/modules/status_conditions/status_weakened.dm b/code/modules/status_conditions/definitions/status_weakened.dm similarity index 100% rename from code/modules/status_conditions/status_weakened.dm rename to code/modules/status_conditions/definitions/status_weakened.dm diff --git a/code/modules/xenoarcheaology/_xenoarch.dm b/code/modules/xenoarcheaology/_xenoarch.dm new file mode 100644 index 00000000000..b0ccad3e1f2 --- /dev/null +++ b/code/modules/xenoarcheaology/_xenoarch.dm @@ -0,0 +1,12 @@ +#define XA_EFFECT_TOUCH 0 +#define XA_EFFECT_AURA 1 +#define XA_EFFECT_PULSE 2 +#define XA_MAX_EFFECT 2 + +#define XA_EFFECT_UNKNOWN 0 +#define XA_EFFECT_ENERGY 1 +#define XA_EFFECT_PSIONIC 2 +#define XA_EFFECT_ELECTRO 3 +#define XA_EFFECT_PARTICLE 4 +#define XA_EFFECT_ORGANIC 5 +#define XA_EFFECT_SYNTH 6 \ No newline at end of file diff --git a/code/modules/xenoarcheaology/artifacts/effects/_effect.dm b/code/modules/xenoarcheaology/artifacts/effects/_effect.dm index 6d441a98c4c..f831aa2dd23 100644 --- a/code/modules/xenoarcheaology/artifacts/effects/_effect.dm +++ b/code/modules/xenoarcheaology/artifacts/effects/_effect.dm @@ -1,6 +1,6 @@ /datum/artifact_effect var/name = "unknown" - var/operation_type = EFFECT_TOUCH + var/operation_type = XA_EFFECT_TOUCH var/effect_range = 4 var/atom/holder var/activated = 0 @@ -14,7 +14,7 @@ /datum/artifact_effect/New(var/atom/location) ..() holder = location - operation_type = rand(0, MAX_EFFECT) + operation_type = rand(0, XA_MAX_EFFECT) var/triggertype = pick(subtypesof(/datum/artifact_trigger)) trigger = new triggertype @@ -39,7 +39,7 @@ /datum/artifact_effect/Destroy() QDEL_NULL(trigger) . = ..() - + /datum/artifact_effect/proc/ToggleActivate(var/reveal_toggle = 1) if(activated) activated = 0 @@ -64,9 +64,9 @@ /datum/artifact_effect/proc/process() if(activated) - if(operation_type == EFFECT_AURA) + if(operation_type == XA_EFFECT_AURA) DoEffectAura() - if(operation_type == EFFECT_PULSE) + if(operation_type == XA_EFFECT_PULSE) pulse_tick++ if(pulse_tick >= pulse_period) pulse_tick = 0 @@ -75,17 +75,17 @@ /datum/artifact_effect/proc/getDescription() . = "" switch(origin_type) - if(EFFECT_ENERGY) + if(XA_EFFECT_ENERGY) . += "Concentrated energy emissions" - if(EFFECT_PSIONIC) + if(XA_EFFECT_PSIONIC) . += "Intermittent psionic wavefront" - if(EFFECT_ELECTRO) + if(XA_EFFECT_ELECTRO) . += "Electromagnetic energy" - if(EFFECT_PARTICLE) + if(XA_EFFECT_PARTICLE) . += "High frequency particles" - if(EFFECT_ORGANIC) + if(XA_EFFECT_ORGANIC) . += "Organically reactive exotic particles" - if(EFFECT_SYNTH) + if(XA_EFFECT_SYNTH) . += "Atomic synthesis" else . += "Low level energy emissions" @@ -93,11 +93,11 @@ . += " have been detected " switch(operation_type) - if(EFFECT_TOUCH) + if(XA_EFFECT_TOUCH) . += "interspersed throughout substructure and shell." - if(EFFECT_AURA) + if(XA_EFFECT_AURA) . += "emitting in an ambient energy field." - if(EFFECT_PULSE) + if(XA_EFFECT_PULSE) . += "emitting in periodic bursts." else . += "emitting in an unknown way." diff --git a/code/modules/xenoarcheaology/artifacts/effects/badfeeling.dm b/code/modules/xenoarcheaology/artifacts/effects/badfeeling.dm index 02f4612a86d..8c9f2d98694 100644 --- a/code/modules/xenoarcheaology/artifacts/effects/badfeeling.dm +++ b/code/modules/xenoarcheaology/artifacts/effects/badfeeling.dm @@ -1,6 +1,6 @@ /datum/artifact_effect/badfeeling name = "badfeeling" - origin_type = EFFECT_PSIONIC + origin_type = XA_EFFECT_PSIONIC var/static/list/messages = list("You feel worried.", "Something doesn't feel right.", "You get a strange feeling in your gut.", diff --git a/code/modules/xenoarcheaology/artifacts/effects/cellcharge.dm b/code/modules/xenoarcheaology/artifacts/effects/cellcharge.dm index d441c9dd2dd..34b02a83da7 100644 --- a/code/modules/xenoarcheaology/artifacts/effects/cellcharge.dm +++ b/code/modules/xenoarcheaology/artifacts/effects/cellcharge.dm @@ -1,7 +1,7 @@ //todo /datum/artifact_effect/cellcharge name = "cell charge" - origin_type = EFFECT_ELECTRO + origin_type = XA_EFFECT_ELECTRO var/last_message /datum/artifact_effect/cellcharge/DoEffectTouch(var/mob/user) diff --git a/code/modules/xenoarcheaology/artifacts/effects/celldrain.dm b/code/modules/xenoarcheaology/artifacts/effects/celldrain.dm index 13cc32c5161..af5e8c2640e 100644 --- a/code/modules/xenoarcheaology/artifacts/effects/celldrain.dm +++ b/code/modules/xenoarcheaology/artifacts/effects/celldrain.dm @@ -1,7 +1,7 @@ //todo /datum/artifact_effect/celldrain name = "cell drain" - origin_type = EFFECT_ELECTRO + origin_type = XA_EFFECT_ELECTRO var/last_message /datum/artifact_effect/celldrain/DoEffectTouch(var/mob/user) diff --git a/code/modules/xenoarcheaology/artifacts/effects/dnaswitch.dm b/code/modules/xenoarcheaology/artifacts/effects/dnaswitch.dm index 4f4fa21b087..b599c8ab178 100644 --- a/code/modules/xenoarcheaology/artifacts/effects/dnaswitch.dm +++ b/code/modules/xenoarcheaology/artifacts/effects/dnaswitch.dm @@ -1,6 +1,6 @@ /datum/artifact_effect/dnaswitch name = "dnaswitch" - origin_type = EFFECT_ORGANIC + origin_type = XA_EFFECT_ORGANIC var/severity var/static/list/feels = list( "You feel a little different.", @@ -14,7 +14,7 @@ /datum/artifact_effect/dnaswitch/New() ..() - if(operation_type == EFFECT_AURA) + if(operation_type == XA_EFFECT_AURA) severity = rand(5,30) else severity = rand(25,95) diff --git a/code/modules/xenoarcheaology/artifacts/effects/emp.dm b/code/modules/xenoarcheaology/artifacts/effects/emp.dm index e22dd21e5b2..3fb29851f6e 100644 --- a/code/modules/xenoarcheaology/artifacts/effects/emp.dm +++ b/code/modules/xenoarcheaology/artifacts/effects/emp.dm @@ -1,10 +1,10 @@ /datum/artifact_effect/emp name = "emp" - origin_type = EFFECT_ELECTRO + origin_type = XA_EFFECT_ELECTRO /datum/artifact_effect/emp/New() ..() - operation_type = EFFECT_PULSE + operation_type = XA_EFFECT_PULSE /datum/artifact_effect/emp/DoEffectPulse() if(holder) diff --git a/code/modules/xenoarcheaology/artifacts/effects/forcefield.dm b/code/modules/xenoarcheaology/artifacts/effects/forcefield.dm index 08df28860c2..63dce153547 100644 --- a/code/modules/xenoarcheaology/artifacts/effects/forcefield.dm +++ b/code/modules/xenoarcheaology/artifacts/effects/forcefield.dm @@ -1,6 +1,6 @@ /datum/artifact_effect/forcefield name = "force field" - origin_type = EFFECT_PARTICLE + origin_type = XA_EFFECT_PARTICLE var/list/created_field var/field_color diff --git a/code/modules/xenoarcheaology/artifacts/effects/gas_generation.dm b/code/modules/xenoarcheaology/artifacts/effects/gas_generation.dm index dd66a9c5865..0d636d1a9bb 100644 --- a/code/modules/xenoarcheaology/artifacts/effects/gas_generation.dm +++ b/code/modules/xenoarcheaology/artifacts/effects/gas_generation.dm @@ -6,8 +6,8 @@ ..() if(!spawned_gas) spawned_gas = pick(decls_repository.get_decl_paths_of_subtype(/decl/material/gas)) - operation_type = pick(EFFECT_TOUCH, EFFECT_AURA) - origin_type = EFFECT_SYNTH + operation_type = pick((XA_EFFECT_TOUCH), (XA_EFFECT_AURA)) + origin_type = XA_EFFECT_SYNTH /datum/artifact_effect/gas/DoEffectTouch(var/mob/user) if(holder) diff --git a/code/modules/xenoarcheaology/artifacts/effects/goodfeeling.dm b/code/modules/xenoarcheaology/artifacts/effects/goodfeeling.dm index e5d88d10a30..ab6db622cf1 100644 --- a/code/modules/xenoarcheaology/artifacts/effects/goodfeeling.dm +++ b/code/modules/xenoarcheaology/artifacts/effects/goodfeeling.dm @@ -1,6 +1,6 @@ /datum/artifact_effect/goodfeeling name = "good feeling" - origin_type = EFFECT_PSIONIC + origin_type = XA_EFFECT_PSIONIC var/static/list/messages = list("You feel good.", "Everything seems to be going alright.", "You've got a good feeling about this.", diff --git a/code/modules/xenoarcheaology/artifacts/effects/heal.dm b/code/modules/xenoarcheaology/artifacts/effects/heal.dm index 73bf53bc022..8add3c13510 100644 --- a/code/modules/xenoarcheaology/artifacts/effects/heal.dm +++ b/code/modules/xenoarcheaology/artifacts/effects/heal.dm @@ -1,6 +1,6 @@ /datum/artifact_effect/heal name = "heal" - origin_type = EFFECT_ORGANIC + origin_type = XA_EFFECT_ORGANIC /datum/artifact_effect/heal/DoEffectTouch(var/mob/toucher) if(isliving(toucher)) diff --git a/code/modules/xenoarcheaology/artifacts/effects/hurt.dm b/code/modules/xenoarcheaology/artifacts/effects/hurt.dm index 238e8b99865..71d2cbd211a 100644 --- a/code/modules/xenoarcheaology/artifacts/effects/hurt.dm +++ b/code/modules/xenoarcheaology/artifacts/effects/hurt.dm @@ -1,6 +1,6 @@ /datum/artifact_effect/hurt name = "hurt" - origin_type = EFFECT_ORGANIC + origin_type = XA_EFFECT_ORGANIC /datum/artifact_effect/hurt/DoEffectTouch(var/mob/toucher) if(isliving(toucher)) diff --git a/code/modules/xenoarcheaology/artifacts/effects/radiate.dm b/code/modules/xenoarcheaology/artifacts/effects/radiate.dm index 591dd8c3a81..e4f24857c52 100644 --- a/code/modules/xenoarcheaology/artifacts/effects/radiate.dm +++ b/code/modules/xenoarcheaology/artifacts/effects/radiate.dm @@ -5,7 +5,7 @@ /datum/artifact_effect/radiate/New() ..() radiation_strength = rand(10, 50) - origin_type = pick(EFFECT_PARTICLE, EFFECT_ORGANIC) + origin_type = pick((XA_EFFECT_PARTICLE), (XA_EFFECT_ORGANIC)) /datum/artifact_effect/radiate/DoEffectTouch(var/mob/living/user) if(istype(user)) diff --git a/code/modules/xenoarcheaology/artifacts/effects/roboheal.dm b/code/modules/xenoarcheaology/artifacts/effects/roboheal.dm index 3b9b2668484..e2ad7fd0967 100644 --- a/code/modules/xenoarcheaology/artifacts/effects/roboheal.dm +++ b/code/modules/xenoarcheaology/artifacts/effects/roboheal.dm @@ -4,7 +4,7 @@ /datum/artifact_effect/roboheal/New() ..() - origin_type = pick(EFFECT_ELECTRO, EFFECT_PARTICLE) + origin_type = pick((XA_EFFECT_ELECTRO), (XA_EFFECT_PARTICLE)) /datum/artifact_effect/roboheal/DoEffectTouch(var/mob/user) if(isrobot(user)) diff --git a/code/modules/xenoarcheaology/artifacts/effects/robohurt.dm b/code/modules/xenoarcheaology/artifacts/effects/robohurt.dm index 0a83ddf57de..c5dde6b16b6 100644 --- a/code/modules/xenoarcheaology/artifacts/effects/robohurt.dm +++ b/code/modules/xenoarcheaology/artifacts/effects/robohurt.dm @@ -4,7 +4,7 @@ /datum/artifact_effect/robohurt/New() ..() - origin_type = pick(EFFECT_ELECTRO, EFFECT_PARTICLE) + origin_type = pick((XA_EFFECT_ELECTRO), (XA_EFFECT_PARTICLE)) /datum/artifact_effect/robohurt/DoEffectTouch(var/mob/user) if(isrobot(user)) diff --git a/code/modules/xenoarcheaology/artifacts/effects/sleepy.dm b/code/modules/xenoarcheaology/artifacts/effects/sleepy.dm index 6bb1478a0ba..f872eeccf49 100644 --- a/code/modules/xenoarcheaology/artifacts/effects/sleepy.dm +++ b/code/modules/xenoarcheaology/artifacts/effects/sleepy.dm @@ -9,7 +9,7 @@ /datum/artifact_effect/sleepy/New() ..() - origin_type = pick(EFFECT_PSIONIC, EFFECT_ORGANIC) + origin_type = pick((XA_EFFECT_PSIONIC), (XA_EFFECT_ORGANIC)) /datum/artifact_effect/sleepy/DoEffectTouch(var/mob/living/toucher) if(istype(toucher)) @@ -40,5 +40,5 @@ return if(prob(message_prob)) to_chat(H, SPAN_NOTICE(pick(sleepy_messages))) - H.set_status(STAT_DROWSY, min(GET_STATUS(H, STAT_DROWSY) + speed * weakness, limit * weakness)) - H.set_status(STAT_BLURRY, min(GET_STATUS(H, STAT_BLURRY) + speed * weakness, limit * weakness)) \ No newline at end of file + H.set_status_condition(STAT_DROWSY, min(GET_STATUS(H, STAT_DROWSY) + speed * weakness, limit * weakness)) + H.set_status_condition(STAT_BLURRY, min(GET_STATUS(H, STAT_BLURRY) + speed * weakness, limit * weakness)) \ No newline at end of file diff --git a/code/modules/xenoarcheaology/artifacts/effects/stun.dm b/code/modules/xenoarcheaology/artifacts/effects/stun.dm index 257a9976bf4..ac0c9598f88 100644 --- a/code/modules/xenoarcheaology/artifacts/effects/stun.dm +++ b/code/modules/xenoarcheaology/artifacts/effects/stun.dm @@ -3,7 +3,7 @@ /datum/artifact_effect/stun/New() ..() - origin_type = pick(EFFECT_PSIONIC, EFFECT_ORGANIC) + origin_type = pick((XA_EFFECT_PSIONIC), (XA_EFFECT_ORGANIC)) /datum/artifact_effect/stun/DoEffectTouch(var/mob/toucher) if(isliving(toucher)) diff --git a/code/modules/xenoarcheaology/artifacts/effects/teleport.dm b/code/modules/xenoarcheaology/artifacts/effects/teleport.dm index ac710fc71a3..255bdd62d2e 100644 --- a/code/modules/xenoarcheaology/artifacts/effects/teleport.dm +++ b/code/modules/xenoarcheaology/artifacts/effects/teleport.dm @@ -1,6 +1,6 @@ /datum/artifact_effect/teleport name = "teleport" - origin_type = EFFECT_PSIONIC + origin_type = XA_EFFECT_PSIONIC /datum/artifact_effect/teleport/DoEffectTouch(var/mob/user) teleport_away(user) diff --git a/code/modules/xenoarcheaology/artifacts/effects/temperature.dm b/code/modules/xenoarcheaology/artifacts/effects/temperature.dm index a50047249fb..4ca5b5e72bc 100644 --- a/code/modules/xenoarcheaology/artifacts/effects/temperature.dm +++ b/code/modules/xenoarcheaology/artifacts/effects/temperature.dm @@ -7,10 +7,10 @@ /datum/artifact_effect/temperature/New() ..() - operation_type = pick(EFFECT_TOUCH, EFFECT_AURA) - origin_type = pick(EFFECT_ORGANIC, EFFECT_SYNTH) + operation_type = pick((XA_EFFECT_TOUCH), (XA_EFFECT_AURA)) + origin_type = pick((XA_EFFECT_ORGANIC), (XA_EFFECT_SYNTH)) if(!direction) - direction = pick(ANOM_EFFECT_COOLING, ANOM_EFFECT_HEATING) + direction = pick((ANOM_EFFECT_COOLING), (ANOM_EFFECT_HEATING)) switch(direction) if(ANOM_EFFECT_COOLING) target_temp = rand(TCMB, T0C - 30) @@ -38,7 +38,7 @@ return air.temperature > target_temp if(ANOM_EFFECT_HEATING) return air.temperature < target_temp - + /datum/artifact_effect/temperature/proc/change_air_temp(datum/gas_mixture/air, degrees) var/new_temp = air.temperature + degrees if(direction == ANOM_EFFECT_COOLING) diff --git a/code/modules/xenoarcheaology/machinery/artifact_harvester.dm b/code/modules/xenoarcheaology/machinery/artifact_harvester.dm index 848a0033f32..15c69a09bbe 100644 --- a/code/modules/xenoarcheaology/machinery/artifact_harvester.dm +++ b/code/modules/xenoarcheaology/machinery/artifact_harvester.dm @@ -130,7 +130,7 @@ inserted_battery.battery_effect.process() //if the effect works by touch, activate it on anyone near the console - if(inserted_battery.battery_effect.operation_type == EFFECT_TOUCH) + if(inserted_battery.battery_effect.operation_type == (XA_EFFECT_TOUCH)) for(var/mob/M in hearers(1, src)) inserted_battery.battery_effect.DoEffectTouch(M) diff --git a/code/modules/xenoarcheaology/tools/ano_device_battery.dm b/code/modules/xenoarcheaology/tools/ano_device_battery.dm index 86f037fd0f8..fcc690b4642 100644 --- a/code/modules/xenoarcheaology/tools/ano_device_battery.dm +++ b/code/modules/xenoarcheaology/tools/ano_device_battery.dm @@ -110,12 +110,12 @@ if(!inserted_battery.battery_effect.activated) inserted_battery.battery_effect.ToggleActivate(1) switch(inserted_battery.battery_effect.operation_type) - if(EFFECT_TOUCH) + if(XA_EFFECT_TOUCH) visible_message("\The [src] shudders.") if(ismob(loc)) inserted_battery.battery_effect.DoEffectTouch(loc) inserted_battery.use_power(energy_consumed_on_touch) - if(EFFECT_PULSE) + if(XA_EFFECT_PULSE) inserted_battery.battery_effect.pulse_tick = inserted_battery.battery_effect.pulse_period //consume power relative to the time the artifact takes to charge and the effect range inserted_battery.use_power(inserted_battery.battery_effect.effect_range * inserted_battery.battery_effect.effect_range * inserted_battery.battery_effect.pulse_period) @@ -192,7 +192,7 @@ /obj/item/anodevice/use_on_mob(mob/living/target, mob/living/user, animate = TRUE) if (!istype(target)) return ..() - if(activated && inserted_battery?.battery_effect?.operation_type == EFFECT_TOUCH) + if(activated && inserted_battery?.battery_effect?.operation_type == XA_EFFECT_TOUCH) inserted_battery.battery_effect.DoEffectTouch(target) inserted_battery.use_power(energy_consumed_on_touch) user.visible_message(SPAN_NOTICE("\The [user] taps [target] with \the [src], and it shudders on contact.")) diff --git a/icons/mob/screen/styles/midnight/modifiers.dmi b/icons/mob/screen/styles/midnight/modifiers.dmi new file mode 100644 index 0000000000000000000000000000000000000000..6cc3b0b6b5d5ed77a6e0d0d91a428d293c4f9504 GIT binary patch literal 372 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=ffJ=Bkj05|`BCNNYRZm}jcXw6GIF(?Ma_x!v&tKcODZf}X z>DkfrpWCx}Cb!DU)-n`NQ2#T7o8t%2Icq#!977^n-%dB=YB3OS4c{=MY=X$PP3fC% zFy}qgEE4dXoirgcIA`Njp_K4uK8{cIQy-~+{MxuRZ$maiUl8Ih`ACxciLvn1NYw7 zv$7>HAfX3wY)%rLJ8#DLe42YeX}NNYRZm}jcXw6GIF(?Ma_x!v&tKcODZf}X z>DkfrpWCx}Cb!DU)-n`NQ2#T7o8t%2IUSxZjv*1PZ?A9UZ7|?rIlz7~rANL&bAnNc z%91w+7~~G?h6X8$91uFYyY8lXx&76skI!`iyNk~Ko?N4u%G{v&i21F>$%T7nmb%0Uyp9yT3_&9uKz=7F<4h)Pe0x-gf@!dYVvn{5|#>^)bU9w#r0?b+J d^p?jzV`-8%2)+2M_$$y&44$rjF6*2UngAN{h;#q| literal 0 HcmV?d00001 diff --git a/icons/mob/screen/styles/modifiers.dmi b/icons/mob/screen/styles/modifiers.dmi new file mode 100644 index 0000000000000000000000000000000000000000..fb652724b08c79f42d97b816ac23078be37ee300 GIT binary patch literal 233 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnL3?x0byx0z;m;-!5Tn`*LkmkKF1;}MA3GxeO zaCmkj4aljf3W+FjNi9w;$}A|!%+F(BsF)KRR!~&>{Y!Ac$FEPcymhtCojD)8A=Kca z@qJFl6i-n9lmGqL1)w{4JY5_^IA$g% bNZbMP7BDbAmG)l;WHETU`njxgN@xNAV=-0C=2r%CQcDFc1ddx%U)*U^gO!?G{sFI>0NCk{~iFMJ8yi#XZg2l43mW&9en_EkSF|@3kdiC005v#L_t(og=0K$-~huw0v2i+T5mNPb;Buc~oI&+vKs1^cn%Y(}Ct6SFzQ44hh6V)7mY&pj_ z>==s!sp|lk{Y!Ac$FEPcymhtCojD)8A=Kca z@qJFl6i-n9lmGqL1)w{4JY5_^IA$g% bNZbMP7BDbAmG)l;WHETU`njxgN@xNAV=-0C=2r%CQcDFc1ddx%U)*U^gO!?G{sFI>0NCk{~iFMJ8yi#XZg2l43mW&9en_EkSF|@3kdiC007}hL_t(oh3%KI4Z|Q1MGutHF|;U> z=kOX#;MqI@E4cIo82~AwJxFh*h%DI&v4nEAoBJKQ13pg__r)*_aHcL)2U**VCH>Cz zEdYR^AYg4bYTXp=LG<8U-;xnn9Bj7gS~p?2CN+TQOsawd^V|*AyZ?_f z#t73ieO08a0>E=ch}?iuDtr0cfP|FRaL5h(di`wRQ%qnN0$VzSK#7NfC(@G zo(FdO1Nou!00Q3M&DK~h#F_%B0j-;W=uJu?8%~6f`v#NQL`gqMHUv01oc^O1xo46K T(qe6*00000NkvXXu0mjf2Y0hA literal 0 HcmV?d00001 diff --git a/icons/mob/screen/styles/underworld/modifiers.dmi b/icons/mob/screen/styles/underworld/modifiers.dmi new file mode 100644 index 0000000000000000000000000000000000000000..f70a3571afb3d9ac8ed7365232b25bc752a6038a GIT binary patch literal 417 zcmV;S0bc%zP)$Sad{Xb7OL8aCB*J zZU6vyoKseCa&`CgQ*iP1^X@3b0oqnLDJt z{}JkDC^l99#?#~5V9ejZk$OHkqRF}Q7jzdynyzyNs~eqL1xRn6y0byfU8e%p291y(#T?t@iM;`-%m!*aG@Xxt11YmL*h>3}5Ya9Fd`4tux zCMPHVo-|7aD9cz9eukTAW;zSx}OhpU1#ZF(){zps4iwm*9er zU!Q1s>uQ}lb3S-OsKG_!2aj~l`)HnIDB?N0!@@Yo__DEAgG{pWx<`|aObSs5*3?ut z)Q|4$HdfudLSji@xA9sHLvztXZL3e6^*`xz+DEs`-%H2u=+dajgICY9zTsdfo}m6G z|NF5EKzI0fx;TbtOiWHVz{zru;b3}*85@%_V@t!v#S0d67*1;F^vGDT*mzPy;)abI zR~l?;$j-><_^^V@D?~y#C{ZaZN9IM3{-O(ug_JiXGBBvGRX3a+>huw4E`z75pUXO@ GgeCwAM|5le literal 0 HcmV?d00001 diff --git a/icons/obj/decals.dmi b/icons/obj/decals.dmi deleted file mode 100644 index f876357570a600200ab89209db0c652d8e554d85..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 568 zcmV-80>}M{P)|NqPY00000|M39kxB$$|0L%dY0L%aYng9Qp z0Q&7amH+?%0d!JMQvg8b*k%9#0C{>;Sad{Xb7OL8aCB*JZU6vyoKseCa&`CgQ*iP1 zyZsY&Qt#E@e{$V5 zf?;X(k6a4DnBJ0lf#|T_r9widmuml`}#Dh9R+#0)FcOKp{jx zo*@I+SP3D7_y#Kg-lKm?;9`apfCi|N>i2hIfdN#6?FhXB=tYEe zk5K3XH~~QE1HZ22RwfJK1PE4k;?*qVx1h|z#*?7Ug6u^(jegtQYnDFP2lWUI8)=%x z@+~9?btfWVZ^4oSMijPk%TleWajn-0O&^vD;g6rTZ|VsVX&pfqfCfDP0000V=-0C=2@&#?-^KoA7b`tB>1q!*)Nca0=SisT=bWX&xmce1E;x zcy|-r=##(nAvsY|X=GZ00005&q+i)`nrnbj^y zhmOD7W0nR5L6CW#*9=0rzg0x={EUno*t0l=L_HE_W+F`T2o4WL)$@iPAc|tm_+qh0 z4Uk7mYlnN|wXwX09M({&^SsRvFieBQ?Tf`C#>U35v9aM98yiEhSOm}W5Cp-L=_Zi4 zJJvJ@X?GM%4-iFB2JUA*6bgCB-&icxD#HnkX3%_QX&7Y!hIi-)5JgdrL?RwC!#2z8Sg+iWmIxYKrK9tMlx?_05^D1W@mn6>W_?yCNAYm8=tAT_z4XQ$b7{9c%B*)`% z&-wW|0H9nhBNmIv#PC9)U`Yg*gF!3@gAH2JAj~v?(WfGS7@ta|JbU5&T416JDgq=)0-gKm3a}Bl-TeWI0J`d<3m-ucWIG-}t3MqAq`hs~ zU^~BNI|P7x<9$9K{C>YJ(IZ$629c{&kgF(MeE#$)rZ}$s9#O9<#9bC3vrkujgM)(r z0KeaFtLht%R>? z642=ZbQ+HYbb0`thHKN{)>b@AU$3tV({`Sp-x*Ln|9a(u`MfLB;MP_=J2y9{Dp>aS z_gAfwFuya9_4})Nx~)*~23RDxE(BP{1Hjze+_u&$SYR0s0DgZpuk{MRWds-*Pf(8p z+W4N~`*w29B0;ACn?HVSx}1#u^t-FS5%dfLHzngfXtp?X8t`q%oPgibttG(B3#{nC z{LVmjVpbml0B~}k*8ye-{QLJM^JoXw*M;f*{e9h<-l_<`Ub&b)Iq(KAjXsPp;>E2gu`LE zQn^+x?t+E;ptshaOePIO$V>pO^b-NRDXB&9t}XBP>xpqR3xvaAxmYaX)vK4_xL$no z%V+rH`wIZT-rgRf(I~>9Q8N(b$% zTe-(D1O`^r8UWPSfJ)^W3kwUXw(Ri{fMINIZr1K;H3|hUwC>Jo157-C7Cp-X=mEIJ z62AO-5FdW`Ppz3-EP-1r;mKEj0r=nWahCeqx##4-i=JTv5uB}}XIQz1hT|bHJ^2jT z<0ITwZ&mG=Z*S4}@%v7{PKyA*j(MsrK)0K&28UkQe7y|(@k1Ga5@_6_^47|)%C+*b zy!9bq2aeVO9M_Azy*&V^X~E@N#S@~@C;-&7z%4Kg0c{;%2So9;Zr|)rZtUWDz>DVr zujxIGZipn4NzcNi{k2bY~?!YEdY7nde$CJ>a9!KD+O02^uk+LO^3UbBU}YVDgJ5Ug= PSI_RANK_GRANDMASTER) ADJ_STATUS(target, STAT_PARA, -1) - target.set_status(STAT_DROWSY, 0) + target.set_status_condition(STAT_DROWSY, 0) if(isliving(target)) var/mob/living/M = target M.adjust_hallucination(-30) diff --git a/mods/gamemodes/cult/mobs/constructs/constructs.dm b/mods/gamemodes/cult/mobs/constructs/constructs.dm index 228b834cc2d..14290066b31 100644 --- a/mods/gamemodes/cult/mobs/constructs/constructs.dm +++ b/mods/gamemodes/cult/mobs/constructs/constructs.dm @@ -124,7 +124,7 @@ _base_attack_force = 30 /mob/living/simple_animal/construct/armoured/handle_regular_status_updates() - set_status(STAT_WEAK, 0) + set_status_condition(STAT_WEAK, 0) if ((. = ..())) return diff --git a/mods/mobs/borers/mob/borer/borer.dm b/mods/mobs/borers/mob/borer/borer.dm index f83d77f9fb0..379bbca678c 100644 --- a/mods/mobs/borers/mob/borer/borer.dm +++ b/mods/mobs/borers/mob/borer/borer.dm @@ -102,8 +102,8 @@ /mob/living/simple_animal/borer/handle_vision() . = ..() - set_status(STAT_BLIND, host ? GET_STATUS(host, STAT_BLIND) : 0) - set_status(STAT_BLURRY, host ? GET_STATUS(host, STAT_BLURRY) : 0) + set_status_condition(STAT_BLIND, host ? GET_STATUS(host, STAT_BLIND) : 0) + set_status_condition(STAT_BLURRY, host ? GET_STATUS(host, STAT_BLURRY) : 0) /mob/living/simple_animal/borer/handle_disabilities() . = ..() diff --git a/mods/species/drakes/drake_abilities_friendly.dm b/mods/species/drakes/drake_abilities_friendly.dm index a224540e988..55d0ccaabd9 100644 --- a/mods/species/drakes/drake_abilities_friendly.dm +++ b/mods/species/drakes/drake_abilities_friendly.dm @@ -49,7 +49,7 @@ var/global/list/_wounds_being_tended_by_drakes = list() return TRUE // Are we already regenerating? - if(friend.has_aura(/obj/aura/sifsap_salve)) + if(friend.has_mob_modifier(/decl/mob_modifier/sifsap_salve)) if(friend == user) to_chat(user, SPAN_WARNING("Your wounds have already been cleaned.")) else @@ -72,7 +72,7 @@ var/global/list/_wounds_being_tended_by_drakes = list() var/friend_ref = "\ref[friend]" global._wounds_being_tended_by_drakes[friend_ref] = world.time + (8 SECONDS) - if(!do_after(user, 8 SECONDS, friend) || QDELETED(friend) || friend.has_aura(/obj/aura/sifsap_salve) || user.incapacitated() || !drake_spend_sap(user, 10)) + if(!do_after(user, 8 SECONDS, friend) || QDELETED(friend) || friend.has_mob_modifier(/decl/mob_modifier/sifsap_salve) || user.incapacitated() || !drake_spend_sap(user, 10)) global._wounds_being_tended_by_drakes -= friend_ref return TRUE @@ -86,7 +86,7 @@ var/global/list/_wounds_being_tended_by_drakes = list() // Sivian animals get a heal buff from the modifier, others just // get it to stop friendly drakes constantly licking their wounds. // Organ wounds are closed, but the owners get sifsap injected via open wounds. - friend.add_aura(new /obj/aura/sifsap_salve(friend, 60 SECONDS)) + friend.add_mob_modifier(/decl/mob_modifier/sifsap_salve, 60 SECONDS, source = user) var/list/friend_organs = friend.get_external_organs() if(length(friend_organs)) for (var/obj/item/organ/external/E in friend_organs) diff --git a/mods/species/drakes/drake_modifiers.dm b/mods/species/drakes/drake_modifiers.dm index a540b0f0c3b..59366e7cfa7 100644 --- a/mods/species/drakes/drake_modifiers.dm +++ b/mods/species/drakes/drake_modifiers.dm @@ -1,46 +1,33 @@ -/obj/aura/sifsap_salve - name = "Sifsap Salve" - icon = 'icons/effects/sparkles.dmi' - icon_state = "cyan_sparkles" - var/expiry - var/descriptor = "glowing sap" - -/obj/aura/sifsap_salve/Initialize(ml, _lifetime) - expiry = world.time + _lifetime - return ..() - -/obj/aura/sifsap_salve/added_to(var/mob/living/L) - ..() - to_chat(user, SPAN_NOTICE("The [descriptor] seethes and bubbles in your wounds, tingling and stinging.")) - -/obj/aura/sifsap_salve/removed() - to_chat(user, SPAN_NOTICE("The last of the [descriptor] in your wounds fizzles away.")) - ..() - -/obj/aura/sifsap_salve/life_tick() - - if(!user || user.stat == DEAD || user.isSynthetic()) - return 0 - - if(world.time >= expiry) - if(user) - user.remove_aura(src) - return 0 - - if(!user.has_trait(/decl/trait/sivian_biochemistry)) - user.heal_damage(BRUTE, 1, do_update_health = FALSE) - user.heal_damage(BURN, 1, do_update_health = TRUE) - return 1 - - if(user.current_health >= user.get_max_health()) - return 0 - - if(user.current_posture?.prone) - user.heal_damage(BRUTE, 3, do_update_health = FALSE) - user.heal_damage(BURN, 3, do_update_health = FALSE) - user.heal_damage(TOX, 2, do_update_health = TRUE) +/decl/mob_modifier/sifsap_salve + name = "Sifsap Salve" + desc = "Your wounds have been cleaned with drake spittle, which is beneficial to drakes - and not great for anyone else." + hud_icon = 'mods/species/drakes/icons/sifsap.dmi' + hud_icon_state = "sifsap_hud" + mob_overlay_icon = 'icons/effects/sparkles.dmi' + mob_overlay_state = "cyan_sparkles" + /// Defined here to allow overriding in fantasy modpack. + var/descriptor = "glowing sap" + +/decl/mob_modifier/sifsap_salve/Initialize() + on_add_message_1p = SPAN_NOTICE("The [descriptor] seethes and bubbles in your wounds, tingling and stinging.") + on_end_message_1p = SPAN_NOTICE("The last of the [descriptor] in your wounds fizzles away.") + . = ..() + +/decl/mob_modifier/sifsap_salve/on_modifier_datum_mob_life(mob/living/owner, decl/mob_modifier/modifier) + . = ..() + if(!owner || owner.stat == DEAD || owner.isSynthetic()) + return + if(!owner.has_trait(/decl/trait/sivian_biochemistry)) + owner.heal_damage(BRUTE, 1, do_update_health = FALSE) + owner.heal_damage(BURN, 1, do_update_health = TRUE) + return + if(owner.current_health >= owner.get_max_health()) + return + if(owner.current_posture?.prone) + owner.heal_damage(BRUTE, 3, do_update_health = FALSE) + owner.heal_damage(BURN, 3, do_update_health = FALSE) + owner.heal_damage(TOX, 2, do_update_health = TRUE) else - user.heal_damage(BRUTE, 2, do_update_health = FALSE) - user.heal_damage(BURN, 2, do_update_health = FALSE) - user.heal_damage(TOX, 1, do_update_health = TRUE) - return 1 + owner.heal_damage(BRUTE, 2, do_update_health = FALSE) + owner.heal_damage(BURN, 2, do_update_health = FALSE) + owner.heal_damage(TOX, 1, do_update_health = TRUE) diff --git a/mods/species/drakes/icons/sifsap.dmi b/mods/species/drakes/icons/sifsap.dmi new file mode 100644 index 0000000000000000000000000000000000000000..6942ef6d839b6d1a2cf3dec26dc3805630a4d526 GIT binary patch literal 619 zcmV-x0+juUP)V=-0C=1w$FUBBAQT1AnfDbpxHne2vKWYAkY6w)V0lAZ!$bS~4sPdknB43G z?BeOnRrvRX!RyhJ`g3Xp2ID}gWPX=+M_Ozd23mNNxUc0%npEN{FnE&MYW(Ee9bB-m zi>C|UWE?U1U`Ag600FZ}L_t(oh3!`%Z-YP>{YWZEPLZZfHrY%}VNg~4i;AIUR)g9P zsjAt`6chawoT@r=s-nRnNQ1hhqGAHRYoSLu3KX-aD7k*$doOp7`;0IQVX=5S!2sB7 zen-Z1`h1#9o{mEhNRrqbm0vuf@ugr%0GrQdFP*yazNO@6?h5=JMSC+zViQRe9I&kM zF-_A>8oL1}jsx%k0I;QmF#zh>BI|LGPL~K+003aGDdGN^^*!LeD|p@<9l-i&dXVc1 z1W>)>0ML${VC-C1g#v+sZ97gF%apVszrZhRN(cG^W@}4s`VCo@RQ)H4_9ph!+59k}QA)R_afGC~(O9jH^seOD~=HBC}f+X0