From 97559bb6091054a7460198a1267d9fc29fed63f6 Mon Sep 17 00:00:00 2001 From: Drulikar Date: Thu, 15 Jun 2023 06:17:45 -0700 Subject: [PATCH 01/15] Initial component definition for weed_food --- code/datums/components/weed_food.dm | 148 ++++++++++++++++++ code/modules/cm_aliens/weeds.dm | 3 + code/modules/mob/living/carbon/human/death.dm | 1 + colonialmarines.dme | 1 + 4 files changed, 153 insertions(+) create mode 100644 code/datums/components/weed_food.dm diff --git a/code/datums/components/weed_food.dm b/code/datums/components/weed_food.dm new file mode 100644 index 000000000000..2a63b8a86329 --- /dev/null +++ b/code/datums/components/weed_food.dm @@ -0,0 +1,148 @@ +#define WEED_FOOD_DELAY 10 SECONDS + +/// A component that can be attached to a human to be merged with weeds after a delay +/// Attach this to any human that is dead and it should handle the rest +/datum/component/weed_food + dupe_mode = COMPONENT_DUPE_UNIQUE_PASSARGS + + /// Whether we are actively being merged + var/active = FALSE + /// Whether we are completely merged with weeds + var/merged = FALSE + var/timer_id = null + /// The weeds that we merging/merged with + var/obj/effect/alien/weeds/absorbing_weeds + /// The human mob that we are bound to + var/mob/living/carbon/human/parent_human + +/datum/component/weed_food/Initialize(...) + . = ..() + parent_human = parent + if(!istype(parent_human)) + return COMPONENT_INCOMPATIBLE + + start() + +/datum/component/weed_food/InheritComponent(datum/component/C, i_am_original) + . = ..() + message_admins("Handling duplicate Init on [parent_human]...") // TODO: Remove this + start() + +/datum/component/weed_food/Destroy(force, silent) + . = ..() + unmerge_with_weeds() + message_admins("Destroying on [parent_human]...") // TODO: Remove this + parent_human = null + +/datum/component/weed_food/RegisterWithParent() + . = ..() + RegisterSignal(parent_human, COMSIG_MOVABLE_MOVED, PROC_REF(on_move)) + RegisterSignal(parent_human, COMSIG_LIVING_REJUVENATED, PROC_REF(on_rejuv)) + RegisterSignal(parent_human, COMSIG_HUMAN_REVIVED, PROC_REF(on_rejuv)) + RegisterSignal(parent_human, COMSIG_HUMAN_SET_UNDEFIBBABLE, PROC_REF(start)) + +/datum/component/weed_food/UnregisterFromParent() + . = ..() + if(parent_human) + UnregisterSignal(parent_human, COMSIG_MOVABLE_MOVED) + UnregisterSignal(parent_human, COMSIG_LIVING_REJUVENATED) + UnregisterSignal(parent_human, COMSIG_HUMAN_REVIVED) + UnregisterSignal(parent_human, COMSIG_HUMAN_SET_UNDEFIBBABLE) + +/datum/component/weed_food/proc/on_move() + SIGNAL_HANDLER + if(absorbing_weeds) + UnregisterSignal(absorbing_weeds, COMSIG_PARENT_QDELETING) + + if(stop() || !merged) + start() + return + + var/turf/parent_turf = get_turf(parent_human) + absorbing_weeds = parent_turf?.weeds + if(absorbing_weeds) + RegisterSignal(absorbing_weeds, COMSIG_PARENT_QDELETING, PROC_REF(unmerge_with_weeds)) + +/datum/component/weed_food/proc/on_rejuv() + message_admins("on_rejuv [parent_human]") // TODO: Remove this + qdel(src) + +/datum/component/weed_food/proc/start(forced = FALSE) + SIGNAL_HANDLER + if(active) + return FALSE + if(merged) + return FALSE + if(QDELETED(parent_human)) + return FALSE + if(!parent_human.undefibbable) + message_admins("cant start [parent_human] because we are defibbable") // TODO: Remove this + return FALSE + if(parent_human.is_xeno_grabbable()) + message_admins("cant start [parent_human] because we are grabable") // TODO: Remove this + return FALSE + + var/turf/parent_turf = get_turf(parent_human) + if(parent_turf?.weeds) + absorbing_weeds = parent_turf.weeds + RegisterSignal(parent_turf.weeds, COMSIG_PARENT_QDELETING, PROC_REF(stop)) + else if(!forced) + message_admins("cant start [parent_human] because we aren't on weeds") // TODO: Remove this + return FALSE + + active = TRUE + timer_id = addtimer(CALLBACK(src, PROC_REF(merge_with_weeds)), WEED_FOOD_DELAY, TIMER_STOPPABLE|TIMER_UNIQUE|TIMER_DELETE_ME|TIMER_OVERRIDE) + + message_admins("started [parent_human]") // TODO: Remove this + return TRUE + +/datum/component/weed_food/proc/stop() + SIGNAL_HANDLER + if(!active) + return FALSE + + active = FALSE + deltimer(timer_id) + timer_id = null + + message_admins("stopped [parent_human]") // TODO: Remove this + return TRUE + +/datum/component/weed_food/proc/merge_with_weeds(force = FALSE) + if(merged) + return FALSE + + if(QDELETED(parent_human)) + return FALSE + + var/turf/parent_turf = get_turf(parent_human) + if(!force && !parent_turf?.weeds) + return FALSE + + active = FALSE + merged = TRUE + + if(absorbing_weeds) + UnregisterSignal(absorbing_weeds, COMSIG_PARENT_QDELETING) + absorbing_weeds = parent_turf?.weeds + if(absorbing_weeds) + RegisterSignal(absorbing_weeds, COMSIG_PARENT_QDELETING, PROC_REF(unmerge_with_weeds)) + + parent_human.density = FALSE + parent_human.anchored = TRUE + // TODO: Update icon + + message_admins("merged [parent_human]") // TODO: Remove this + return TRUE + +/datum/component/weed_food/proc/unmerge_with_weeds() + SIGNAL_HANDLER + merged = FALSE + absorbing_weeds = null + + parent_human.anchored = FALSE + // TODO: Update icon + + message_admins("unmerged [parent_human]") // TODO: Remove this + +#undef WEED_FOOD_DELAY diff --git a/code/modules/cm_aliens/weeds.dm b/code/modules/cm_aliens/weeds.dm index 0be2220994d8..ea440b6d12a6 100644 --- a/code/modules/cm_aliens/weeds.dm +++ b/code/modules/cm_aliens/weeds.dm @@ -77,6 +77,9 @@ if(T) T.weeds = src weeded_turf = T + for(var/mob/living/carbon/human/body in T) + if(body.stat & DEAD && !body.is_xeno_grabbable) // TODO: Are there any non-bursted bodies this applies to? + body.AddComponent(/datum/component/weed_food) RegisterSignal(src, list( COMSIG_ATOM_TURF_CHANGE, diff --git a/code/modules/mob/living/carbon/human/death.dm b/code/modules/mob/living/carbon/human/death.dm index becb5dcd6610..1c10d5990456 100644 --- a/code/modules/mob/living/carbon/human/death.dm +++ b/code/modules/mob/living/carbon/human/death.dm @@ -50,6 +50,7 @@ disable_lights() disable_special_items() disable_headsets() //Disable radios for dead people to reduce load + AddComponent(/datum/component/weed_food) if(pulledby && isxeno(pulledby)) // Xenos lose grab on dead humans pulledby.stop_pulling() //Handle species-specific deaths. diff --git a/colonialmarines.dme b/colonialmarines.dme index 9feb76faf408..707a9c556373 100644 --- a/colonialmarines.dme +++ b/colonialmarines.dme @@ -366,6 +366,7 @@ #include "code\datums\components\speed_modifier.dm" #include "code\datums\components\toxin_buildup.dm" #include "code\datums\components\weed_damage_reduction.dm" +#include "code\datums\components\weed_food.dm" #include "code\datums\components\xeno\shield_slash.dm" #include "code\datums\construction\construction_template.dm" #include "code\datums\construction\xenomorph\construction_template_xenomorph.dm" From 76481478b52381d7b345881e1ae992e2c7f4aff4 Mon Sep 17 00:00:00 2001 From: Drulikar Date: Thu, 15 Jun 2023 10:34:35 -0700 Subject: [PATCH 02/15] Fix overlay animation Hide name and description --- code/datums/components/weed_food.dm | 66 ++++++++++++++++++++++++---- code/modules/cm_aliens/weeds.dm | 2 +- icons/mob/xenos/weeds.dmi | Bin 16470 -> 46893 bytes 3 files changed, 59 insertions(+), 9 deletions(-) diff --git a/code/datums/components/weed_food.dm b/code/datums/components/weed_food.dm index 2a63b8a86329..e96f19d1e839 100644 --- a/code/datums/components/weed_food.dm +++ b/code/datums/components/weed_food.dm @@ -1,10 +1,20 @@ #define WEED_FOOD_DELAY 10 SECONDS -/// A component that can be attached to a human to be merged with weeds after a delay -/// Attach this to any human that is dead and it should handle the rest +/atom/movable/vis_obj/weed_food + icon = 'icons/mob/xenos/weeds.dmi' + icon_state = "human" + vis_flags = VIS_INHERIT_ID|VIS_INHERIT_DIR|VIS_INHERIT_LAYER + +/** + * A component that can be attached to a human to be merged with weeds after a delay + * Attach this to any human that is dead and it should handle the rest (currently no signal for weeds spreading) + */ /datum/component/weed_food dupe_mode = COMPONENT_DUPE_UNIQUE_PASSARGS + var/name = "weeds" + var/description = "Weird black weeds in the shape of a body..." + /// Whether we are actively being merged var/active = FALSE /// Whether we are completely merged with weeds @@ -14,6 +24,12 @@ var/obj/effect/alien/weeds/absorbing_weeds /// The human mob that we are bound to var/mob/living/carbon/human/parent_human + /// The overlay image when merged + var/atom/movable/vis_obj/weed_food/weed_appearance + /// The original description if our parent has TRAIT_SIMPLE_DESC: Assumes it wasn't also just left null + var/old_simple_desc = null + /// The original name for our parent (currently set at Initialize) + var/old_name /datum/component/weed_food/Initialize(...) . = ..() @@ -21,6 +37,11 @@ if(!istype(parent_human)) return COMPONENT_INCOMPATIBLE + // Save any simple description and name + if(HAS_TRAIT(src, TRAIT_SIMPLE_DESC)) + old_simple_desc = parent_human.desc + old_name = parent_human.name + start() /datum/component/weed_food/InheritComponent(datum/component/C, i_am_original) @@ -54,20 +75,25 @@ if(absorbing_weeds) UnregisterSignal(absorbing_weeds, COMSIG_PARENT_QDELETING) + // We moved, restart or start the proccess if(stop() || !merged) start() return + // If we somehow moved when we were merged, handle that var/turf/parent_turf = get_turf(parent_human) absorbing_weeds = parent_turf?.weeds if(absorbing_weeds) RegisterSignal(absorbing_weeds, COMSIG_PARENT_QDELETING, PROC_REF(unmerge_with_weeds)) + else + unmerge_with_weeds() /datum/component/weed_food/proc/on_rejuv() message_admins("on_rejuv [parent_human]") // TODO: Remove this qdel(src) -/datum/component/weed_food/proc/start(forced = FALSE) +/// Try to start the process to turn into weeds +/datum/component/weed_food/proc/start(force = FALSE) SIGNAL_HANDLER if(active) return FALSE @@ -86,7 +112,7 @@ if(parent_turf?.weeds) absorbing_weeds = parent_turf.weeds RegisterSignal(parent_turf.weeds, COMSIG_PARENT_QDELETING, PROC_REF(stop)) - else if(!forced) + else if(!force) message_admins("cant start [parent_human] because we aren't on weeds") // TODO: Remove this return FALSE @@ -96,6 +122,7 @@ message_admins("started [parent_human]") // TODO: Remove this return TRUE +/// Try to stop the process turning into weeds /datum/component/weed_food/proc/stop() SIGNAL_HANDLER if(!active) @@ -108,6 +135,7 @@ message_admins("stopped [parent_human]") // TODO: Remove this return TRUE +/// Finish becomming one with the weeds /datum/component/weed_food/proc/merge_with_weeds(force = FALSE) if(merged) return FALSE @@ -115,6 +143,9 @@ if(QDELETED(parent_human)) return FALSE + if(absorbing_weeds) + UnregisterSignal(absorbing_weeds, COMSIG_PARENT_QDELETING) + var/turf/parent_turf = get_turf(parent_human) if(!force && !parent_turf?.weeds) return FALSE @@ -122,26 +153,45 @@ active = FALSE merged = TRUE - if(absorbing_weeds) - UnregisterSignal(absorbing_weeds, COMSIG_PARENT_QDELETING) absorbing_weeds = parent_turf?.weeds if(absorbing_weeds) RegisterSignal(absorbing_weeds, COMSIG_PARENT_QDELETING, PROC_REF(unmerge_with_weeds)) parent_human.density = FALSE parent_human.anchored = TRUE - // TODO: Update icon + + // Update the sprite + weed_appearance = new() + if(absorbing_weeds) + weed_appearance.color = absorbing_weeds.color + parent_human.vis_contents += weed_appearance + + // Hide the examine info by using TRAIT_SIMPLE_DESC and replacing the name + ADD_TRAIT(parent_human, TRAIT_SIMPLE_DESC, TRAIT_SOURCE_HIVE) + parent_human.desc = description + parent_human.name = name message_admins("merged [parent_human]") // TODO: Remove this return TRUE +/// Undo the weedening /datum/component/weed_food/proc/unmerge_with_weeds() SIGNAL_HANDLER merged = FALSE absorbing_weeds = null parent_human.anchored = FALSE - // TODO: Update icon + + // Undo the sprite changes + parent_human.vis_contents -= weed_appearance + QDEL_NULL(weed_appearance) + + // Undo changes to the name and description + if(isnull(old_simple_desc)) + REMOVE_TRAIT(parent_human, TRAIT_SIMPLE_DESC, TRAIT_SOURCE_HIVE) + else + parent_human.desc = old_simple_desc + parent_human.name = old_name message_admins("unmerged [parent_human]") // TODO: Remove this diff --git a/code/modules/cm_aliens/weeds.dm b/code/modules/cm_aliens/weeds.dm index ea440b6d12a6..eede24413216 100644 --- a/code/modules/cm_aliens/weeds.dm +++ b/code/modules/cm_aliens/weeds.dm @@ -78,7 +78,7 @@ T.weeds = src weeded_turf = T for(var/mob/living/carbon/human/body in T) - if(body.stat & DEAD && !body.is_xeno_grabbable) // TODO: Are there any non-bursted bodies this applies to? + if(body.stat & DEAD && !body.is_xeno_grabbable()) body.AddComponent(/datum/component/weed_food) RegisterSignal(src, list( diff --git a/icons/mob/xenos/weeds.dmi b/icons/mob/xenos/weeds.dmi index 8eb4b2203cf6f680305449a38bf3413921c4dabc..c1ee22a5fe0a4c1fafb64258bea61ab2d3a8d449 100644 GIT binary patch literal 46893 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 G>i+?HJ`6|z literal 16470 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 bSRR%F%ZpG_!e#s$@c;uIQ|)R^$G86vO}RPT From 2bd35160e9e7da5f08956217fea41364bcaaaad5 Mon Sep 17 00:00:00 2001 From: Drulikar Date: Wed, 21 Jun 2023 06:10:14 -0700 Subject: [PATCH 03/15] Progress on hud removal, interactivity, and refactoring --- .../__DEFINES/dcs/signals/atom/signals_obj.dm | 2 + code/datums/components/weed_food.dm | 168 +++++++++++------- code/modules/cm_aliens/weeds.dm | 12 +- code/modules/gear_presets/corpses.dm | 2 +- code/modules/mob/living/carbon/human/death.dm | 26 ++- icons/mob/xenos/weeds.dmi | Bin 46893 -> 46897 bytes 6 files changed, 127 insertions(+), 83 deletions(-) diff --git a/code/__DEFINES/dcs/signals/atom/signals_obj.dm b/code/__DEFINES/dcs/signals/atom/signals_obj.dm index df53558834f6..f37d5f7a6554 100644 --- a/code/__DEFINES/dcs/signals/atom/signals_obj.dm +++ b/code/__DEFINES/dcs/signals/atom/signals_obj.dm @@ -4,6 +4,8 @@ /// From /obj/effect/alien/weeds/Initialize() #define COMSIG_WEEDNODE_GROWTH_COMPLETE "weednode_growth_complete" +/// From /obj/effect/alien/weeds/Initialize() +#define COMSIG_WEEDNODE_GROWTH "weednode_growth" /// From /obj/effect/alien/weeds/proc/on_weed_expand() #define COMSIG_WEEDNODE_CANNOT_EXPAND_FURTHER "weednode_cannot_expand_further" diff --git a/code/datums/components/weed_food.dm b/code/datums/components/weed_food.dm index e96f19d1e839..31db9087a14a 100644 --- a/code/datums/components/weed_food.dm +++ b/code/datums/components/weed_food.dm @@ -3,77 +3,99 @@ /atom/movable/vis_obj/weed_food icon = 'icons/mob/xenos/weeds.dmi' icon_state = "human" - vis_flags = VIS_INHERIT_ID|VIS_INHERIT_DIR|VIS_INHERIT_LAYER + vis_flags = VIS_INHERIT_DIR|VIS_INHERIT_PLANE|VIS_INHERIT_LAYER + name = "weeds" + desc = "Weird black weeds in the shape of a body..." + gender = PLURAL /** - * A component that can be attached to a human to be merged with weeds after a delay - * Attach this to any human that is dead and it should handle the rest (currently no signal for weeds spreading) + * A component that can be attached to a living mob to be merged with weeds after a delay. + * Attempting to attach a new weed_food even if one already exists is equivalent to calling start(). + * + * Attach this to any living mob that is dead (death or initialized dead) and it should handle the rest. */ /datum/component/weed_food dupe_mode = COMPONENT_DUPE_UNIQUE_PASSARGS - var/name = "weeds" - var/description = "Weird black weeds in the shape of a body..." - /// Whether we are actively being merged var/active = FALSE /// Whether we are completely merged with weeds var/merged = FALSE + /// Any active timer for a pending merge var/timer_id = null - /// The weeds that we merging/merged with + /// The weeds that we are merging/merged with var/obj/effect/alien/weeds/absorbing_weeds - /// The human mob that we are bound to - var/mob/living/carbon/human/parent_human + /// The living mob that we are bound to + var/mob/living/parent_mob + /// The turf that our parent is on + var/turf/parent_turf /// The overlay image when merged var/atom/movable/vis_obj/weed_food/weed_appearance - /// The original description if our parent has TRAIT_SIMPLE_DESC: Assumes it wasn't also just left null - var/old_simple_desc = null - /// The original name for our parent (currently set at Initialize) - var/old_name /datum/component/weed_food/Initialize(...) . = ..() - parent_human = parent - if(!istype(parent_human)) - return COMPONENT_INCOMPATIBLE - // Save any simple description and name - if(HAS_TRAIT(src, TRAIT_SIMPLE_DESC)) - old_simple_desc = parent_human.desc - old_name = parent_human.name + parent_mob = parent + //if(!istype(parent_mob)) + //return COMPONENT_INCOMPATIBLE + if(!istype(parent_mob, /mob/living/carbon/human)) + return COMPONENT_INCOMPATIBLE // At the moment we only support humans + + parent_turf = get_turf(parent_mob) start() /datum/component/weed_food/InheritComponent(datum/component/C, i_am_original) . = ..() - message_admins("Handling duplicate Init on [parent_human]...") // TODO: Remove this + + message_admins("Handling duplicate Init on [parent_mob]...") // TODO: Remove this start() /datum/component/weed_food/Destroy(force, silent) . = ..() + unmerge_with_weeds() - message_admins("Destroying on [parent_human]...") // TODO: Remove this - parent_human = null + message_admins("Destroying on [parent_mob]...") // TODO: Remove this + parent_mob = null + parent_turf = null /datum/component/weed_food/RegisterWithParent() . = ..() - RegisterSignal(parent_human, COMSIG_MOVABLE_MOVED, PROC_REF(on_move)) - RegisterSignal(parent_human, COMSIG_LIVING_REJUVENATED, PROC_REF(on_rejuv)) - RegisterSignal(parent_human, COMSIG_HUMAN_REVIVED, PROC_REF(on_rejuv)) - RegisterSignal(parent_human, COMSIG_HUMAN_SET_UNDEFIBBABLE, PROC_REF(start)) + + RegisterSignal(parent_mob, COMSIG_MOVABLE_MOVED, PROC_REF(on_move)) + RegisterSignal(parent_mob, COMSIG_LIVING_REJUVENATED, PROC_REF(on_rejuv)) + RegisterSignal(parent_mob, COMSIG_HUMAN_REVIVED, PROC_REF(on_rejuv)) + RegisterSignal(parent_mob, COMSIG_HUMAN_SET_UNDEFIBBABLE, PROC_REF(start)) + if(parent_turf) + RegisterSignal(parent_turf, COMSIG_WEEDNODE_GROWTH, PROC_REF(start)) /datum/component/weed_food/UnregisterFromParent() . = ..() - if(parent_human) - UnregisterSignal(parent_human, COMSIG_MOVABLE_MOVED) - UnregisterSignal(parent_human, COMSIG_LIVING_REJUVENATED) - UnregisterSignal(parent_human, COMSIG_HUMAN_REVIVED) - UnregisterSignal(parent_human, COMSIG_HUMAN_SET_UNDEFIBBABLE) + message_admins("UnregisterFromParent on [parent_mob]...") // TODO: Remove this + + if(parent_mob) + UnregisterSignal(parent_mob, COMSIG_MOVABLE_MOVED) + UnregisterSignal(parent_mob, COMSIG_LIVING_REJUVENATED) + UnregisterSignal(parent_mob, COMSIG_HUMAN_REVIVED) + UnregisterSignal(parent_mob, COMSIG_HUMAN_SET_UNDEFIBBABLE) + if(absorbing_weeds) + UnregisterSignal(absorbing_weeds, COMSIG_PARENT_QDELETING) + if(parent_turf) + UnregisterSignal(parent_turf, COMSIG_WEEDNODE_GROWTH) + +/// SIGNAL_HANDLER for COMSIG_MOVABLE_MOVED /datum/component/weed_food/proc/on_move() SIGNAL_HANDLER + if(absorbing_weeds) UnregisterSignal(absorbing_weeds, COMSIG_PARENT_QDELETING) + absorbing_weeds = null + if(parent_turf) + UnregisterSignal(parent_turf, COMSIG_WEEDNODE_GROWTH) + parent_turf = get_turf(parent_mob) + if(parent_turf) + RegisterSignal(parent_turf, COMSIG_WEEDNODE_GROWTH, PROC_REF(start)) // We moved, restart or start the proccess if(stop() || !merged) @@ -81,50 +103,57 @@ return // If we somehow moved when we were merged, handle that - var/turf/parent_turf = get_turf(parent_human) absorbing_weeds = parent_turf?.weeds if(absorbing_weeds) RegisterSignal(absorbing_weeds, COMSIG_PARENT_QDELETING, PROC_REF(unmerge_with_weeds)) else unmerge_with_weeds() +/// SIGNAL_HANDLER for COMSIG_LIVING_REJUVENATED and COMSIG_HUMAN_REVIVED /datum/component/weed_food/proc/on_rejuv() - message_admins("on_rejuv [parent_human]") // TODO: Remove this + SIGNAL_HANDLER + + message_admins("on_rejuv [parent_mob]") // TODO: Remove this qdel(src) /// Try to start the process to turn into weeds +/// SIGNAL_HANDLER for COMSIG_HUMAN_SET_UNDEFIBBABLE & COMSIG_WEEDNODE_GROWTH which should not set force TRUE /datum/component/weed_food/proc/start(force = FALSE) SIGNAL_HANDLER + if(active) return FALSE if(merged) return FALSE - if(QDELETED(parent_human)) - return FALSE - if(!parent_human.undefibbable) - message_admins("cant start [parent_human] because we are defibbable") // TODO: Remove this + if(QDELETED(parent_mob)) return FALSE - if(parent_human.is_xeno_grabbable()) - message_admins("cant start [parent_human] because we are grabable") // TODO: Remove this + if(parent_mob.is_xeno_grabbable()) + message_admins("cant start [parent_mob] because we are grabable") // TODO: Remove this return FALSE + if(!(parent_mob.status_flags & PERMANENTLY_DEAD)) + var/mob/living/carbon/human/parent_human = parent_mob + if(istype(parent_human) && !parent_human.undefibbable && !parent_human.is_revivable()) + message_admins("cant start [parent_mob] because we are defibbable") // TODO: Remove this + return FALSE - var/turf/parent_turf = get_turf(parent_human) if(parent_turf?.weeds) absorbing_weeds = parent_turf.weeds RegisterSignal(parent_turf.weeds, COMSIG_PARENT_QDELETING, PROC_REF(stop)) else if(!force) - message_admins("cant start [parent_human] because we aren't on weeds") // TODO: Remove this + message_admins("cant start [parent_mob] because we aren't on weeds") // TODO: Remove this return FALSE active = TRUE timer_id = addtimer(CALLBACK(src, PROC_REF(merge_with_weeds)), WEED_FOOD_DELAY, TIMER_STOPPABLE|TIMER_UNIQUE|TIMER_DELETE_ME|TIMER_OVERRIDE) - message_admins("started [parent_human]") // TODO: Remove this + message_admins("started [parent_mob]") // TODO: Remove this return TRUE /// Try to stop the process turning into weeds +/// Signal handler for COMSIG_PARENT_QDELETING of weeds /datum/component/weed_food/proc/stop() SIGNAL_HANDLER + if(!active) return FALSE @@ -132,67 +161,72 @@ deltimer(timer_id) timer_id = null - message_admins("stopped [parent_human]") // TODO: Remove this + message_admins("stopped [parent_mob]") // TODO: Remove this return TRUE /// Finish becomming one with the weeds /datum/component/weed_food/proc/merge_with_weeds(force = FALSE) if(merged) return FALSE - - if(QDELETED(parent_human)) + if(QDELETED(parent_mob)) return FALSE if(absorbing_weeds) UnregisterSignal(absorbing_weeds, COMSIG_PARENT_QDELETING) - var/turf/parent_turf = get_turf(parent_human) if(!force && !parent_turf?.weeds) return FALSE active = FALSE merged = TRUE + parent_mob.density = FALSE + parent_mob.anchored = TRUE + parent_mob.mouse_opacity = MOUSE_OPACITY_TRANSPARENT + parent_mob.plane = FLOOR_PLANE + + for(var/datum/mob_hud/hud in huds) + if(istype(hud, /datum/mob_hud/xeno)) + continue + if(!hud.hudmobs.Find(parent_mob)) + message_admins("[parent_mob] NOT PRESENT IN [hud]") + hud.remove_from_hud(parent_mob) + absorbing_weeds = parent_turf?.weeds if(absorbing_weeds) RegisterSignal(absorbing_weeds, COMSIG_PARENT_QDELETING, PROC_REF(unmerge_with_weeds)) - parent_human.density = FALSE - parent_human.anchored = TRUE - // Update the sprite weed_appearance = new() if(absorbing_weeds) weed_appearance.color = absorbing_weeds.color - parent_human.vis_contents += weed_appearance - - // Hide the examine info by using TRAIT_SIMPLE_DESC and replacing the name - ADD_TRAIT(parent_human, TRAIT_SIMPLE_DESC, TRAIT_SOURCE_HIVE) - parent_human.desc = description - parent_human.name = name + // For non-humans change the icon_state or something here + parent_mob.vis_contents += weed_appearance - message_admins("merged [parent_human]") // TODO: Remove this + message_admins("merged [parent_mob] on [parent_mob.layer]") // TODO: Remove this return TRUE /// Undo the weedening +/// SIGNAL_HANDLER for COMSIG_PARENT_QDELETING of weeds /datum/component/weed_food/proc/unmerge_with_weeds() SIGNAL_HANDLER + merged = FALSE absorbing_weeds = null - parent_human.anchored = FALSE + parent_mob.anchored = FALSE + parent_mob.mouse_opacity = MOUSE_OPACITY_ICON + parent_mob.plane = GAME_PLANE + + for(var/datum/mob_hud/hud in huds) + if(istype(hud, /datum/mob_hud/xeno)) + continue + hud.add_to_hud(parent_mob) // Undo the sprite changes - parent_human.vis_contents -= weed_appearance + parent_mob.vis_contents -= weed_appearance QDEL_NULL(weed_appearance) - // Undo changes to the name and description - if(isnull(old_simple_desc)) - REMOVE_TRAIT(parent_human, TRAIT_SIMPLE_DESC, TRAIT_SOURCE_HIVE) - else - parent_human.desc = old_simple_desc - parent_human.name = old_name - - message_admins("unmerged [parent_human]") // TODO: Remove this + message_admins("unmerged [parent_mob]") // TODO: Remove this #undef WEED_FOOD_DELAY diff --git a/code/modules/cm_aliens/weeds.dm b/code/modules/cm_aliens/weeds.dm index eede24413216..d5f989956d8e 100644 --- a/code/modules/cm_aliens/weeds.dm +++ b/code/modules/cm_aliens/weeds.dm @@ -73,13 +73,11 @@ else if(!hibernate && do_spread) addtimer(CALLBACK(src, PROC_REF(weed_expand)), WEED_BASE_GROW_SPEED / max(weed_strength, 1)) - var/turf/T = get_turf(src) - if(T) - T.weeds = src - weeded_turf = T - for(var/mob/living/carbon/human/body in T) - if(body.stat & DEAD && !body.is_xeno_grabbable()) - body.AddComponent(/datum/component/weed_food) + var/turf/turf = get_turf(src) + if(turf) + turf.weeds = src + weeded_turf = turf + SEND_SIGNAL(turf, COMSIG_WEEDNODE_GROWTH) // Currently for weed_food wakeup RegisterSignal(src, list( COMSIG_ATOM_TURF_CHANGE, diff --git a/code/modules/gear_presets/corpses.dm b/code/modules/gear_presets/corpses.dm index 9641ab96a1c0..53f6de131f8c 100644 --- a/code/modules/gear_presets/corpses.dm +++ b/code/modules/gear_presets/corpses.dm @@ -16,6 +16,7 @@ /datum/equipment_preset/corpse/load_status(mob/living/carbon/human/new_human) . = ..(new_human) + new_human.undefibbable = TRUE new_human.death(create_cause_data("existing"), TRUE) //Kills the new mob new_human.apply_damage(100, BRUTE) new_human.apply_damage(100, BRUTE) @@ -37,7 +38,6 @@ new_human.update_canmove() N.buckled_mob = new_human N.afterbuckle(new_human) - new_human.undefibbable = TRUE new_human.spawned_corpse = TRUE new_human.updatehealth() new_human.pulse = PULSE_NONE diff --git a/code/modules/mob/living/carbon/human/death.dm b/code/modules/mob/living/carbon/human/death.dm index 1c10d5990456..f5655069c505 100644 --- a/code/modules/mob/living/carbon/human/death.dm +++ b/code/modules/mob/living/carbon/human/death.dm @@ -41,7 +41,9 @@ if(stat == DEAD) species?.handle_dead_death(src, gibbed) return + GLOB.alive_human_list -= src + if(!gibbed) if(HAS_TRAIT(src, TRAIT_HARDCORE) || MODE_HAS_TOGGLEABLE_FLAG(MODE_HARDCORE_PERMA)) if(!(species.flags & IS_SYNTHETIC)) // Synths wont perma @@ -50,9 +52,10 @@ disable_lights() disable_special_items() disable_headsets() //Disable radios for dead people to reduce load - AddComponent(/datum/component/weed_food) + if(pulledby && isxeno(pulledby)) // Xenos lose grab on dead humans pulledby.stop_pulling() + //Handle species-specific deaths. if(species) species.handle_death(src, gibbed) @@ -67,16 +70,14 @@ // Finding the last guy for anti-delay. if(SSticker.mode && SSticker.mode.is_in_endgame && SSticker.current_state != GAME_STATE_FINISHED && is_mainship_level(z)) var/mob/last_living_human - for(var/mob/living/carbon/human/H as anything in GLOB.alive_human_list) - if(!is_mainship_level(H.z)) + for(var/mob/living/carbon/human/cur_human as anything in GLOB.alive_human_list) + if(!is_mainship_level(cur_human.z)) continue if(last_living_human) last_living_human = null break - last_living_human = H - if(last_living_human) - if((last_qm_callout + 2 MINUTES) > world.time) - return + last_living_human = cur_human + if(last_living_human && (last_qm_callout + 2 MINUTES) > world.time) last_qm_callout = world.time // Tell the xenos where the human is. xeno_announcement("I sense the last tallhost hiding in [get_area(last_living_human)].", XENO_HIVE_NORMAL, SPAN_ANNOUNCEMENT_HEADER_BLUE("[QUEEN_MOTHER_ANNOUNCE]")) @@ -104,4 +105,13 @@ if(HAS_TRAIT(src, TRAIT_HARDCORE)) death_message = "valiantly falls to the ground, dead, unable to continue." - return ..(cause, gibbed, death_message) + . = ..(cause, gibbed, death_message) + + // stat is now set + if(!gibbed) + AddComponent(/datum/component/weed_food) + else + var/datum/cause_data/death_data = cause + if(death_data?.cause_name == "existing") + // Somereason corpses have always been considered gibbed? + AddComponent(/datum/component/weed_food) diff --git a/icons/mob/xenos/weeds.dmi b/icons/mob/xenos/weeds.dmi index c1ee22a5fe0a4c1fafb64258bea61ab2d3a8d449..6b0c62f51b76de5703847189bfcce88add377cb6 100644 GIT binary patch delta 445 zcmV;u0Yd(*?gFvy0+1wsqk2?WbVOxyV{&P5bZKvH004NLrI*2OfUmw^?XnyB{%lU?-mw=KqJ8F!x@zue-gsdE2>HS=Cut zc+Xz=;JZ$nB~98LmVxV}GW$pyeW;tbk=^a=J+9@%D`ny% zN+2pg)Dlr4q9R1C5Vc0sBch&|s!)8UzF_hTroUhY2QP=l>#v?<{o0ev@}6XUtBS|u1Vj0QGU?km&oMaartp7KU^2ku5|be&BTTLkS(M2i z>tfwSWgdU^`(-hIx_x7}~lr^q)%2b6_tl;Os+%mHDwsOjK5 delta 441 zcmV;q0Y?6@?gFju0+1wspL$eSbVOxyV{&P5bZKvH004NLrI*2Of%nP#ww?Ht;$VO|as=HADBVH!Mbp0~ST{j&8hvTpLK z3?75{ZtiQR1v)?Yoz`n4yS(jkAwd*IAG0I_n%=XRV{_taWvreL3b>?w37OWz*K@L#w9w ze^k%%i`=sTZc(@D7Ih!QqHfhK>Q>#N?p(E~J1#Bi&R~nWZMUd3^@_b%q7(C jK~YujH}=>c|F+9C*zDH&H{=rt&6B@yyYf)8&;en!&;#0% From 92da5d88ac403deb263c3d3e57423f29af099301 Mon Sep 17 00:00:00 2001 From: Drulikar Date: Thu, 22 Jun 2023 10:04:52 -0700 Subject: [PATCH 04/15] Increase delays Fix weeds upgrading Fix force methods Refactoring --- code/datums/components/weed_food.dm | 46 +++++++++++++-------------- code/modules/gear_presets/corpses.dm | 6 +++- icons/mob/xenos/weeds.dmi | Bin 46897 -> 46894 bytes 3 files changed, 27 insertions(+), 25 deletions(-) diff --git a/code/datums/components/weed_food.dm b/code/datums/components/weed_food.dm index 31db9087a14a..5da09a51a5b4 100644 --- a/code/datums/components/weed_food.dm +++ b/code/datums/components/weed_food.dm @@ -1,4 +1,4 @@ -#define WEED_FOOD_DELAY 10 SECONDS +#define WEED_FOOD_DELAY 5 MINUTES /atom/movable/vis_obj/weed_food icon = 'icons/mob/xenos/weeds.dmi' @@ -21,6 +21,8 @@ var/active = FALSE /// Whether we are completely merged with weeds var/merged = FALSE + /// The time we were unmerged (just to handle weeds upgrading) + var/unmerged_time /// Any active timer for a pending merge var/timer_id = null /// The weeds that we are merging/merged with @@ -56,6 +58,7 @@ unmerge_with_weeds() message_admins("Destroying on [parent_mob]...") // TODO: Remove this + QDEL_NULL(weed_appearance) parent_mob = null parent_turf = null @@ -132,11 +135,15 @@ return FALSE if(!(parent_mob.status_flags & PERMANENTLY_DEAD)) var/mob/living/carbon/human/parent_human = parent_mob - if(istype(parent_human) && !parent_human.undefibbable && !parent_human.is_revivable()) - message_admins("cant start [parent_mob] because we are defibbable") // TODO: Remove this + message_admins("cant start [parent_mob] because we are defibbable revive status: [parent_human.is_revivable()]") // TODO: Remove this + if(istype(parent_human) && !parent_human.undefibbable) return FALSE if(parent_turf?.weeds) + if(unmerged_time == world.time) + // Weeds upgraded, re-merge now + return merge_with_weeds() + QDEL_NULL(weed_appearance) // if we're here, we know we aren't re-using the apperance absorbing_weeds = parent_turf.weeds RegisterSignal(parent_turf.weeds, COMSIG_PARENT_QDELETING, PROC_REF(stop)) else if(!force) @@ -144,7 +151,7 @@ return FALSE active = TRUE - timer_id = addtimer(CALLBACK(src, PROC_REF(merge_with_weeds)), WEED_FOOD_DELAY, TIMER_STOPPABLE|TIMER_UNIQUE|TIMER_DELETE_ME|TIMER_OVERRIDE) + timer_id = addtimer(CALLBACK(src, PROC_REF(merge_with_weeds), force), WEED_FOOD_DELAY, TIMER_STOPPABLE|TIMER_UNIQUE|TIMER_DELETE_ME|TIMER_OVERRIDE) message_admins("started [parent_mob]") // TODO: Remove this return TRUE @@ -177,6 +184,10 @@ if(!force && !parent_turf?.weeds) return FALSE + absorbing_weeds = parent_turf?.weeds + if(absorbing_weeds) + RegisterSignal(absorbing_weeds, COMSIG_PARENT_QDELETING, PROC_REF(unmerge_with_weeds)) + active = FALSE merged = TRUE @@ -184,20 +195,11 @@ parent_mob.anchored = TRUE parent_mob.mouse_opacity = MOUSE_OPACITY_TRANSPARENT parent_mob.plane = FLOOR_PLANE - - for(var/datum/mob_hud/hud in huds) - if(istype(hud, /datum/mob_hud/xeno)) - continue - if(!hud.hudmobs.Find(parent_mob)) - message_admins("[parent_mob] NOT PRESENT IN [hud]") - hud.remove_from_hud(parent_mob) - - absorbing_weeds = parent_turf?.weeds - if(absorbing_weeds) - RegisterSignal(absorbing_weeds, COMSIG_PARENT_QDELETING, PROC_REF(unmerge_with_weeds)) + parent_mob.remove_from_all_mob_huds() // Update the sprite - weed_appearance = new() + if(!weed_appearance) + weed_appearance = new() if(absorbing_weeds) weed_appearance.color = absorbing_weeds.color // For non-humans change the icon_state or something here @@ -212,20 +214,16 @@ SIGNAL_HANDLER merged = FALSE + unmerged_time = world.time + if(absorbing_weeds) // Just to supress errors if this proc is manually called + UnregisterSignal(absorbing_weeds, COMSIG_PARENT_QDELETING) absorbing_weeds = null parent_mob.anchored = FALSE parent_mob.mouse_opacity = MOUSE_OPACITY_ICON parent_mob.plane = GAME_PLANE - - for(var/datum/mob_hud/hud in huds) - if(istype(hud, /datum/mob_hud/xeno)) - continue - hud.add_to_hud(parent_mob) - - // Undo the sprite changes + parent_mob.add_to_all_mob_huds() parent_mob.vis_contents -= weed_appearance - QDEL_NULL(weed_appearance) message_admins("unmerged [parent_mob]") // TODO: Remove this diff --git a/code/modules/gear_presets/corpses.dm b/code/modules/gear_presets/corpses.dm index 53f6de131f8c..bda7301b31af 100644 --- a/code/modules/gear_presets/corpses.dm +++ b/code/modules/gear_presets/corpses.dm @@ -16,7 +16,12 @@ /datum/equipment_preset/corpse/load_status(mob/living/carbon/human/new_human) . = ..(new_human) + + // These two values matter because they are checked on death for weed_food new_human.undefibbable = TRUE + if(xenovictim) + new_human.chestburst = 2 + new_human.death(create_cause_data("existing"), TRUE) //Kills the new mob new_human.apply_damage(100, BRUTE) new_human.apply_damage(100, BRUTE) @@ -28,7 +33,6 @@ O = new_human.internal_organs_by_name[i] new_human.internal_organs_by_name -= i new_human.internal_organs -= O - new_human.chestburst = 2 new_human.update_burst() //buckle to nest var/obj/structure/bed/nest/N = locate() in get_turf(src) diff --git a/icons/mob/xenos/weeds.dmi b/icons/mob/xenos/weeds.dmi index 6b0c62f51b76de5703847189bfcce88add377cb6..794005d12ce4d93ea749989ee3c08fd319c3d2d9 100644 GIT binary patch delta 442 zcmV;r0Y(0??gFmv0+1wspn6nTbVOxyV{&P5bZKvH004NLrI*2Of1asF(Wp+#(y{MbGk=^a&J+9@%b&{;AyQOe{okJC$q`o&$D`ny% zN+4>Er~pwRq85l+B5H-GM?^g_RiXGyeZk}xOn<=)5X^z7L*R}IWx^(`!SmiHv6W8 z$GBK^Rhh@1{d}2!U0pw)S2+7mv}2DPhhP`l~|wdblq?Qv;Pdj=cSZo5J4gJrN_j9nxA0-ZOo zBOC)mdtlitY_lRMTNW0YWoe;V78ja@qeihTFf_{&Umw^?XnyB{%lU?-mw=KqJ8F!x@zue-gsdE2>HS=Cut zc+Xz=;JZ$nB~98LmVxV}GW$pyeW;tbk=^a=J+9@%D`ny% zN+2pg)Dlr4q9R1C5Vc0sBch&|s!)8UzF_hTroUhY2QP=l>#v?<{o0ev@}6XUtBS|u1Vj0QGU?km&oMaartp7KU^2ku5|be&BTTLkS(M2i z>tfwSWgdU^`(-hIx_x7}~lr^q)%2b6_tl;Os+%>iMxs;b~V From 3d24d39b33157e0004ad5347d078a367e644b547 Mon Sep 17 00:00:00 2001 From: Drulikar Date: Thu, 22 Jun 2023 10:05:09 -0700 Subject: [PATCH 05/15] Remove logging --- code/datums/components/weed_food.dm | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/code/datums/components/weed_food.dm b/code/datums/components/weed_food.dm index 5da09a51a5b4..1c36fa679d66 100644 --- a/code/datums/components/weed_food.dm +++ b/code/datums/components/weed_food.dm @@ -49,15 +49,12 @@ /datum/component/weed_food/InheritComponent(datum/component/C, i_am_original) . = ..() - - message_admins("Handling duplicate Init on [parent_mob]...") // TODO: Remove this start() /datum/component/weed_food/Destroy(force, silent) . = ..() unmerge_with_weeds() - message_admins("Destroying on [parent_mob]...") // TODO: Remove this QDEL_NULL(weed_appearance) parent_mob = null parent_turf = null @@ -75,8 +72,6 @@ /datum/component/weed_food/UnregisterFromParent() . = ..() - message_admins("UnregisterFromParent on [parent_mob]...") // TODO: Remove this - if(parent_mob) UnregisterSignal(parent_mob, COMSIG_MOVABLE_MOVED) UnregisterSignal(parent_mob, COMSIG_LIVING_REJUVENATED) @@ -115,8 +110,6 @@ /// SIGNAL_HANDLER for COMSIG_LIVING_REJUVENATED and COMSIG_HUMAN_REVIVED /datum/component/weed_food/proc/on_rejuv() SIGNAL_HANDLER - - message_admins("on_rejuv [parent_mob]") // TODO: Remove this qdel(src) /// Try to start the process to turn into weeds @@ -131,11 +124,9 @@ if(QDELETED(parent_mob)) return FALSE if(parent_mob.is_xeno_grabbable()) - message_admins("cant start [parent_mob] because we are grabable") // TODO: Remove this return FALSE if(!(parent_mob.status_flags & PERMANENTLY_DEAD)) var/mob/living/carbon/human/parent_human = parent_mob - message_admins("cant start [parent_mob] because we are defibbable revive status: [parent_human.is_revivable()]") // TODO: Remove this if(istype(parent_human) && !parent_human.undefibbable) return FALSE @@ -147,13 +138,11 @@ absorbing_weeds = parent_turf.weeds RegisterSignal(parent_turf.weeds, COMSIG_PARENT_QDELETING, PROC_REF(stop)) else if(!force) - message_admins("cant start [parent_mob] because we aren't on weeds") // TODO: Remove this return FALSE active = TRUE timer_id = addtimer(CALLBACK(src, PROC_REF(merge_with_weeds), force), WEED_FOOD_DELAY, TIMER_STOPPABLE|TIMER_UNIQUE|TIMER_DELETE_ME|TIMER_OVERRIDE) - message_admins("started [parent_mob]") // TODO: Remove this return TRUE /// Try to stop the process turning into weeds @@ -168,7 +157,6 @@ deltimer(timer_id) timer_id = null - message_admins("stopped [parent_mob]") // TODO: Remove this return TRUE /// Finish becomming one with the weeds @@ -205,7 +193,6 @@ // For non-humans change the icon_state or something here parent_mob.vis_contents += weed_appearance - message_admins("merged [parent_mob] on [parent_mob.layer]") // TODO: Remove this return TRUE /// Undo the weedening @@ -225,6 +212,4 @@ parent_mob.add_to_all_mob_huds() parent_mob.vis_contents -= weed_appearance - message_admins("unmerged [parent_mob]") // TODO: Remove this - #undef WEED_FOOD_DELAY From 83d3dc77f267ed793dd1e4d5082829bbcedb8e58 Mon Sep 17 00:00:00 2001 From: Drulikar Date: Thu, 22 Jun 2023 11:24:49 -0700 Subject: [PATCH 06/15] Prepare support for future xeno support Fix possible edgecase where a xeno transfer prevents the rest of the death proc of queen Fix unnecessary weed_food component adding to actually gibbed humans (it would get cleaned up, but a lot of unnecessary extra work) --- code/modules/mob/living/carbon/human/death.dm | 12 ++++++------ code/modules/mob/living/carbon/xenomorph/death.dm | 10 ++++++---- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/code/modules/mob/living/carbon/human/death.dm b/code/modules/mob/living/carbon/human/death.dm index f5655069c505..5c4c11a7adb5 100644 --- a/code/modules/mob/living/carbon/human/death.dm +++ b/code/modules/mob/living/carbon/human/death.dm @@ -108,10 +108,10 @@ . = ..(cause, gibbed, death_message) // stat is now set - if(!gibbed) + var/datum/cause_data/death_data = cause + if(!gibbed && death_data?.cause_name != "gibbing") + // Hilariously the gibbing proc causes death via droplimb which means gibbed is false... + AddComponent(/datum/component/weed_food) + else if(death_data?.cause_name == "existing") + // Corpses spawn as gibbed true to avoid sfx, even though they aren't actually gibbed... AddComponent(/datum/component/weed_food) - else - var/datum/cause_data/death_data = cause - if(death_data?.cause_name == "existing") - // Somereason corpses have always been considered gibbed? - AddComponent(/datum/component/weed_food) diff --git a/code/modules/mob/living/carbon/xenomorph/death.dm b/code/modules/mob/living/carbon/xenomorph/death.dm index ce3f55700753..517767c1d428 100644 --- a/code/modules/mob/living/carbon/xenomorph/death.dm +++ b/code/modules/mob/living/carbon/xenomorph/death.dm @@ -49,7 +49,7 @@ new_xeno.generate_name() if(!SSticker.mode.transfer_xeno(xeno_candidate, new_xeno)) qdel(new_xeno) - return + break new_xeno.visible_message(SPAN_XENODANGER("A larva suddenly burrows out of the ground!"), SPAN_XENODANGER("You burrow out of the ground after feeling an immense tremor through the hive, which quickly fades into complete silence...")) @@ -101,6 +101,11 @@ GLOB.hive_datum[hivenumber].stored_larva++ GLOB.hive_datum[hivenumber].hive_ui.update_burrowed_larva() + if(hardcore) + QDEL_IN(src, 3 SECONDS) + //else if(!gibbed) // At the moment we only support humans + //AddComponent(/datum/component/weed_food) + if(hive) hive.remove_xeno(src) // Finding the last xeno for anti-delay. @@ -119,9 +124,6 @@ to_chat(X, SPAN_XENOANNOUNCE("Your carapace rattles with dread. You are all that remains of the hive!")) announce_dchat("There is only one Xenomorph left: [X.name].", X) - if(hardcore) - QDEL_IN(src, 3 SECONDS) - SEND_GLOBAL_SIGNAL(COMSIG_GLOB_XENO_DEATH, src, gibbed) /mob/living/carbon/xenomorph/gib(datum/cause_data/cause = create_cause_data("gibbing", src)) From 007779ffad0f8d5ef21c057ece4471d9fe187ff8 Mon Sep 17 00:00:00 2001 From: Drulikar Date: Fri, 23 Jun 2023 23:03:09 -0700 Subject: [PATCH 07/15] Fix animations not replicating (now explicitly sets each state) Fix rollers (now there is a signal for afterbuckle) Fix coffins (now closets also check for anchored) --- .../__DEFINES/dcs/signals/atom/signals_obj.dm | 3 + code/datums/components/weed_food.dm | 192 ++++++++++++------ code/game/objects/objs.dm | 1 + .../structures/crates_lockers/closets.dm | 2 + icons/mob/xenos/weeds.dmi | Bin 46894 -> 47070 bytes 5 files changed, 140 insertions(+), 58 deletions(-) diff --git a/code/__DEFINES/dcs/signals/atom/signals_obj.dm b/code/__DEFINES/dcs/signals/atom/signals_obj.dm index f37d5f7a6554..aebd0d09d0d2 100644 --- a/code/__DEFINES/dcs/signals/atom/signals_obj.dm +++ b/code/__DEFINES/dcs/signals/atom/signals_obj.dm @@ -26,3 +26,6 @@ #define COMSIG_TRANSMITTER_UPDATE_ICON "transmitter_update_icon" #define COMSIG_TENT_COLLAPSING "tent_collapsing" + +/// from /obj/proc/afterbuckle() +#define COSMIG_OBJ_AFTER_BUCKLE "signal_obj_after_buckle" diff --git a/code/datums/components/weed_food.dm b/code/datums/components/weed_food.dm index 1c36fa679d66..08eebf61880f 100644 --- a/code/datums/components/weed_food.dm +++ b/code/datums/components/weed_food.dm @@ -1,54 +1,71 @@ -#define WEED_FOOD_DELAY 5 MINUTES +#define WEED_FOOD_DELAY 10 SECONDS +#define WEED_FOOD_STATE_DELAY 10 SECONDS // TODO: 1 MINUTES /atom/movable/vis_obj/weed_food - icon = 'icons/mob/xenos/weeds.dmi' - icon_state = "human" - vis_flags = VIS_INHERIT_DIR|VIS_INHERIT_PLANE|VIS_INHERIT_LAYER name = "weeds" desc = "Weird black weeds in the shape of a body..." gender = PLURAL + vis_flags = VIS_INHERIT_DIR|VIS_INHERIT_PLANE|VIS_INHERIT_LAYER + icon = 'icons/mob/xenos/weeds.dmi' + var/static/list/icon_states = list("human_1","human_2","human_3","human_4","human_5") + var/icon_state_idx = 0 + var/timer_id = null + +/atom/movable/vis_obj/weed_food/Initialize(mapload, ...) + timer_id = addtimer(CALLBACK(src, PROC_REF(on_animation_timer)), WEED_FOOD_STATE_DELAY, TIMER_STOPPABLE|TIMER_UNIQUE|TIMER_LOOP|TIMER_DELETE_ME) + on_animation_timer() + return ..() + +/// Timer callback for changing the icon_state +/atom/movable/vis_obj/weed_food/proc/on_animation_timer() + icon_state_idx++ + if(icon_state_idx > length(icon_states)) + deltimer(timer_id) + timer_id = null + return + icon_state = icon_states[icon_state_idx] /** - * A component that can be attached to a living mob to be merged with weeds after a delay. + * A component that can be attached to a mob/living to be merged with weeds after a delay. * Attempting to attach a new weed_food even if one already exists is equivalent to calling start(). * - * Attach this to any living mob that is dead (death or initialized dead) and it should handle the rest. + * Attach this to any mob/living that is dead (death or initialized dead) and it should handle the rest. */ /datum/component/weed_food dupe_mode = COMPONENT_DUPE_UNIQUE_PASSARGS - - /// Whether we are actively being merged + /// Whether we are waiting on timer to merge var/active = FALSE - /// Whether we are completely merged with weeds + /// Whether we are merged with weeds var/merged = FALSE /// The time we were unmerged (just to handle weeds upgrading) var/unmerged_time /// Any active timer for a pending merge var/timer_id = null - /// The weeds that we are merging/merged with - var/obj/effect/alien/weeds/absorbing_weeds /// The living mob that we are bound to var/mob/living/parent_mob /// The turf that our parent is on var/turf/parent_turf + /// The obj that our parent is buckled to and we have registered a signal + var/obj/parent_buckle + /// The weeds that we are merging/merged with + var/obj/effect/alien/weeds/absorbing_weeds /// The overlay image when merged var/atom/movable/vis_obj/weed_food/weed_appearance /datum/component/weed_food/Initialize(...) - . = ..() - parent_mob = parent //if(!istype(parent_mob)) //return COMPONENT_INCOMPATIBLE if(!istype(parent_mob, /mob/living/carbon/human)) - return COMPONENT_INCOMPATIBLE // At the moment we only support humans + return COMPONENT_INCOMPATIBLE // TODO: At the moment we only support humans parent_turf = get_turf(parent_mob) + if(parent_turf != parent_mob.loc) + parent_turf = null // if our location is actually a container, we want to be safe from weeds start() /datum/component/weed_food/InheritComponent(datum/component/C, i_am_original) - . = ..() start() /datum/component/weed_food/Destroy(force, silent) @@ -60,27 +77,26 @@ parent_turf = null /datum/component/weed_food/RegisterWithParent() - . = ..() - RegisterSignal(parent_mob, COMSIG_MOVABLE_MOVED, PROC_REF(on_move)) - RegisterSignal(parent_mob, COMSIG_LIVING_REJUVENATED, PROC_REF(on_rejuv)) - RegisterSignal(parent_mob, COMSIG_HUMAN_REVIVED, PROC_REF(on_rejuv)) + RegisterSignal(parent_mob, list(COMSIG_LIVING_REJUVENATED, COMSIG_HUMAN_REVIVED), PROC_REF(on_rejuv)) RegisterSignal(parent_mob, COMSIG_HUMAN_SET_UNDEFIBBABLE, PROC_REF(start)) if(parent_turf) RegisterSignal(parent_turf, COMSIG_WEEDNODE_GROWTH, PROC_REF(start)) /datum/component/weed_food/UnregisterFromParent() - . = ..() - if(parent_mob) - UnregisterSignal(parent_mob, COMSIG_MOVABLE_MOVED) - UnregisterSignal(parent_mob, COMSIG_LIVING_REJUVENATED) - UnregisterSignal(parent_mob, COMSIG_HUMAN_REVIVED) - UnregisterSignal(parent_mob, COMSIG_HUMAN_SET_UNDEFIBBABLE) + UnregisterSignal(parent_mob, list( + COMSIG_MOVABLE_MOVED, + COMSIG_LIVING_REJUVENATED, + COMSIG_HUMAN_REVIVED, + COMSIG_HUMAN_SET_UNDEFIBBABLE, + )) if(absorbing_weeds) UnregisterSignal(absorbing_weeds, COMSIG_PARENT_QDELETING) if(parent_turf) UnregisterSignal(parent_turf, COMSIG_WEEDNODE_GROWTH) + if(parent_buckle) + UnregisterSignal(parent_buckle, COSMIG_OBJ_AFTER_BUCKLE) /// SIGNAL_HANDLER for COMSIG_MOVABLE_MOVED /datum/component/weed_food/proc/on_move() @@ -89,10 +105,13 @@ if(absorbing_weeds) UnregisterSignal(absorbing_weeds, COMSIG_PARENT_QDELETING) absorbing_weeds = null + if(parent_turf) UnregisterSignal(parent_turf, COMSIG_WEEDNODE_GROWTH) parent_turf = get_turf(parent_mob) - if(parent_turf) + if(parent_turf != parent_mob.loc) + parent_turf = null // if our location is actually a container, we want to be safe from weeds + else RegisterSignal(parent_turf, COMSIG_WEEDNODE_GROWTH, PROC_REF(start)) // We moved, restart or start the proccess @@ -104,17 +123,30 @@ absorbing_weeds = parent_turf?.weeds if(absorbing_weeds) RegisterSignal(absorbing_weeds, COMSIG_PARENT_QDELETING, PROC_REF(unmerge_with_weeds)) - else - unmerge_with_weeds() + return + unmerge_with_weeds() /// SIGNAL_HANDLER for COMSIG_LIVING_REJUVENATED and COMSIG_HUMAN_REVIVED /datum/component/weed_food/proc/on_rejuv() SIGNAL_HANDLER + + message_admins("on_rejuv [parent_mob]") // TODO: Remove this qdel(src) -/// Try to start the process to turn into weeds -/// SIGNAL_HANDLER for COMSIG_HUMAN_SET_UNDEFIBBABLE & COMSIG_WEEDNODE_GROWTH which should not set force TRUE -/datum/component/weed_food/proc/start(force = FALSE) +/// SIGNAL_HANDLER for COSMIG_OBJ_AFTER_BUCKLE +/datum/component/weed_food/proc/on_after_buckle(obj/source, mob/buckled) + SIGNAL_HANDLER + + if(buckled) + return + start() // We unbuckled, so lets try to start again + +/** + * Try to start the process to turn into weeds + * SIGNAL_HANDLER for COMSIG_HUMAN_SET_UNDEFIBBABLE & COMSIG_WEEDNODE_GROWTH + * Returns TRUE if started successfully + */ +/datum/component/weed_food/proc/start() SIGNAL_HANDLER if(active) @@ -123,30 +155,50 @@ return FALSE if(QDELETED(parent_mob)) return FALSE + + if(parent_mob.buckled) + if(parent_mob.buckled == parent_buckle) + return FALSE // Still buckled to the same thing + if(!istype(parent_mob.buckled, /obj/structure/bed/nest)) + message_admins("cant start [parent_mob] because we are buckled. Listening...") // TODO: Remove this + if(parent_buckle) // Still have a lingering reference somehow? + UnregisterSignal(parent_buckle, COSMIG_OBJ_AFTER_BUCKLE) + parent_buckle = parent_mob.buckled + RegisterSignal(parent_mob.buckled, COSMIG_OBJ_AFTER_BUCKLE, PROC_REF(on_after_buckle)) + return FALSE + if(parent_buckle) + UnregisterSignal(parent_buckle, COSMIG_OBJ_AFTER_BUCKLE) + parent_buckle = null + if(parent_mob.is_xeno_grabbable()) + message_admins("cant start [parent_mob] because we are grabable") // TODO: Remove this return FALSE if(!(parent_mob.status_flags & PERMANENTLY_DEAD)) var/mob/living/carbon/human/parent_human = parent_mob if(istype(parent_human) && !parent_human.undefibbable) + message_admins("cant start [parent_mob] because we are defibbable revive status: [parent_human.is_revivable()]") // TODO: Remove this return FALSE - - if(parent_turf?.weeds) - if(unmerged_time == world.time) - // Weeds upgraded, re-merge now - return merge_with_weeds() - QDEL_NULL(weed_appearance) // if we're here, we know we aren't re-using the apperance - absorbing_weeds = parent_turf.weeds - RegisterSignal(parent_turf.weeds, COMSIG_PARENT_QDELETING, PROC_REF(stop)) - else if(!force) + if(!parent_turf?.weeds) + message_admins("cant start [parent_mob] because we aren't on weeds") // TODO: Remove this return FALSE + if(unmerged_time == world.time) + return merge_with_weeds() // Weeds upgraded, re-merge now re-using the apperance + QDEL_NULL(weed_appearance) + absorbing_weeds = parent_turf.weeds + RegisterSignal(parent_turf.weeds, COMSIG_PARENT_QDELETING, PROC_REF(stop)) + active = TRUE - timer_id = addtimer(CALLBACK(src, PROC_REF(merge_with_weeds), force), WEED_FOOD_DELAY, TIMER_STOPPABLE|TIMER_UNIQUE|TIMER_DELETE_ME|TIMER_OVERRIDE) + timer_id = addtimer(CALLBACK(src, PROC_REF(merge_with_weeds)), WEED_FOOD_DELAY, TIMER_STOPPABLE|TIMER_UNIQUE|TIMER_DELETE_ME|TIMER_OVERRIDE) + message_admins("started [parent_mob]") // TODO: Remove this return TRUE -/// Try to stop the process turning into weeds -/// Signal handler for COMSIG_PARENT_QDELETING of weeds +/** + * Try to stop the process turning into weeds + * Signal handler for COMSIG_PARENT_QDELETING of weeds + * Returns TRUE if stopped successfully (was active when called) + */ /datum/component/weed_food/proc/stop() SIGNAL_HANDLER @@ -157,24 +209,41 @@ deltimer(timer_id) timer_id = null + message_admins("stopped [parent_mob]") // TODO: Remove this return TRUE -/// Finish becomming one with the weeds -/datum/component/weed_food/proc/merge_with_weeds(force = FALSE) +/** + * Finish becomming one with the weeds + * Returns TRUE if merged successfully + */ +/datum/component/weed_food/proc/merge_with_weeds() if(merged) return FALSE if(QDELETED(parent_mob)) return FALSE - if(absorbing_weeds) + if(absorbing_weeds) // Remove the signal that would call stop UnregisterSignal(absorbing_weeds, COMSIG_PARENT_QDELETING) - if(!force && !parent_turf?.weeds) - return FALSE + if(parent_mob.buckled) + if(parent_mob.buckled == parent_buckle) + return FALSE // Still buckled to the same thing somehow? + if(!istype(parent_mob.buckled, /obj/structure/bed/nest)) + if(parent_buckle) // Still have a lingering reference somehow? + UnregisterSignal(parent_buckle, COSMIG_OBJ_AFTER_BUCKLE) + message_admins("cant merge [parent_mob] because we are buckled. Listening...") // TODO: Remove this + parent_buckle = parent_mob.buckled + RegisterSignal(parent_mob.buckled, COSMIG_OBJ_AFTER_BUCKLE, PROC_REF(on_after_buckle)) + return FALSE + if(parent_buckle) + UnregisterSignal(parent_buckle, COSMIG_OBJ_AFTER_BUCKLE) + parent_buckle = null absorbing_weeds = parent_turf?.weeds - if(absorbing_weeds) - RegisterSignal(absorbing_weeds, COMSIG_PARENT_QDELETING, PROC_REF(unmerge_with_weeds)) + if(!absorbing_weeds) + message_admins("cant merge [parent_mob] because we aren't on weeds") // TODO: Remove this + return FALSE + RegisterSignal(absorbing_weeds, COMSIG_PARENT_QDELETING, PROC_REF(unmerge_with_weeds)) active = FALSE merged = TRUE @@ -185,24 +254,27 @@ parent_mob.plane = FLOOR_PLANE parent_mob.remove_from_all_mob_huds() - // Update the sprite - if(!weed_appearance) + if(!weed_appearance) // Make a new sprite if we aren't re-merging weed_appearance = new() - if(absorbing_weeds) - weed_appearance.color = absorbing_weeds.color - // For non-humans change the icon_state or something here + weed_appearance.color = absorbing_weeds.color + // TODO: For non-humans change the icon_state or something here parent_mob.vis_contents += weed_appearance + message_admins("merged [parent_mob] on [parent_mob.layer]") // TODO: Remove this return TRUE -/// Undo the weedening -/// SIGNAL_HANDLER for COMSIG_PARENT_QDELETING of weeds +/** + * Undo the weedening + * SIGNAL_HANDLER for COMSIG_PARENT_QDELETING of weeds + * Returns TRUE if unmerged successfully (always) + */ /datum/component/weed_food/proc/unmerge_with_weeds() SIGNAL_HANDLER merged = FALSE unmerged_time = world.time - if(absorbing_weeds) // Just to supress errors if this proc is manually called + + if(absorbing_weeds) UnregisterSignal(absorbing_weeds, COMSIG_PARENT_QDELETING) absorbing_weeds = null @@ -212,4 +284,8 @@ parent_mob.add_to_all_mob_huds() parent_mob.vis_contents -= weed_appearance + message_admins("unmerged [parent_mob]") // TODO: Remove this + return TRUE + #undef WEED_FOOD_DELAY +#undef WEED_FOOD_STATE_DELAY diff --git a/code/game/objects/objs.dm b/code/game/objects/objs.dm index 42a3a2f0b9ea..03894100d1a4 100644 --- a/code/game/objects/objs.dm +++ b/code/game/objects/objs.dm @@ -223,6 +223,7 @@ /obj/proc/afterbuckle(mob/M as mob) // Called after somebody buckled / unbuckled handle_rotation() + SEND_SIGNAL(src, COSMIG_OBJ_AFTER_BUCKLE, buckled_mob) return buckled_mob /obj/proc/unbuckle() diff --git a/code/game/objects/structures/crates_lockers/closets.dm b/code/game/objects/structures/crates_lockers/closets.dm index 05355feeb154..a139e0ef0bfb 100644 --- a/code/game/objects/structures/crates_lockers/closets.dm +++ b/code/game/objects/structures/crates_lockers/closets.dm @@ -142,6 +142,8 @@ continue if(M.buckled) continue + if(M.anchored) + continue M.forceMove(src) stored_units += mob_size diff --git a/icons/mob/xenos/weeds.dmi b/icons/mob/xenos/weeds.dmi index 794005d12ce4d93ea749989ee3c08fd319c3d2d9..0b9403058109ed40a5cf445d2a223bc2dfa30ce6 100644 GIT binary patch delta 16372 zcmW+-Wn2{P+g-X#kuE`$P63IfBt$?#P`X=E0f_|$q*Oq_hmbBQ=~x<;P#TtQc0p?C zC70ZN`M>jR=F437^*eLj=bZaYRj^xLdtbu>c+ToUP8_e-laE()J zpxy344z&GK$+TSB!@`7g9;mW_+WW6lxJUpDRyJ@}!XrohCw>+yE$$WO^C`v3@m;XI!~Tt?)|#Op={`pWAj#COYmM&uyg zdo}CP;3V~B!_?=Kx+gd_@JOYcEy0q$?9TT=k`IR8TM9l-u_s^uF8J8$V|dW@ebB|v zkVB}EK2~e?OHkNg>pUGZ!Sid!c_FttZho^Fp>l`iZqpf&^2mZ-;~BAX2X?z>tS@Ai zHrN;w71D_r+4GV#=T^|)k4sqD5c(Wn!+Ych3%tGJ{W6IcZ+nAMZb5xX>n;{@L$V+c z^tf&u59|+^1q!!*KRI`|RJ_uv9dJB(ctkg^#l=^p5~_pGSCh{bTJh%x*Wxi(3Y8P> zALXKfKLA%ah)m)|?jsiCSNQ76YIl!QE(s+1JN4L1$oYr3=WS&Q4>rrRzR5Ix!uVY- zAHJ(-KSz|!bfo^94fZ;icgnHY)qh*|uEG?`Z7K!mgUj_yuqyFGU6`q$qvIhitrVsVgE)b>X(=J@7=VD2v_2B&Z zWK+P&T*mX8EcQIz6Ys>ZLH!o&8h^MErnemXo3j1twQe4dAic{caA7>sHadWAc6{}B61v;D0y8s)>4=ZWf=zB0&Dy+o zP&>VBaRTRBCR)`Qj;3E}-rbs-x-omh)HX~E00uRYa2e~9P6IQbifyTi1J19zB;Sa= z$$A2yAZQuECmhOiFaJQ(uTFg7%d=+Kf~x{^gyhT=@C|q5Rxh={o>P#v&vpek+p*70 zN&S)ZM=PBm*{+I{lwD}`oSjx>ImELL$~IVT5e4CpmsF8R-R3y%ULq>b7K&X0QQy*% z>8RRiV@0=lv4Yf~A#%s4lG_5;mpMr0g_-#?C!k114Dt>25M#%w*tD#{)Fu6C#^iGlAK3UWZ#k-C`s_7<4`{dQMJ*z?o% z)C}~TWr;(9$zO!=&{X#pJj>Q&fYqrZ!mYJFC+LT+_IuI`Z&>Y`^WX$1S~SRXrh)G_ z>R*<;baHU-LcTL(2aKm2zP;T#0;p~+6zs`KV%(f=liH-L1R8FIetTxr({^3YDwjwi+npi0fGJ1|13jkR=vfH$A0vd{@o_IroI` GI3a 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 Date: Fri, 23 Jun 2023 23:05:46 -0700 Subject: [PATCH 08/15] Remove testing logic (mostly just doing this so I can easily revert locally for testing) --- code/datums/components/weed_food.dm | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) diff --git a/code/datums/components/weed_food.dm b/code/datums/components/weed_food.dm index 08eebf61880f..bd3f2cdea226 100644 --- a/code/datums/components/weed_food.dm +++ b/code/datums/components/weed_food.dm @@ -1,5 +1,5 @@ -#define WEED_FOOD_DELAY 10 SECONDS -#define WEED_FOOD_STATE_DELAY 10 SECONDS // TODO: 1 MINUTES +#define WEED_FOOD_DELAY 5 MINUTES +#define WEED_FOOD_STATE_DELAY 1 MINUTES /atom/movable/vis_obj/weed_food name = "weeds" @@ -130,7 +130,6 @@ /datum/component/weed_food/proc/on_rejuv() SIGNAL_HANDLER - message_admins("on_rejuv [parent_mob]") // TODO: Remove this qdel(src) /// SIGNAL_HANDLER for COSMIG_OBJ_AFTER_BUCKLE @@ -160,7 +159,6 @@ if(parent_mob.buckled == parent_buckle) return FALSE // Still buckled to the same thing if(!istype(parent_mob.buckled, /obj/structure/bed/nest)) - message_admins("cant start [parent_mob] because we are buckled. Listening...") // TODO: Remove this if(parent_buckle) // Still have a lingering reference somehow? UnregisterSignal(parent_buckle, COSMIG_OBJ_AFTER_BUCKLE) parent_buckle = parent_mob.buckled @@ -171,15 +169,12 @@ parent_buckle = null if(parent_mob.is_xeno_grabbable()) - message_admins("cant start [parent_mob] because we are grabable") // TODO: Remove this return FALSE if(!(parent_mob.status_flags & PERMANENTLY_DEAD)) var/mob/living/carbon/human/parent_human = parent_mob if(istype(parent_human) && !parent_human.undefibbable) - message_admins("cant start [parent_mob] because we are defibbable revive status: [parent_human.is_revivable()]") // TODO: Remove this return FALSE if(!parent_turf?.weeds) - message_admins("cant start [parent_mob] because we aren't on weeds") // TODO: Remove this return FALSE if(unmerged_time == world.time) @@ -191,7 +186,6 @@ active = TRUE timer_id = addtimer(CALLBACK(src, PROC_REF(merge_with_weeds)), WEED_FOOD_DELAY, TIMER_STOPPABLE|TIMER_UNIQUE|TIMER_DELETE_ME|TIMER_OVERRIDE) - message_admins("started [parent_mob]") // TODO: Remove this return TRUE /** @@ -209,7 +203,6 @@ deltimer(timer_id) timer_id = null - message_admins("stopped [parent_mob]") // TODO: Remove this return TRUE /** @@ -231,7 +224,6 @@ if(!istype(parent_mob.buckled, /obj/structure/bed/nest)) if(parent_buckle) // Still have a lingering reference somehow? UnregisterSignal(parent_buckle, COSMIG_OBJ_AFTER_BUCKLE) - message_admins("cant merge [parent_mob] because we are buckled. Listening...") // TODO: Remove this parent_buckle = parent_mob.buckled RegisterSignal(parent_mob.buckled, COSMIG_OBJ_AFTER_BUCKLE, PROC_REF(on_after_buckle)) return FALSE @@ -241,7 +233,6 @@ absorbing_weeds = parent_turf?.weeds if(!absorbing_weeds) - message_admins("cant merge [parent_mob] because we aren't on weeds") // TODO: Remove this return FALSE RegisterSignal(absorbing_weeds, COMSIG_PARENT_QDELETING, PROC_REF(unmerge_with_weeds)) @@ -260,7 +251,6 @@ // TODO: For non-humans change the icon_state or something here parent_mob.vis_contents += weed_appearance - message_admins("merged [parent_mob] on [parent_mob.layer]") // TODO: Remove this return TRUE /** @@ -284,7 +274,6 @@ parent_mob.add_to_all_mob_huds() parent_mob.vis_contents -= weed_appearance - message_admins("unmerged [parent_mob]") // TODO: Remove this return TRUE #undef WEED_FOOD_DELAY From ae175d1722f10828826e37931c74e42677a0a7d4 Mon Sep 17 00:00:00 2001 From: Drulikar Date: Fri, 23 Jun 2023 23:47:30 -0700 Subject: [PATCH 09/15] Headless zombie weed food --- code/modules/mob/living/carbon/human/species/zombie.dm | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/code/modules/mob/living/carbon/human/species/zombie.dm b/code/modules/mob/living/carbon/human/species/zombie.dm index 2c9c423c671e..532d9413102c 100644 --- a/code/modules/mob/living/carbon/human/species/zombie.dm +++ b/code/modules/mob/living/carbon/human/species/zombie.dm @@ -102,6 +102,8 @@ if(zombie.client) zombie.play_screen_text("You are dead...
You lost your head. No reviving for you.", /atom/movable/screen/text/screen_text/command_order, rgb(155, 0, 200)) to_chat(zombie, SPAN_XENOWARNING("You fall... headless, you will no longer rise.")) + zombie.undefibbable = TRUE // really only for weed_food + SEND_SIGNAL(zombie, COMSIG_HUMAN_SET_UNDEFIBBABLE) /datum/species/zombie/handle_dead_death(mob/living/carbon/human/zombie, gibbed) if(gibbed) @@ -144,6 +146,9 @@ return static_tab_items /datum/species/zombie/handle_head_loss(mob/living/carbon/human/zombie) + if(!zombie.undefibbable) + zombie.undefibbable = TRUE // really only for weed_food + SEND_SIGNAL(zombie, COMSIG_HUMAN_SET_UNDEFIBBABLE) if(WEAKREF(zombie) in to_revive) remove_from_revive(zombie) var/client/receiving_client = zombie.client From 6f78d0a6d388cdd0bc116166aa1454ef762a27fa Mon Sep 17 00:00:00 2001 From: Drulikar Date: Tue, 27 Jun 2023 03:53:28 -0700 Subject: [PATCH 10/15] Fix weed_food observers keeping mouse_opacity setting --- code/modules/mob/dead/observer/observer.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/modules/mob/dead/observer/observer.dm b/code/modules/mob/dead/observer/observer.dm index fcb95a6fd783..6c7424854894 100644 --- a/code/modules/mob/dead/observer/observer.dm +++ b/code/modules/mob/dead/observer/observer.dm @@ -86,7 +86,6 @@ body.alter_ghost(src) apply_transform(matrix()) - own_orbit_size = body.get_orbit_size() desc = initial(desc) @@ -95,6 +94,7 @@ invisibility = INVISIBILITY_OBSERVER plane = GHOST_PLANE layer = ABOVE_FLY_LAYER + mouse_opacity = MOUSE_OPACITY_ICON // In case we were weed_food sight |= SEE_TURFS|SEE_MOBS|SEE_OBJS|SEE_SELF see_invisible = INVISIBILITY_OBSERVER From 4c01f9e81d81e459111e3a883e4c38ef53fa3706 Mon Sep 17 00:00:00 2001 From: Drulikar Date: Tue, 27 Jun 2023 03:54:06 -0700 Subject: [PATCH 11/15] Fix deleted mobs re-adding their huds --- code/datums/components/weed_food.dm | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/code/datums/components/weed_food.dm b/code/datums/components/weed_food.dm index bd3f2cdea226..565a373f1279 100644 --- a/code/datums/components/weed_food.dm +++ b/code/datums/components/weed_food.dm @@ -271,9 +271,11 @@ parent_mob.anchored = FALSE parent_mob.mouse_opacity = MOUSE_OPACITY_ICON parent_mob.plane = GAME_PLANE - parent_mob.add_to_all_mob_huds() parent_mob.vis_contents -= weed_appearance + if(!QDELETED(parent_mob)) + parent_mob.add_to_all_mob_huds() + return TRUE #undef WEED_FOOD_DELAY From 946f7713cd6556cbeeb0855ff16d32535f0ddd16 Mon Sep 17 00:00:00 2001 From: Drulikar Date: Tue, 27 Jun 2023 03:55:55 -0700 Subject: [PATCH 12/15] Refactor signal handlers to procs that don't return anything --- code/datums/components/weed_food.dm | 39 ++++++++++++++++++----------- 1 file changed, 24 insertions(+), 15 deletions(-) diff --git a/code/datums/components/weed_food.dm b/code/datums/components/weed_food.dm index 565a373f1279..f7afc2bdcc65 100644 --- a/code/datums/components/weed_food.dm +++ b/code/datums/components/weed_food.dm @@ -79,9 +79,9 @@ /datum/component/weed_food/RegisterWithParent() RegisterSignal(parent_mob, COMSIG_MOVABLE_MOVED, PROC_REF(on_move)) RegisterSignal(parent_mob, list(COMSIG_LIVING_REJUVENATED, COMSIG_HUMAN_REVIVED), PROC_REF(on_rejuv)) - RegisterSignal(parent_mob, COMSIG_HUMAN_SET_UNDEFIBBABLE, PROC_REF(start)) + RegisterSignal(parent_mob, COMSIG_HUMAN_SET_UNDEFIBBABLE, PROC_REF(on_update)) if(parent_turf) - RegisterSignal(parent_turf, COMSIG_WEEDNODE_GROWTH, PROC_REF(start)) + RegisterSignal(parent_turf, COMSIG_WEEDNODE_GROWTH, PROC_REF(on_update)) /datum/component/weed_food/UnregisterFromParent() if(parent_mob) @@ -112,7 +112,7 @@ if(parent_turf != parent_mob.loc) parent_turf = null // if our location is actually a container, we want to be safe from weeds else - RegisterSignal(parent_turf, COMSIG_WEEDNODE_GROWTH, PROC_REF(start)) + RegisterSignal(parent_turf, COMSIG_WEEDNODE_GROWTH, PROC_REF(on_update)) // We moved, restart or start the proccess if(stop() || !merged) @@ -122,7 +122,7 @@ // If we somehow moved when we were merged, handle that absorbing_weeds = parent_turf?.weeds if(absorbing_weeds) - RegisterSignal(absorbing_weeds, COMSIG_PARENT_QDELETING, PROC_REF(unmerge_with_weeds)) + RegisterSignal(absorbing_weeds, COMSIG_PARENT_QDELETING, PROC_REF(on_weed_deletion)) return unmerge_with_weeds() @@ -140,14 +140,28 @@ return start() // We unbuckled, so lets try to start again +/// SIGNAL_HANDLER for COMSIG_HUMAN_SET_UNDEFIBBABLE & COMSIG_WEEDNODE_GROWTH +/datum/component/weed_food/proc/on_update() + SIGNAL_HANDLER + + start() + +/// SIGNAL_HANDLER for COMSIG_PARENT_QDELETING of weeds +/datum/component/weed_food/proc/on_weed_deletion() + SIGNAL_HANDLER + + if(active) + stop() + return + if(merged) + unmerge_with_weeds() + return + /** * Try to start the process to turn into weeds - * SIGNAL_HANDLER for COMSIG_HUMAN_SET_UNDEFIBBABLE & COMSIG_WEEDNODE_GROWTH * Returns TRUE if started successfully */ /datum/component/weed_food/proc/start() - SIGNAL_HANDLER - if(active) return FALSE if(merged) @@ -181,7 +195,7 @@ return merge_with_weeds() // Weeds upgraded, re-merge now re-using the apperance QDEL_NULL(weed_appearance) absorbing_weeds = parent_turf.weeds - RegisterSignal(parent_turf.weeds, COMSIG_PARENT_QDELETING, PROC_REF(stop)) + RegisterSignal(parent_turf.weeds, COMSIG_PARENT_QDELETING, PROC_REF(on_weed_deletion)) active = TRUE timer_id = addtimer(CALLBACK(src, PROC_REF(merge_with_weeds)), WEED_FOOD_DELAY, TIMER_STOPPABLE|TIMER_UNIQUE|TIMER_DELETE_ME|TIMER_OVERRIDE) @@ -190,12 +204,9 @@ /** * Try to stop the process turning into weeds - * Signal handler for COMSIG_PARENT_QDELETING of weeds * Returns TRUE if stopped successfully (was active when called) */ /datum/component/weed_food/proc/stop() - SIGNAL_HANDLER - if(!active) return FALSE @@ -234,7 +245,8 @@ absorbing_weeds = parent_turf?.weeds if(!absorbing_weeds) return FALSE - RegisterSignal(absorbing_weeds, COMSIG_PARENT_QDELETING, PROC_REF(unmerge_with_weeds)) + RegisterSignal(absorbing_weeds, COMSIG_PARENT_QDELETING, PROC_REF(on_weed_deletion)) + // Technically we could have just left the signal alone, but both because of the posibility of other conditions preventing a merge or weeds somehow changing and on_move didn't catch it, this is less fragile active = FALSE merged = TRUE @@ -255,12 +267,9 @@ /** * Undo the weedening - * SIGNAL_HANDLER for COMSIG_PARENT_QDELETING of weeds * Returns TRUE if unmerged successfully (always) */ /datum/component/weed_food/proc/unmerge_with_weeds() - SIGNAL_HANDLER - merged = FALSE unmerged_time = world.time From 27d6e5e1f04f3d193da3788e554a09e81ce8a0b1 Mon Sep 17 00:00:00 2001 From: Drulikar Date: Wed, 28 Jun 2023 07:07:36 -0700 Subject: [PATCH 13/15] Upright light --- code/datums/components/weed_food.dm | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/code/datums/components/weed_food.dm b/code/datums/components/weed_food.dm index f7afc2bdcc65..0c578b661517 100644 --- a/code/datums/components/weed_food.dm +++ b/code/datums/components/weed_food.dm @@ -8,10 +8,13 @@ vis_flags = VIS_INHERIT_DIR|VIS_INHERIT_PLANE|VIS_INHERIT_LAYER icon = 'icons/mob/xenos/weeds.dmi' var/static/list/icon_states = list("human_1","human_2","human_3","human_4","human_5") + var/static/list/icon_states_flipped = list("human_1_f","human_2_f","human_3_f","human_4_f","human_5_f") var/icon_state_idx = 0 var/timer_id = null + var/flipped = FALSE -/atom/movable/vis_obj/weed_food/Initialize(mapload, ...) +/atom/movable/vis_obj/weed_food/Initialize(mapload, is_flipped, ...) + flipped = is_flipped timer_id = addtimer(CALLBACK(src, PROC_REF(on_animation_timer)), WEED_FOOD_STATE_DELAY, TIMER_STOPPABLE|TIMER_UNIQUE|TIMER_LOOP|TIMER_DELETE_ME) on_animation_timer() return ..() @@ -23,7 +26,7 @@ deltimer(timer_id) timer_id = null return - icon_state = icon_states[icon_state_idx] + icon_state = flipped ? icon_states_flipped[icon_state_idx] : icon_states[icon_state_idx] /** * A component that can be attached to a mob/living to be merged with weeds after a delay. @@ -258,7 +261,10 @@ parent_mob.remove_from_all_mob_huds() if(!weed_appearance) // Make a new sprite if we aren't re-merging - weed_appearance = new() + var/is_flipped = parent_mob.transform.b == -1 // Technically we should check if d is 1 too, but corpses can only be rotated 90 or 270 (1/-1 or -1/1) + if(parent_mob.dir & WEST) + is_flipped = !is_flipped // The direction reversed the effect of the flip! + weed_appearance = new(null, is_flipped) weed_appearance.color = absorbing_weeds.color // TODO: For non-humans change the icon_state or something here parent_mob.vis_contents += weed_appearance From 5ce7304673351e89c9c60304969b32a8b3dcf42f Mon Sep 17 00:00:00 2001 From: Drulikar Date: Wed, 28 Jun 2023 08:47:04 -0700 Subject: [PATCH 14/15] single letters --- .../structures/crates_lockers/closets.dm | 10 +++++----- code/modules/gear_presets/corpses.dm | 18 +++++++++--------- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/code/game/objects/structures/crates_lockers/closets.dm b/code/game/objects/structures/crates_lockers/closets.dm index a139e0ef0bfb..b8eba6815570 100644 --- a/code/game/objects/structures/crates_lockers/closets.dm +++ b/code/game/objects/structures/crates_lockers/closets.dm @@ -135,17 +135,17 @@ return stored_units /obj/structure/closet/proc/store_mobs(stored_units) - for(var/mob/M in src.loc) + for(var/mob/cur_mob in src.loc) if(stored_units + mob_size > storage_capacity) break - if(istype (M, /mob/dead/observer)) + if(istype (cur_mob, /mob/dead/observer)) continue - if(M.buckled) + if(cur_mob.buckled) continue - if(M.anchored) + if(cur_mob.anchored) continue - M.forceMove(src) + cur_mob.forceMove(src) stored_units += mob_size return stored_units diff --git a/code/modules/gear_presets/corpses.dm b/code/modules/gear_presets/corpses.dm index a5acbc886f43..7e9dd5b841a0 100644 --- a/code/modules/gear_presets/corpses.dm +++ b/code/modules/gear_presets/corpses.dm @@ -27,21 +27,21 @@ new_human.apply_damage(100, BRUTE) new_human.apply_damage(100, BRUTE) if(xenovictim) - var/datum/internal_organ/O + var/datum/internal_organ/organ var/i for(i in list("heart","lungs")) - O = new_human.internal_organs_by_name[i] + organ = new_human.internal_organs_by_name[i] new_human.internal_organs_by_name -= i - new_human.internal_organs -= O + new_human.internal_organs -= organ new_human.update_burst() //buckle to nest - var/obj/structure/bed/nest/N = locate() in get_turf(src) - if(N) - new_human.buckled = N - new_human.setDir(N.dir) + var/obj/structure/bed/nest/nest = locate() in get_turf(src) + if(nest) + new_human.buckled = nest + new_human.setDir(nest.dir) new_human.update_canmove() - N.buckled_mob = new_human - N.afterbuckle(new_human) + nest.buckled_mob = new_human + nest.afterbuckle(new_human) new_human.spawned_corpse = TRUE new_human.updatehealth() new_human.pulse = PULSE_NONE From 999e85903c44ee8b86089d031800879bdac52537 Mon Sep 17 00:00:00 2001 From: Drulikar Date: Tue, 4 Jul 2023 23:46:11 -0700 Subject: [PATCH 15/15] Fix logic error when changing last living human from an early return to just an if check --- code/modules/mob/living/carbon/human/death.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/modules/mob/living/carbon/human/death.dm b/code/modules/mob/living/carbon/human/death.dm index 5c4c11a7adb5..dbe00407d7ef 100644 --- a/code/modules/mob/living/carbon/human/death.dm +++ b/code/modules/mob/living/carbon/human/death.dm @@ -77,7 +77,7 @@ last_living_human = null break last_living_human = cur_human - if(last_living_human && (last_qm_callout + 2 MINUTES) > world.time) + if(last_living_human && (last_qm_callout + 2 MINUTES) < world.time) last_qm_callout = world.time // Tell the xenos where the human is. xeno_announcement("I sense the last tallhost hiding in [get_area(last_living_human)].", XENO_HIVE_NORMAL, SPAN_ANNOUNCEMENT_HEADER_BLUE("[QUEEN_MOTHER_ANNOUNCE]"))