From 416dea02aa56fdc3224fe8bce438b73360846067 Mon Sep 17 00:00:00 2001
From: tonty <39193182+tontyGH@users.noreply.github.com>
Date: Thu, 13 Nov 2025 01:09:49 -0500
Subject: [PATCH] [MDB IGNORE] isolates signpost teleporting into new component
/datum/component/houlihan_teleport (#93810)
## About The Pull Request
Isolates signpost teleport code into a component
`/datum/component/houlihan_teleport`, which takes a question argument
and a list of zlevels.
Removes `/obj/structure/no_effect_signpost` and turns existing mapped-in
instances into `/obj/structure/signpost`s
Adds/documents/fixes some attack signals that were added to the element
## Jebediah
## Changelog
:cl:
refactor: Signposts have had their code improved internally. Please make
an issue if a signpost that should teleport you no longer can.
/:cl:
---
_maps/RandomRuins/SpaceRuins/clownplanet.dmm | 4 +-
_maps/RandomZLevels/TheBeach.dmm | 2 +-
_maps/RandomZLevels/museum.dmm | 2 +-
.../map_files/IceBoxStation/IceBoxStation.dmm | 4 +-
.../map_files/NebulaStation/NebulaStation.dmm | 2 +-
.../lazy_templates/heretic_sacrifice.dmm | 2 +-
_maps/virtual_domains/island_brawl.dmm | 2 +-
.../signals_atom/signals_atom_attack.dm | 8 +-
code/_onclick/other_mobs.dm | 4 +-
code/datums/components/houlihan_teleport.dm | 93 +++++++++++++++++++
.../sacrifice_knowledge/sacrifice_map.dm | 22 -----
code/modules/awaymissions/signpost.dm | 80 ++++++----------
tgstation.dme | 1 +
.../Scripts/93810_refactor_signposts.txt | 1 +
14 files changed, 139 insertions(+), 88 deletions(-)
create mode 100644 code/datums/components/houlihan_teleport.dm
create mode 100644 tools/UpdatePaths/Scripts/93810_refactor_signposts.txt
diff --git a/_maps/RandomRuins/SpaceRuins/clownplanet.dmm b/_maps/RandomRuins/SpaceRuins/clownplanet.dmm
index fa0b50cc443..a9e023ba6c4 100644
--- a/_maps/RandomRuins/SpaceRuins/clownplanet.dmm
+++ b/_maps/RandomRuins/SpaceRuins/clownplanet.dmm
@@ -118,7 +118,9 @@
/turf/open/floor/iron/bluespace,
/area/ruin/space/has_grav/powered/clownplanet)
"az" = (
-/obj/structure/signpost,
+/obj/structure/signpost{
+ teleports = 1
+ },
/turf/open/floor/grass{
color = "#1eff00"
},
diff --git a/_maps/RandomZLevels/TheBeach.dmm b/_maps/RandomZLevels/TheBeach.dmm
index 6b29a5e2fc5..cc06de9ed5d 100644
--- a/_maps/RandomZLevels/TheBeach.dmm
+++ b/_maps/RandomZLevels/TheBeach.dmm
@@ -93,7 +93,7 @@
/turf/open/floor/wood,
/area/awaymission/beach)
"bg" = (
-/obj/structure/no_effect_signpost{
+/obj/structure/signpost{
pixel_y = 6;
desc = "Northwest: Hotel. South: Seaside Bar. East: Dressing Rooms."
},
diff --git a/_maps/RandomZLevels/museum.dmm b/_maps/RandomZLevels/museum.dmm
index 4c7fe9782de..75a7b06b8be 100644
--- a/_maps/RandomZLevels/museum.dmm
+++ b/_maps/RandomZLevels/museum.dmm
@@ -119,7 +119,7 @@
/turf/open/floor/wood/large,
/area/awaymission/museum)
"bg" = (
-/obj/structure/no_effect_signpost{
+/obj/structure/signpost{
name = "if youre reading this you stink and also made by jimmyl"
},
/turf/open/floor/bluespace,
diff --git a/_maps/map_files/IceBoxStation/IceBoxStation.dmm b/_maps/map_files/IceBoxStation/IceBoxStation.dmm
index 9de5c04633a..39051d7f3f3 100644
--- a/_maps/map_files/IceBoxStation/IceBoxStation.dmm
+++ b/_maps/map_files/IceBoxStation/IceBoxStation.dmm
@@ -16602,7 +16602,7 @@
/turf/open/floor/iron,
/area/station/hallway/primary/central/fore)
"eCR" = (
-/obj/structure/no_effect_signpost{
+/obj/structure/signpost{
desc = "Now, where to go from here? That's a timeless question."
},
/turf/open/misc/asteroid/snow/icemoon,
@@ -18524,7 +18524,7 @@
/turf/open/floor/plating,
/area/station/maintenance/aft/greater)
"fep" = (
-/obj/structure/no_effect_signpost,
+/obj/structure/signpost,
/turf/open/misc/asteroid/snow/icemoon,
/area/icemoon/underground/explored)
"fez" = (
diff --git a/_maps/map_files/NebulaStation/NebulaStation.dmm b/_maps/map_files/NebulaStation/NebulaStation.dmm
index 612993993f1..5fcdbb8c55f 100644
--- a/_maps/map_files/NebulaStation/NebulaStation.dmm
+++ b/_maps/map_files/NebulaStation/NebulaStation.dmm
@@ -83271,7 +83271,7 @@
/turf/open/floor/iron/dark/textured,
/area/station/security/checkpoint/medical)
"mqY" = (
-/obj/structure/no_effect_signpost,
+/obj/structure/signpost,
/turf/open/misc/asteroid/airless,
/area/space/nearstation)
"mqZ" = (
diff --git a/_maps/templates/lazy_templates/heretic_sacrifice.dmm b/_maps/templates/lazy_templates/heretic_sacrifice.dmm
index 7a752a33e73..b938a35278b 100644
--- a/_maps/templates/lazy_templates/heretic_sacrifice.dmm
+++ b/_maps/templates/lazy_templates/heretic_sacrifice.dmm
@@ -19,7 +19,7 @@
/turf/open/floor/stone,
/area/centcom/heretic_sacrifice/flesh)
"cW" = (
-/obj/structure/no_effect_signpost/void,
+/obj/structure/signpost/void,
/turf/open/misc/asteroid,
/area/centcom/heretic_sacrifice/void)
"dX" = (
diff --git a/_maps/virtual_domains/island_brawl.dmm b/_maps/virtual_domains/island_brawl.dmm
index afb11be05ed..07003db1aa5 100644
--- a/_maps/virtual_domains/island_brawl.dmm
+++ b/_maps/virtual_domains/island_brawl.dmm
@@ -2551,7 +2551,7 @@
/turf/open/floor/wood,
/area/virtual_domain)
"Gp" = (
-/obj/structure/no_effect_signpost{
+/obj/structure/signpost{
pixel_y = 6;
desc = "Northwest: Hotel. South: Seaside Bar. East: Dressing Rooms."
},
diff --git a/code/__DEFINES/dcs/signals/signals_atom/signals_atom_attack.dm b/code/__DEFINES/dcs/signals/signals_atom/signals_atom_attack.dm
index 0219f795c32..16c3fb9eb12 100644
--- a/code/__DEFINES/dcs/signals/signals_atom/signals_atom_attack.dm
+++ b/code/__DEFINES/dcs/signals/signals_atom/signals_atom_attack.dm
@@ -14,7 +14,7 @@
#define COMPONENT_NO_AFTERATTACK (1<<0)
///from base of atom/attack_hulk(): (/mob/living/carbon/human)
#define COMSIG_ATOM_HULK_ATTACK "hulk_attack"
-///from base of atom/animal_attack(): (/mob/user)
+///from base of atom/animal_attack(): (/mob/user, list/modifiers)
#define COMSIG_ATOM_ATTACK_ANIMAL "attack_animal"
//from base of atom/attack_basic_mob(): (/mob/user)
#define COMSIG_ATOM_ATTACK_BASIC_MOB "attack_basic_mob"
@@ -43,16 +43,18 @@
#define COMSIG_ATOM_ATTACK_GHOST "atom_attack_ghost"
///from base of atom/attack_hand(): (mob/user, list/modifiers)
#define COMSIG_ATOM_ATTACK_HAND "atom_attack_hand"
-///from base of atom/attack_paw(): (mob/user)
+///from base of atom/attack_paw(): (mob/user, list/modifiers)
#define COMSIG_ATOM_ATTACK_PAW "atom_attack_paw"
///from base of atom/mech_melee_attack(): (obj/vehicle/sealed/mecha/mecha_attacker, mob/living/user)
#define COMSIG_ATOM_ATTACK_MECH "atom_attack_mech"
-/// from base of atom/attack_robot(): (mob/user)
+/// from base of atom/attack_robot(): (mob/user, list/modifiers)
#define COMSIG_ATOM_ATTACK_ROBOT "atom_attack_robot"
/// from base of atom/attack_robot_secondary(): (mob/user)
#define COMSIG_ATOM_ATTACK_ROBOT_SECONDARY "atom_attack_robot_secondary"
/// from base of atom/attack_ai(): (mob/user, params)
#define COMSIG_ATOM_ATTACK_AI "atom_attack_ai"
+/// from base of atom/attack_larva(): (mob/user, list/modifiers)
+#define COMSIG_ATOM_ATTACK_LARVA "atom_attack_larva"
///from relay_attackers element: (atom/attacker, attack_flags)
#define COMSIG_ATOM_WAS_ATTACKED "atom_was_attacked"
///Called before a atom gets something tilted on them. If [COMPONENT_IMMUNE_TO_TILT_AND_CRUSH] is returned in a signal, the atom will be unaffected: (atom/target, atom/source)
diff --git a/code/_onclick/other_mobs.dm b/code/_onclick/other_mobs.dm
index eab5f0a7cd9..1cd89773c55 100644
--- a/code/_onclick/other_mobs.dm
+++ b/code/_onclick/other_mobs.dm
@@ -175,7 +175,7 @@
* Called when a simple animal is unarmed attacking / clicking on this atom.
*/
/atom/proc/attack_animal(mob/user, list/modifiers)
- SEND_SIGNAL(src, COMSIG_ATOM_ATTACK_ANIMAL, user)
+ SEND_SIGNAL(src, COMSIG_ATOM_ATTACK_ANIMAL, user, modifiers)
/**
* Called when a simple animal or basic mob right clicks an atom.
@@ -235,7 +235,7 @@
return TRUE
/atom/proc/attack_larva(mob/user, list/modifiers)
- return
+ SEND_SIGNAL(src, COMSIG_ATOM_ATTACK_LARVA, user, modifiers)
/**
* Called when an alien larva right clicks an atom.
diff --git a/code/datums/components/houlihan_teleport.dm b/code/datums/components/houlihan_teleport.dm
new file mode 100644
index 00000000000..b819742e495
--- /dev/null
+++ b/code/datums/components/houlihan_teleport.dm
@@ -0,0 +1,93 @@
+/// Teleports interactors onto a safe turf randomly picked from a list of z-levels.
+/datum/component/houlihan_teleport
+ dupe_mode = COMPONENT_DUPE_HIGHLANDER
+ /// Text that will appear in the alert prompt.
+ var/question = "Travel back?"
+ /// List of z-levels that the user can teleport to. By default, this is station z-levels.
+ var/list/zlevels
+
+/datum/component/houlihan_teleport/Initialize(question, zlevels)
+ . = ..()
+ if(!isstructure(parent))
+ return COMPONENT_INCOMPATIBLE
+
+ if(!isnull(question) && (!istext(question) || !length(question)))
+ stack_trace("received bad question argument, falling back to default")
+ question = null
+ src.question = question || initial(src.question)
+
+ if(!isnull(zlevels) && (!islist(zlevels) || !length(zlevels)))
+ stack_trace("received bad zlevels argument, falling back to default")
+ zlevels = null
+ src.zlevels = zlevels || SSmapping.levels_by_trait(ZTRAIT_STATION)
+
+/datum/component/houlihan_teleport/RegisterWithParent()
+ RegisterSignals(parent, list(COMSIG_ATOM_ATTACK_ROBOT, COMSIG_ATOM_ATTACK_PAW, COMSIG_ATOM_ATTACK_ANIMAL, COMSIG_ATOM_ATTACK_LARVA), PROC_REF(handle_generic_attack))
+ RegisterSignal(parent, COMSIG_ATOM_ATTACK_HAND, PROC_REF(handle_attack_hand))
+ RegisterSignal(parent, COMSIG_ATOM_ATTACKBY, PROC_REF(handle_attackby))
+
+/datum/component/houlihan_teleport/UnregisterFromParent()
+ UnregisterSignal(parent, list(
+ COMSIG_ATOM_ATTACK_ROBOT, COMSIG_ATOM_ATTACK_PAW, COMSIG_ATOM_ATTACK_ANIMAL, COMSIG_ATOM_ATTACK_LARVA, //handle_generic_attack
+ COMSIG_ATOM_ATTACK_HAND, //handle_attack_hand
+ COMSIG_ATOM_ATTACKBY, //handle_attackby
+ ))
+
+/datum/component/houlihan_teleport/proc/get_me_outta_here(obj/structure/source, mob/living/user)
+ var/said_yes = (tgui_alert(user, question, source.name, list("Yes", "No")) == "Yes")
+ if(!said_yes || !source.Adjacent(user))
+ return
+
+ var/turf/destination_turf = zlevels ? find_safe_turf(zlevels) : get_safe_random_station_turf_equal_weight()
+ if(!destination_turf)
+ source.balloon_alert(user, "uh oh...")
+ to_chat(user, span_warning("Nothing happens. You feel like this is a bad sign."))
+ return
+
+ var/turf/user_turf = get_turf(user)
+ var/atom/movable/dragged = user.pulling
+ user.forceMove(destination_turf)
+ user_turf.balloon_alert_to_viewers("(pop)")
+ if(dragged)
+ var/turf/dragged_turf = get_turf(dragged)
+ dragged.forceMove(destination_turf)
+ user.start_pulling(dragged, force = TRUE)
+ dragged_turf.balloon_alert_to_viewers("(pop)")
+
+ to_chat(list(user, dragged), span_notice("You blink and find yourself in [get_area_name(destination_turf)]."))
+ user.emote("blink")
+ astype(dragged, /mob)?.emote("blink") // shhhhh just let it happen
+
+/datum/component/houlihan_teleport/proc/handle_generic_attack(obj/structure/source, mob/living/user, list/modifiers)
+ SIGNAL_HANDLER
+
+ if(user.combat_mode)
+ return NONE
+
+ if(iscyborg(user) && !source.Adjacent(user))
+ return NONE
+
+ INVOKE_ASYNC(src, PROC_REF(get_me_outta_here), source, user)
+ return COMPONENT_NO_AFTERATTACK
+
+/datum/component/houlihan_teleport/proc/handle_attack_hand(obj/structure/source, mob/user, list/modifiers)
+ SIGNAL_HANDLER
+
+ if(!isliving(user))
+ return NONE
+
+ var/mob/living/living_user = user
+ if(living_user.combat_mode)
+ return NONE
+
+ INVOKE_ASYNC(src, PROC_REF(get_me_outta_here), source, living_user)
+ return COMPONENT_CANCEL_ATTACK_CHAIN
+
+/datum/component/houlihan_teleport/proc/handle_attackby(obj/structure/source, obj/item/item, mob/living/user, list/modifiers)
+ SIGNAL_HANDLER
+
+ if(user.combat_mode)
+ return NONE
+
+ INVOKE_ASYNC(src, PROC_REF(get_me_outta_here), source, user)
+ return COMPONENT_NO_AFTERATTACK
diff --git a/code/modules/antagonists/heretic/knowledge/sacrifice_knowledge/sacrifice_map.dm b/code/modules/antagonists/heretic/knowledge/sacrifice_knowledge/sacrifice_map.dm
index 3dee1c0176f..30d9f89a424 100644
--- a/code/modules/antagonists/heretic/knowledge/sacrifice_knowledge/sacrifice_map.dm
+++ b/code/modules/antagonists/heretic/knowledge/sacrifice_knowledge/sacrifice_map.dm
@@ -38,28 +38,6 @@ GLOBAL_LIST_EMPTY(heretic_sacrifice_landmarks)
name = "lock heretic sacrifice landmark"
for_heretic_path = PATH_LOCK
-// A fluff signpost object that doesn't teleport you somewhere when you touch it.
-/obj/structure/no_effect_signpost
- name = "signpost"
- desc = "Won't somebody give me a sign?"
- icon = 'icons/obj/fluff/general.dmi'
- icon_state = "signpost"
- anchored = TRUE
- density = TRUE
-
-/obj/structure/no_effect_signpost/void
- name = "signpost at the edge of the universe"
- desc = "A direction in the directionless void."
- density = FALSE
- /// Brightness of the signpost.
- var/range = 2
- /// Light power of the signpost.
- var/power = 0.8
-
-/obj/structure/no_effect_signpost/void/Initialize(mapload)
- . = ..()
- set_light(range, power)
-
// Some VERY dim lights, used for the void sacrifice realm.
/obj/machinery/light/very_dim
nightshift_allowed = FALSE
diff --git a/code/modules/awaymissions/signpost.dm b/code/modules/awaymissions/signpost.dm
index 4a2f63b8cfb..b822043b4a2 100644
--- a/code/modules/awaymissions/signpost.dm
+++ b/code/modules/awaymissions/signpost.dm
@@ -1,71 +1,45 @@
-/*An alternative to exit gateways, signposts send you back to somewhere safe onstation with their semiotic magic.*/
/obj/structure/signpost
+ name = "signpost"
+ desc = "Won't somebody give me a sign?"
icon = 'icons/obj/fluff/general.dmi'
icon_state = "signpost"
anchored = TRUE
density = TRUE
- var/question = "Travel back?"
- var/list/zlevels
+
+ /// Whether or not this enables the Houlihan element.
+ var/teleports = FALSE
+ /// Optional replacement for the teleport question.
+ var/question = null
+ /// Optional list of z-levels that the Houlihan element can send us to. Modify this on Initialize().
+ VAR_FINAL/list/zlevels = null
/obj/structure/signpost/Initialize(mapload)
- . = ..()
+ ..()
set_light(2)
- zlevels = SSmapping.levels_by_trait(ZTRAIT_STATION)
+ return INITIALIZE_HINT_LATELOAD
-/obj/structure/signpost/interact(mob/user)
- . = ..()
- if(.)
- return
- if(tgui_alert(usr,question,name,list("Yes","No")) != "Yes" && !Adjacent(user))
- return
+/obj/structure/signpost/LateInitialize()
+ // This is here cause we wanna be super sure zlevels is properly initialized
+ if(teleports)
+ AddComponent(/datum/component/houlihan_teleport, question, zlevels)
- var/turf/safe_dropoff = zlevels ? find_safe_turf(zlevels) : get_safe_random_station_turf_equal_weight()
- if(!safe_dropoff)
- to_chat(user, "Nothing happens. You feel that this is a bad sign.")
- return
-
- var/atom/movable/pulled = user.pulling
- user.forceMove(safe_dropoff)
- if(pulled)
- pulled.forceMove(safe_dropoff)
- user.start_pulling(pulled)
- to_chat(user, span_notice("You blink and find yourself in [get_area_name(safe_dropoff)]."))
-
-/obj/structure/signpost/attackby(obj/item/W, mob/user, list/modifiers, list/attack_modifiers)
- return interact(user)
-
-/obj/structure/signpost/attack_paw(mob/user, list/modifiers)
- return interact(user)
-
-/obj/structure/signpost/attack_hulk(mob/user)
- return
-
-/obj/structure/signpost/attack_larva(mob/user, list/modifiers)
- return interact(user)
-
-/obj/structure/signpost/attack_robot(mob/user)
- if (Adjacent(user))
- return interact(user)
-
-/obj/structure/signpost/attack_animal(mob/user, list/modifiers)
- return interact(user)
+/* ----------------- */
/obj/structure/signpost/salvation
name = "\proper salvation"
desc = "In the darkest times, we will find our way home."
resistance_flags = INDESTRUCTIBLE
+ teleports = TRUE
-/obj/structure/signpost/exit
- name = "exit"
- desc = "Make sure to bring all your belongings with you when you \
- exit the area."
- question = "Leave? You might never come back."
+/obj/structure/signpost/void
+ name = "signpost at the edge of the universe"
+ desc = "A direction in the directionless void."
+ density = FALSE
+ /// Brightness of the signpost.
+ var/range = 2
+ /// Light power of the signpost.
+ var/power = 0.8
-/obj/structure/signpost/exit/Initialize(mapload)
+/obj/structure/signpost/void/Initialize(mapload)
. = ..()
- zlevels = list()
- for(var/i in 1 to world.maxz)
- zlevels += i
- zlevels -= SSmapping.levels_by_trait(ZTRAIT_CENTCOM) // no easy victory, even with meme signposts
- // also, could you think of the horror if they ended up in a holodeck
- // template or something
+ set_light(range, power)
diff --git a/tgstation.dme b/tgstation.dme
index d30e4926dca..eda78e46494 100644
--- a/tgstation.dme
+++ b/tgstation.dme
@@ -1197,6 +1197,7 @@
#include "code\datums\components\hide_weather_planes.dm"
#include "code\datums\components\holderloving.dm"
#include "code\datums\components\holographic_nature.dm"
+#include "code\datums\components\houlihan_teleport.dm"
#include "code\datums\components\igniter.dm"
#include "code\datums\components\infective.dm"
#include "code\datums\components\ingredients_holder.dm"
diff --git a/tools/UpdatePaths/Scripts/93810_refactor_signposts.txt b/tools/UpdatePaths/Scripts/93810_refactor_signposts.txt
new file mode 100644
index 00000000000..4a77f273a56
--- /dev/null
+++ b/tools/UpdatePaths/Scripts/93810_refactor_signposts.txt
@@ -0,0 +1 @@
+/obj/structure/no_effect_signpost/@SUBTYPES : /obj/structure/signpost/@SUBTYPES{@OLD}