From 3ec8bd669ead655dcf512fa202d203b919923e5f Mon Sep 17 00:00:00 2001 From: ChungusGamer666 <82850673+ChungusGamer666@users.noreply.github.com> Date: Sun, 18 Jun 2023 21:29:29 -0300 Subject: [PATCH] Food gets stink lines when about to go rotten (#76038) ## About The Pull Request Title says it all, food that decomposes gets stink lines halfway through. ![image](https://github.com/tgstation/tgstation/assets/82850673/ae90220c-4b27-49dd-873a-6f349055f891) ![image](https://github.com/tgstation/tgstation/assets/82850673/c982055d-ed69-4935-bda5-7851836fad2c) Moldy messes always gets stink lines. ## Why It's Good For The Game 1. It's funny 2. It's a visual indicator for food going bad which is kinda nice ## Changelog :cl: add: Food now gets stink lines when going bad. Uh oh, stinky. /:cl: --------- Co-authored-by: san7890 --- code/datums/components/food/decomposition.dm | 86 +++++++++++++------ code/game/objects/effects/particles/misc.dm | 13 +++ code/game/objects/items/food/_food.dm | 4 +- code/game/objects/items/food/misc.dm | 5 ++ icons/effects/particles/stink.dmi | Bin 0 -> 259 bytes 5 files changed, 82 insertions(+), 26 deletions(-) create mode 100644 icons/effects/particles/stink.dmi diff --git a/code/datums/components/food/decomposition.dm b/code/datums/components/food/decomposition.dm index ee5c8e22f1b..9f5d0f0a2ac 100644 --- a/code/datums/components/food/decomposition.dm +++ b/code/datums/components/food/decomposition.dm @@ -10,21 +10,27 @@ var/handled = TRUE /// Used to stop food in someone's hand & in storage slots from decomposing. var/protected = FALSE - /// Used to stop the timer & check for the examine proc - var/timerid /// The total time that this takes to decompose var/original_time = DECOMPOSITION_TIME /// Used so the timer won't reset. var/time_remaining = DECOMPOSITION_TIME + /// Used to create stink lines when the food is close to going bad + var/stink_timerid + /// Used to stop decomposition & check for the examine proc + var/decomp_timerid /// Used to give raw/gross food lower timers var/decomp_flags /// Use for determining what kind of item the food decomposes into. var/decomp_result /// Does our food attract ants? var/produce_ants = FALSE + /// Stink particle type, if we are supposed to create stink particles + var/stink_particles + /// Stink particle holder + var/obj/effect/abstract/particle_holder/particle_effect -/datum/component/decomposition/Initialize(mapload, decomp_req_handle, decomp_flags = NONE, decomp_result, ant_attracting = FALSE, custom_time = 0) - if(!isobj(parent)) +/datum/component/decomposition/Initialize(mapload, decomp_req_handle, decomp_flags = NONE, decomp_result, ant_attracting = FALSE, custom_time = 0, stink_particles = /particles/stink) + if(!ismovable(parent)) return COMPONENT_INCOMPATIBLE src.decomp_flags = decomp_flags @@ -33,17 +39,6 @@ handled = FALSE src.produce_ants = ant_attracting - RegisterSignal(parent, COMSIG_MOVABLE_MOVED, PROC_REF(handle_movement)) - RegisterSignals(parent, list( - COMSIG_ITEM_PICKUP, //person picks up an item - COMSIG_ATOM_ENTERED), //Object enters a storage object (boxes, etc.) - PROC_REF(picked_up)) - RegisterSignals(parent, list( - COMSIG_ITEM_DROPPED, //Object is dropped anywhere - COMSIG_ATOM_EXITED), //Object exits a storage object (boxes, etc) - PROC_REF(dropped)) - RegisterSignal(parent, COMSIG_ATOM_EXAMINE, PROC_REF(examine)) - if(custom_time) // We have a custom decomposition time, set it to that original_time = custom_time else if(decomp_flags & RAW) // Raw food overrides gross @@ -53,8 +48,28 @@ time_remaining = original_time + src.stink_particles = stink_particles + handle_movement() +/datum/component/decomposition/Destroy() + . = ..() + if(particle_effect) + QDEL_NULL(particle_effect) + +/datum/component/decomposition/RegisterWithParent() + RegisterSignal(parent, COMSIG_MOVABLE_MOVED, PROC_REF(handle_movement)) + RegisterSignals(parent, list( + COMSIG_ITEM_PICKUP, //person picks up an item + COMSIG_ATOM_ENTERED), //Object enters a storage object (boxes, etc.) + PROC_REF(picked_up), + ) + RegisterSignals(parent, list( + COMSIG_ITEM_DROPPED, //Object is dropped anywhere + COMSIG_ATOM_EXITED), //Object exits a storage object (boxes, etc) + PROC_REF(dropped), + ) + RegisterSignal(parent, COMSIG_ATOM_EXAMINE, PROC_REF(examine)) /datum/component/decomposition/UnregisterFromParent() UnregisterSignal(parent, list( @@ -67,8 +82,10 @@ /datum/component/decomposition/proc/handle_movement() SIGNAL_HANDLER + if(!handled) // If maploaded, has someone touched this previously? return + var/obj/food = parent // Doesn't HAVE to be food, that's just what it's intended for var/turf/open/open_turf = food.loc @@ -83,7 +100,14 @@ return // If all other checks fail, then begin decomposition. - timerid = addtimer(CALLBACK(src, PROC_REF(decompose)), time_remaining, TIMER_STOPPABLE | TIMER_UNIQUE) + decomp_timerid = addtimer(CALLBACK(src, PROC_REF(decompose)), time_remaining, TIMER_STOPPABLE | TIMER_UNIQUE) + + // Also start the stinking timer, if have stink particles and aren't stinking yet + if(!stink_particles || particle_effect) + return + + var/stink_time = max(0, time_remaining - (original_time * 0.5)) + stink_timerid = addtimer(CALLBACK(src, PROC_REF(stink_up)), stink_time, TIMER_STOPPABLE | TIMER_UNIQUE) /datum/component/decomposition/Destroy() remove_timer() @@ -91,16 +115,20 @@ /// Returns the time remaining in decomp, either from our potential timer or our own value, whichever is more useful /datum/component/decomposition/proc/get_time() - if(!timerid) + if(!decomp_timerid) return time_remaining - return timeleft(timerid) + return timeleft(decomp_timerid) /datum/component/decomposition/proc/remove_timer() - if(!timerid) + if(!decomp_timerid) return - time_remaining = timeleft(timerid) - deltimer(timerid) - timerid = null + time_remaining = timeleft(decomp_timerid) + deltimer(decomp_timerid) + decomp_timerid = null + if(!stink_timerid) + return + deltimer(stink_timerid) + stink_timerid = null /datum/component/decomposition/proc/dropped() SIGNAL_HANDLER @@ -111,16 +139,24 @@ SIGNAL_HANDLER remove_timer() protected = TRUE - if(!handled) - handled = TRUE + handled = TRUE + +/datum/component/decomposition/proc/stink_up() + stink_timerid = null + // Neither should happen, but to be sure + if(particle_effect || !stink_particles) + return + // we don't want stink lines on mobs (even though it'd be quite funny) + particle_effect = new(parent, stink_particles, isitem(parent) ? NONE : PARTICLE_ATTACH_MOB) /datum/component/decomposition/proc/decompose() + decomp_timerid = null var/obj/decomp = parent //Lets us spawn things at decomp if(produce_ants) new /obj/effect/decal/cleanable/ants(decomp.loc) if(decomp_result) new decomp_result(decomp.loc) - decomp.visible_message("[decomp] gets overtaken by mold[produce_ants ? " and ants":""]! Gross!") + decomp.visible_message(span_warning("[decomp] gets overtaken by mold[produce_ants ? " and ants":""]! Gross!")) qdel(decomp) return diff --git a/code/game/objects/effects/particles/misc.dm b/code/game/objects/effects/particles/misc.dm index 18db20d6379..a1f188f88c9 100644 --- a/code/game/objects/effects/particles/misc.dm +++ b/code/game/objects/effects/particles/misc.dm @@ -30,3 +30,16 @@ position = generator(GEN_BOX, list(-240, -240), list(240, 240), NORMAL_RAND) drift = generator(GEN_VECTOR, list(-0.1, 0), list(0.1, 0)) rotation = generator(GEN_NUM, 0, 360, NORMAL_RAND) + +/particles/stink + icon = 'icons/effects/particles/stink.dmi' + icon_state = list("stink_1" = 1, "stink_2" = 2, "stink_3" = 2) + color = "#0BDA51" + width = 100 + height = 100 + count = 25 + spawning = 0.25 + lifespan = 1 SECONDS + fade = 1 SECONDS + position = generator(GEN_CIRCLE, 0, 16, UNIFORM_RAND) + gravity = list(0, 0.25) diff --git a/code/game/objects/items/food/_food.dm b/code/game/objects/items/food/_food.dm index 4c707f88ae3..b9d9551bfb9 100644 --- a/code/game/objects/items/food/_food.dm +++ b/code/game/objects/items/food/_food.dm @@ -46,6 +46,8 @@ var/decomp_req_handle = FALSE ///Used to set custom decomposition times for food. Set to 0 to have it automatically set via the food's flags. var/decomposition_time = 0 + ///Used to set decomposition stink particles for food, will have no particles if null + var/decomposition_particles = /particles/stink /obj/item/food/Initialize(mapload) . = ..() @@ -112,4 +114,4 @@ ///Set decomp_req_handle to TRUE to only make it decompose when someone picks it up. /obj/item/food/proc/make_decompose(mapload) if(!preserved_food) - AddComponent(/datum/component/decomposition, mapload, decomp_req_handle, decomp_flags = foodtypes, decomp_result = decomp_type, ant_attracting = ant_attracting, custom_time = decomposition_time) + AddComponent(/datum/component/decomposition, mapload, decomp_req_handle, decomp_flags = foodtypes, decomp_result = decomp_type, ant_attracting = ant_attracting, custom_time = decomposition_time, stink_particles = decomposition_particles) diff --git a/code/game/objects/items/food/misc.dm b/code/game/objects/items/food/misc.dm index 79456a5f979..0742db2bf35 100644 --- a/code/game/objects/items/food/misc.dm +++ b/code/game/objects/items/food/misc.dm @@ -87,10 +87,14 @@ foodtypes = GROSS w_class = WEIGHT_CLASS_SMALL preserved_food = TRUE //Can't decompose any more than this + /// Variable that holds the reference to the stink lines we get when we're moldy, yucky yuck + var/stink_particles /obj/item/food/badrecipe/Initialize(mapload) . = ..() RegisterSignal(src, COMSIG_ITEM_GRILL_PROCESS, PROC_REF(OnGrill)) + if(stink_particles) + particles = new stink_particles /obj/item/food/badrecipe/moldy name = "moldy mess" @@ -100,6 +104,7 @@ ant_attracting = TRUE decomp_type = null decomposition_time = 30 SECONDS + stink_particles = /particles/stink /obj/item/food/badrecipe/moldy/bacteria name = "bacteria rich moldy mess" diff --git a/icons/effects/particles/stink.dmi b/icons/effects/particles/stink.dmi new file mode 100644 index 0000000000000000000000000000000000000000..29b92acbe67c69df28ba41e4285ae0fb787a80a5 GIT binary patch literal 259 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0L3?#3!&-4XSoB=)|t_Kbr`2YVuklfRK+Zrgy zSQ6wH%;50sMjDV)QWX+W;*wgNT$EW*l9`{!z)&$KIIN(k^!u0Kf{$OHXnE^uojY?r zctfbcMdJsLbk6%|o@6NM>D^&r9Atdi*h^u~qe(|5g(w8C+@WHuZ+$PIv)fp8^9l)# zq!UMHhE16!mv&8fYUC9L}zzC28Q((40kw`+dcyIFnGH9xvX