From 753d8a24400dc683bba05c38c8fc9eb03628522b Mon Sep 17 00:00:00 2001
From: Wallem <66052067+Wallemations@users.noreply.github.com>
Date: Mon, 7 Apr 2025 12:29:03 -0400
Subject: [PATCH] Implements some of the helpers I made for #90354 (#90436)
## About The Pull Request
Adds a couple helpers from #90354
1. `/proc/pick_recursive()` > able to take in nested lists and pick one
object from them. Works the same way `pick_weight_recursive()` does,
just without all the extra `_weight` stuff
2. `span_tinynicegreen()` > we had span_tiny for danger and notice but
not nicegreen, just filling that gap
3. `/matrix/proc/get_angle()` > Tells us the angle a matrix is currently
in
4. `GLOB.all_tool_behaviours` > in case you wanted an easy list for all
tool behaviors
5. `transition_filter_chain()` > a more complicated one, this is used if
you want to make an animation chain for a filter. (Thank you
LemonInTheDark for the help on this one.)
## Why It's Good For The Game
Helpful stuff for future coders is good
## Changelog
:cl: Wallem, LemonInTheDark
code: Added a couple helpers & procs for coders
/:cl:
---
code/__DEFINES/animate.dm | 2 ++
code/__DEFINES/span.dm | 1 +
code/__DEFINES/tools.dm | 1 +
code/__HELPERS/_lists.dm | 17 ++++++++++
code/__HELPERS/matrices.dm | 4 +++
code/__HELPERS/names.dm | 2 ++
code/_globalvars/admin.dm | 2 ++
code/_globalvars/lists/engineering.dm | 23 +++++++++++++
code/datums/datum.dm | 34 +++++++++++++++++++
code/game/objects/items/debug_items.dm | 22 +-----------
.../crossbreeding/_status_effects.dm | 2 +-
.../xenobiology/crossbreeding/stabilized.dm | 19 +----------
.../organs/internal/heart/heart_anomalock.dm | 4 ---
interface/stylesheet.dm | 1 +
tgstation.dme | 2 ++
.../tgui-panel/styles/tgchat/chat-dark.scss | 5 +++
.../tgui-panel/styles/tgchat/chat-light.scss | 5 +++
17 files changed, 102 insertions(+), 44 deletions(-)
create mode 100644 code/__DEFINES/animate.dm
create mode 100644 code/_globalvars/lists/engineering.dm
diff --git a/code/__DEFINES/animate.dm b/code/__DEFINES/animate.dm
new file mode 100644
index 00000000000..e430022d1bb
--- /dev/null
+++ b/code/__DEFINES/animate.dm
@@ -0,0 +1,2 @@
+/// The animation/chain runs indefinitely
+#define INDEFINITE -1
diff --git a/code/__DEFINES/span.dm b/code/__DEFINES/span.dm
index f371df8157e..b98b8bd1b7f 100644
--- a/code/__DEFINES/span.dm
+++ b/code/__DEFINES/span.dm
@@ -145,6 +145,7 @@
#define span_tinydanger(str) ("" + str + "")
#define span_tinynotice(str) ("" + str + "")
#define span_tinynoticeital(str) ("" + str + "")
+#define span_tinynicegreen(str) ("" + str + "")
#define span_unconscious(str) ("" + str + "")
#define span_userdanger(str) ("" + str + "")
#define span_warning(str) ("" + str + "")
diff --git a/code/__DEFINES/tools.dm b/code/__DEFINES/tools.dm
index 2d1ed94cdb1..b086860bc7d 100644
--- a/code/__DEFINES/tools.dm
+++ b/code/__DEFINES/tools.dm
@@ -1,4 +1,5 @@
// Tool types, if you add new ones please add them to /obj/item/debug/omnitool in code/game/objects/items/debug_items.dm
+// and to GLOB.all_tool_behaviours in code/_globalvars/lists/engineering.dm
#define TOOL_CROWBAR "crowbar"
#define TOOL_MULTITOOL "multitool"
#define TOOL_SCREWDRIVER "screwdriver"
diff --git a/code/__HELPERS/_lists.dm b/code/__HELPERS/_lists.dm
index d1c6e6bb7d6..cb4eb9b724a 100644
--- a/code/__HELPERS/_lists.dm
+++ b/code/__HELPERS/_lists.dm
@@ -1327,3 +1327,20 @@
&& deep_compare_list(log_1["stack"], log_2["stack"])
else
return TRUE
+
+
+/**
+ * Similar to pick_weight_recursive, except without the weight part, meaning it should hopefully not take
+ * up as much computing power for things that don't +need+ weights.
+ * * * Able to handle cases such as:
+ * * pick_recursive(list(a), list(b), list(c))
+ * * pick_recursive(list(list(a), list(b)))
+ * * pick_recursive(a, list(b), list(list(c), list(d)))
+ * * pick_recusrive(list(a, b, c), d, e)
+ * Really any combination of lists & vars, as long as the passed lists aren't empty
+ */
+/proc/pick_recursive(...)
+ var/result = pick(args)
+ while(islist(result))
+ result = pick(result)
+ return result
diff --git a/code/__HELPERS/matrices.dm b/code/__HELPERS/matrices.dm
index 8a5534e3827..777b4415a9d 100644
--- a/code/__HELPERS/matrices.dm
+++ b/code/__HELPERS/matrices.dm
@@ -86,6 +86,10 @@ c f 1
/matrix/proc/get_y_shift()
. = f
+///The angle of this matrix
+/matrix/proc/get_angle()
+ . = -ATAN2(a,d)
+
/////////////////////
// COLOUR MATRICES //
/////////////////////
diff --git a/code/__HELPERS/names.dm b/code/__HELPERS/names.dm
index b5f6d484f2e..89541c1c187 100644
--- a/code/__HELPERS/names.dm
+++ b/code/__HELPERS/names.dm
@@ -376,6 +376,8 @@ GLOBAL_DATUM(syndicate_code_response_regex, /regex)
return "a blood filter"
if(TOOL_ROLLINGPIN)
return "a rolling pin"
+ if(TOOL_RUSTSCRAPER)
+ return "a rust scraper"
else
return "something... but the gods didn't set this up right (Please report this bug)"
diff --git a/code/_globalvars/admin.dm b/code/_globalvars/admin.dm
index 31281276dc0..93ff52f7f7c 100644
--- a/code/_globalvars/admin.dm
+++ b/code/_globalvars/admin.dm
@@ -144,6 +144,8 @@ GLOBAL_LIST_INIT(spanname_to_formatting, list(
"Tape Recorder" = "tape_recorder",
"Tiny Notice" = "tinynotice",
"Tiny Notice Italic" = "tinynoticeital",
+ "Tiny Danger" = "tinydanger",
+ "Tiny Nice Green" = "tinynicegreen",
"Unconscious" = "unconscious",
"User Danger" = "userdanger",
"Warning" = "warning",
diff --git a/code/_globalvars/lists/engineering.dm b/code/_globalvars/lists/engineering.dm
new file mode 100644
index 00000000000..70114905b5f
--- /dev/null
+++ b/code/_globalvars/lists/engineering.dm
@@ -0,0 +1,23 @@
+// List of all tool behaviours.
+GLOBAL_LIST_INIT(all_tool_behaviours, list(
+ TOOL_ANALYZER,
+ TOOL_BLOODFILTER,
+ TOOL_BONESET,
+ TOOL_CAUTERY,
+ TOOL_CROWBAR,
+ TOOL_DRILL,
+ TOOL_HEMOSTAT,
+ TOOL_KNIFE,
+ TOOL_MINING,
+ TOOL_MULTITOOL,
+ TOOL_RETRACTOR,
+ TOOL_ROLLINGPIN,
+ TOOL_RUSTSCRAPER,
+ TOOL_SAW,
+ TOOL_SCALPEL,
+ TOOL_SCREWDRIVER,
+ TOOL_SHOVEL,
+ TOOL_WELDER,
+ TOOL_WIRECUTTER,
+ TOOL_WRENCH,
+))
diff --git a/code/datums/datum.dm b/code/datums/datum.dm
index 0dc21ab494d..87b51584967 100644
--- a/code/datums/datum.dm
+++ b/code/datums/datum.dm
@@ -385,6 +385,40 @@
animate(filter, new_params, time = time, easing = easing, loop = loop)
modify_filter(name, new_params)
+/** Keeps the steps in the correct order.
+* Arguments:
+* * params - the parameters you want this step to animate to
+* * duration - the time it takes to animate this step
+* * easing - the type of easing this step has
+*/
+/proc/FilterChainStep(params, duration, easing)
+ params -= "type"
+ return list("params"= params, "duration"=duration, "easing"=easing)
+
+/** Similar to transition_filter(), except it creates an animation chain that moves between a list of states.
+ * Arguments:
+ * * name - Filter name
+ * * num_loops - Amount of times the chain loops. INDEFINITE = Infinite
+ * * ... - a list of each link in the animation chain. Use FilterChainStep(params, duration, easing) for each link
+ * Example use:
+ * * add_filter("blue_pulse", 1, color_matrix_filter(COLOR_WHITE))
+ * * transition_filter_chain(src, "blue_pulse", INDEFINITE,\
+ * * FilterChainStep(color_matrix_filter(COLOR_BLUE), 10 SECONDS, CUBIC_EASING),\
+ * * FilterChainStep(color_matrix_filter(COLOR_WHITE), 10 SECONDS, CUBIC_EASING))
+ * The above code would edit a color_matrix_filter() to slowly turn blue over 10 seconds before returning back to white 10 seconds after, repeating this chain forever.
+ */
+/datum/proc/transition_filter_chain(name, num_loops, ...)
+ var/list/transition_steps = args.Copy(3)
+ var/filter = get_filter(name)
+ if(!filter)
+ return
+ var/list/first_step = transition_steps[1]
+ animate(filter, first_step["params"], time = first_step["duration"], easing = first_step["easing"], loop = num_loops)
+ for(var/transition_step in 2 to length(transition_steps))
+ var/list/this_step = transition_steps[transition_step]
+ animate(this_step["params"], time = this_step["duration"], easing = this_step["easing"])
+
+
/// Updates the priority of the passed filter key
/datum/proc/change_filter_priority(name, new_priority)
if(!filter_data || !filter_data[name])
diff --git a/code/game/objects/items/debug_items.dm b/code/game/objects/items/debug_items.dm
index 9af69c33d7f..e52cced51bf 100644
--- a/code/game/objects/items/debug_items.dm
+++ b/code/game/objects/items/debug_items.dm
@@ -52,27 +52,7 @@
return TRUE
/obj/item/debug/omnitool/get_all_tool_behaviours()
- return list(TOOL_ANALYZER,
- TOOL_BLOODFILTER,
- TOOL_BONESET,
- TOOL_CAUTERY,
- TOOL_CROWBAR,
- TOOL_DRILL,
- TOOL_HEMOSTAT,
- TOOL_KNIFE,
- TOOL_MINING,
- TOOL_MULTITOOL,
- TOOL_RETRACTOR,
- TOOL_ROLLINGPIN,
- TOOL_RUSTSCRAPER,
- TOOL_SAW,
- TOOL_SCALPEL,
- TOOL_SCREWDRIVER,
- TOOL_SHOVEL,
- TOOL_WELDER,
- TOOL_WIRECUTTER,
- TOOL_WRENCH,
- )
+ return GLOB.all_tool_behaviours
/obj/item/debug/omnitool/attack_self(mob/user)
if(!user)
diff --git a/code/modules/research/xenobiology/crossbreeding/_status_effects.dm b/code/modules/research/xenobiology/crossbreeding/_status_effects.dm
index fb419a60f1a..d51a0c04774 100644
--- a/code/modules/research/xenobiology/crossbreeding/_status_effects.dm
+++ b/code/modules/research/xenobiology/crossbreeding/_status_effects.dm
@@ -463,7 +463,7 @@
if(isnull(linked_extract))
qdel(src)
return
- if(linked_extract.get_held_mob() == owner)
+ if(get_atom_on_turf(linked_extract, /mob/living) == owner)
return
owner.balloon_alert(owner, "[colour] extract faded!")
if(!QDELETED(linked_extract))
diff --git a/code/modules/research/xenobiology/crossbreeding/stabilized.dm b/code/modules/research/xenobiology/crossbreeding/stabilized.dm
index 14bbdd6dda5..fc1c219f2fb 100644
--- a/code/modules/research/xenobiology/crossbreeding/stabilized.dm
+++ b/code/modules/research/xenobiology/crossbreeding/stabilized.dm
@@ -22,25 +22,8 @@ Stabilized extracts:
qdel(linked_effect)
return ..()
-/// Returns the mob that is currently holding us if we are either in their inventory or a backpack analogue.
-/// Returns null if it's in an invalid location, so that we can check explicitly for null later.
-/obj/item/slimecross/stabilized/proc/get_held_mob()
- if(isnull(loc))
- return null
- if(isliving(loc))
- return loc
- // Snowflake check for modsuit backpacks, which should be valid but are 3 rather than 2 steps from the owner
- if(istype(loc, /obj/item/mod/module/storage))
- var/obj/item/mod/module/storage/mod_backpack = loc
- var/mob/living/modsuit_wearer = mod_backpack.mod?.wearer
- return modsuit_wearer ? modsuit_wearer : null
- var/nested_loc = loc.loc
- if (isliving(nested_loc))
- return nested_loc
- return null
-
/obj/item/slimecross/stabilized/process()
- var/mob/living/holder = get_held_mob()
+ var/mob/living/holder = get_atom_on_turf(src, /mob/living)
if(isnull(holder))
return
var/effectpath = /datum/status_effect/stabilized
diff --git a/code/modules/surgery/organs/internal/heart/heart_anomalock.dm b/code/modules/surgery/organs/internal/heart/heart_anomalock.dm
index 06d70385bc3..b19888347b6 100644
--- a/code/modules/surgery/organs/internal/heart/heart_anomalock.dm
+++ b/code/modules/surgery/organs/internal/heart/heart_anomalock.dm
@@ -118,10 +118,6 @@
balloon_alert(organ_owner, "your heart strengthtens")
playsound(organ_owner, 'sound/items/eshield_recharge.ogg', 40)
-///Returns the mob we are implanted in so that the electricity effect doesn't runtime
-/obj/item/organ/heart/cybernetic/anomalock/proc/get_held_mob()
- return owner
-
/obj/item/organ/heart/cybernetic/anomalock/item_interaction(mob/living/user, obj/item/tool, list/modifiers)
if(!istype(tool, required_anomaly))
return NONE
diff --git a/interface/stylesheet.dm b/interface/stylesheet.dm
index 7b75a36790a..0c0fd796145 100644
--- a/interface/stylesheet.dm
+++ b/interface/stylesheet.dm
@@ -95,6 +95,7 @@ h1.alert, h2.alert {color: #000000;}
.grey {color: #838383;}
.nicegreen {color: #14a833;}
.boldnicegreen {color: #14a833; font-weight: bold;}
+.tinynicegreen {color: #14a833; font-size: 85%;}
.cult {color: #973e3b;}
.cultlarge {color: #973e3b; font-weight: bold; font-size: 3;}
.narsie {color: #973e3b; font-weight: bold; font-size: 15;}
diff --git a/tgstation.dme b/tgstation.dme
index b4ce9bf6245..5fb6f9d4bf2 100644
--- a/tgstation.dme
+++ b/tgstation.dme
@@ -42,6 +42,7 @@
#include "code\__DEFINES\airlock.dm"
#include "code\__DEFINES\alarm.dm"
#include "code\__DEFINES\alerts.dm"
+#include "code\__DEFINES\animate.dm"
#include "code\__DEFINES\announcements.dm"
#include "code\__DEFINES\anomaly.dm"
#include "code\__DEFINES\antagonists.dm"
@@ -694,6 +695,7 @@
#include "code\_globalvars\lists\client.dm"
#include "code\_globalvars\lists\color.dm"
#include "code\_globalvars\lists\crafting.dm"
+#include "code\_globalvars\lists\engineering.dm"
#include "code\_globalvars\lists\flavor_misc.dm"
#include "code\_globalvars\lists\icons.dm"
#include "code\_globalvars\lists\keybindings.dm"
diff --git a/tgui/packages/tgui-panel/styles/tgchat/chat-dark.scss b/tgui/packages/tgui-panel/styles/tgchat/chat-dark.scss
index ba39d32d70a..c8128cc3aa7 100644
--- a/tgui/packages/tgui-panel/styles/tgchat/chat-dark.scss
+++ b/tgui/packages/tgui-panel/styles/tgchat/chat-dark.scss
@@ -587,6 +587,11 @@ em {
font-weight: bold;
}
+.tinynicegreen {
+ color: hsl(132.8, 93.4%, 29.6%);
+ font-size: 85%;
+}
+
.blob {
color: hsl(16.1, 100%, 46.7%);
}
diff --git a/tgui/packages/tgui-panel/styles/tgchat/chat-light.scss b/tgui/packages/tgui-panel/styles/tgchat/chat-light.scss
index 45a9826362e..f8280225fe0 100644
--- a/tgui/packages/tgui-panel/styles/tgchat/chat-light.scss
+++ b/tgui/packages/tgui-panel/styles/tgchat/chat-light.scss
@@ -600,6 +600,11 @@ h2.alert {
font-weight: bold;
}
+.tinynicegreen {
+ color: hsl(132.6, 78.7%, 36.9%);
+ font-size: 85%;
+}
+
.cult {
color: hsl(2, 43.8%, 41.2%);
}