mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-08-27 07:08:00 +01:00
Player-craftable Trapdoors (#68920)
Makes trapdoors player-craftable. Player-crafted trapdoors have a tiny outline as well as being visible on examine. (Mapped in trapdoors have conspicuous = FALSE by default) Trapdoors can be made by using a trapdoor kit (crafted via player crafting menu) on openspace. Trapdoor electronics / assembly can be made via autolathe or engineering lathe. A preloaded trapdoor remote (optional) can be made by crafting the electronics with a compact remote (from science lathe / circuit lab) and some cable coil. Also allows unlinking trapdoors via a multitool, decreased trapdoor link range, and made some changes to trapdoor code. Added change: Trapdoors now don't break with just a crowbar Why It's Good For The Game Trapdoors currently can only be added in by mappers and this would allow for a lot of interesting contraptions, while having player-crafted trapdoors be detectable provides some counterplay Picture trapdoorlookdemo Changelog cl add: You can now make trapdoors. Craft a trapdoor kit and use it on an openspace tile to make one, then link and activate it with some trapdoor electronics (printable at an autolathe or the engineering lathe) and optionally a trapdoor remote (crafted in personal crafting menu). qol: You can now unlink trapdoors by using a multitool on them. balance: Trapdoors now won't break if you just crowbar them. You need to block them from closing, such as with a lattice, cover it up with a wall, or fully destroy the floor tile its on to get rid of them. /cl
This commit is contained in:
@@ -4,6 +4,7 @@
|
||||
#define CHANGETURF_SKIP (1<<3) // A flag for PlaceOnTop to just instance the new turf instead of calling ChangeTurf. Used for uninitialized turfs NOTHING ELSE
|
||||
#define CHANGETURF_INHERIT_AIR (1<<4) // Inherit air from previous turf. Implies CHANGETURF_IGNORE_AIR
|
||||
#define CHANGETURF_RECALC_ADJACENT (1<<5) //Immediately recalc adjacent atmos turfs instead of queuing.
|
||||
#define CHANGETURF_TRAPDOOR_INDUCED (1<<6) // Caused by a trapdoor, for trapdoor to know that this changeturf was caused by itself
|
||||
|
||||
#define IS_OPAQUE_TURF(turf) (turf.directional_opacity == ALL_CARDINALS)
|
||||
|
||||
|
||||
@@ -759,6 +759,29 @@
|
||||
time = 20 SECONDS
|
||||
category = CAT_MISC
|
||||
|
||||
/datum/crafting_recipe/trapdoor_kit
|
||||
name = "Trapdoor Construction Kit"
|
||||
result = /obj/item/trapdoor_kit
|
||||
reqs = list(/obj/item/stack/sheet/iron = 4,
|
||||
/obj/item/stack/rods = 4,
|
||||
/obj/item/stack/cable_coil = 10,
|
||||
/obj/item/stock_parts/manipulator = 2,
|
||||
/obj/item/assembly/signaler = 1)
|
||||
tool_behaviors = list(TOOL_WELDER, TOOL_SCREWDRIVER)
|
||||
time = 10 SECONDS
|
||||
category = CAT_MISC
|
||||
|
||||
/datum/crafting_recipe/trapdoor_remote
|
||||
name = "Trapdoor Remote"
|
||||
result = /obj/item/trapdoor_remote/preloaded // since its useless without its assembly just require an assembly to craft it
|
||||
reqs = list(
|
||||
/obj/item/compact_remote = 1,
|
||||
/obj/item/stack/cable_coil = 5,
|
||||
/obj/item/assembly/trapdoor = 1)
|
||||
tool_behaviors = list(TOOL_SCREWDRIVER, TOOL_WIRECUTTER)
|
||||
time = 5 SECONDS
|
||||
category = CAT_MISC
|
||||
|
||||
/datum/crafting_recipe/mousetrap
|
||||
name = "Mouse Trap"
|
||||
result = /obj/item/assembly/mousetrap
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
///makes this file more legible
|
||||
#define IS_OPEN(parent) isgroundlessturf(parent)
|
||||
///distance a trapdoor will accept a link request.
|
||||
#define TRAPDOOR_LINKING_SEARCH_RANGE 7
|
||||
#define TRAPDOOR_LINKING_SEARCH_RANGE 4
|
||||
|
||||
/**
|
||||
* ## trapdoor component!
|
||||
@@ -15,12 +15,21 @@
|
||||
var/obj/item/assembly/trapdoor/assembly
|
||||
///path of the turf this should change into when the assembly is pulsed. needed for openspace trapdoors knowing what to turn back into
|
||||
var/trapdoor_turf_path
|
||||
/// is this trapdoor "conspicuous" (ie. it gets examine text and overlay added)
|
||||
var/conspicuous
|
||||
/// overlay that makes trapdoors more obvious
|
||||
var/static/trapdoor_overlay
|
||||
|
||||
/datum/component/trapdoor/Initialize(starts_open, trapdoor_turf_path, assembly)
|
||||
/datum/component/trapdoor/Initialize(starts_open, trapdoor_turf_path, assembly, conspicuous = TRUE)
|
||||
if(!isopenturf(parent))
|
||||
return COMPONENT_INCOMPATIBLE
|
||||
|
||||
src.conspicuous = conspicuous
|
||||
src.assembly = assembly
|
||||
|
||||
if(!trapdoor_overlay)
|
||||
trapdoor_overlay = mutable_appearance('icons/turf/overlays.dmi', "border_black", ABOVE_NORMAL_TURF_LAYER)
|
||||
|
||||
if(IS_OPEN(parent))
|
||||
openspace_trapdoor_setup(trapdoor_turf_path, assembly)
|
||||
else
|
||||
@@ -38,14 +47,19 @@
|
||||
src.trapdoor_turf_path = parent.type
|
||||
if(assembly && assembly.stored_decals.len)
|
||||
reapply_all_decals()
|
||||
if(conspicuous)
|
||||
var/turf/parent_turf = parent
|
||||
parent_turf.add_overlay(trapdoor_overlay)
|
||||
|
||||
/datum/component/trapdoor/RegisterWithParent()
|
||||
. = ..()
|
||||
RegisterSignal(parent, COMSIG_TURF_CHANGE, .proc/turf_changed_pre)
|
||||
RegisterSignal(parent, COMSIG_PARENT_EXAMINE, .proc/on_examine)
|
||||
if(!src.assembly)
|
||||
RegisterSignal(SSdcs, COMSIG_GLOB_TRAPDOOR_LINK, .proc/on_link_requested)
|
||||
else
|
||||
RegisterSignal(assembly, COMSIG_ASSEMBLY_PULSED, .proc/toggle_trapdoor)
|
||||
RegisterSignal(parent, COMSIG_ATOM_TOOL_ACT(TOOL_MULTITOOL), .proc/try_unlink)
|
||||
|
||||
/datum/component/trapdoor/UnregisterFromParent()
|
||||
. = ..()
|
||||
@@ -53,6 +67,33 @@
|
||||
if(assembly)
|
||||
UnregisterSignal(assembly, COMSIG_ASSEMBLY_PULSED)
|
||||
UnregisterSignal(parent, COMSIG_TURF_CHANGE)
|
||||
UnregisterSignal(parent, COMSIG_PARENT_EXAMINE)
|
||||
UnregisterSignal(parent, COMSIG_ATOM_TOOL_ACT(TOOL_MULTITOOL))
|
||||
|
||||
/datum/component/trapdoor/proc/try_unlink(turf/source, mob/user, obj/item/tool)
|
||||
SIGNAL_HANDLER
|
||||
if(!assembly)
|
||||
return
|
||||
if(IS_OPEN(parent))
|
||||
source.balloon_alert(user, "can't unlink trapdoor when its open")
|
||||
return
|
||||
source.balloon_alert(user, "unlinking trapdoor")
|
||||
INVOKE_ASYNC(src, .proc/async_try_unlink, source, user, tool)
|
||||
return
|
||||
|
||||
/datum/component/trapdoor/proc/async_try_unlink(turf/source, mob/user, obj/item/tool)
|
||||
if(!do_after(user, 5 SECONDS, target=source))
|
||||
return
|
||||
if(IS_OPEN(parent))
|
||||
source.balloon_alert(user, "can't unlink trapdoor when its open")
|
||||
return
|
||||
assembly.linked = FALSE
|
||||
assembly.stored_decals = list()
|
||||
UnregisterSignal(assembly, COMSIG_ASSEMBLY_PULSED)
|
||||
UnregisterSignal(parent, COMSIG_ATOM_TOOL_ACT(TOOL_MULTITOOL))
|
||||
RegisterSignal(SSdcs, COMSIG_GLOB_TRAPDOOR_LINK, .proc/on_link_requested)
|
||||
assembly = null
|
||||
source.balloon_alert(user, "trapdoor unlinked")
|
||||
|
||||
/datum/component/trapdoor/proc/decal_detached(datum/source, description, cleanable, directional, pic)
|
||||
SIGNAL_HANDLER
|
||||
@@ -76,13 +117,14 @@
|
||||
///called by linking remotes to tie an assembly to the trapdoor
|
||||
/datum/component/trapdoor/proc/on_link_requested(datum/source, obj/item/assembly/trapdoor/assembly)
|
||||
SIGNAL_HANDLER
|
||||
if(get_dist(parent, assembly) > TRAPDOOR_LINKING_SEARCH_RANGE)
|
||||
if(get_dist(parent, assembly) > TRAPDOOR_LINKING_SEARCH_RANGE || assembly.linked)
|
||||
return
|
||||
. = LINKED_UP
|
||||
src.assembly = assembly
|
||||
assembly.linked = TRUE
|
||||
UnregisterSignal(SSdcs, COMSIG_GLOB_TRAPDOOR_LINK)
|
||||
RegisterSignal(assembly, COMSIG_ASSEMBLY_PULSED, .proc/toggle_trapdoor)
|
||||
RegisterSignal(parent, COMSIG_ATOM_TOOL_ACT(TOOL_MULTITOOL), .proc/try_unlink)
|
||||
|
||||
///signal called by our assembly being pulsed
|
||||
/datum/component/trapdoor/proc/toggle_trapdoor(datum/source)
|
||||
@@ -96,14 +138,18 @@
|
||||
/datum/component/trapdoor/proc/turf_changed_pre(datum/source, path, new_baseturfs, flags, post_change_callbacks)
|
||||
SIGNAL_HANDLER
|
||||
var/turf/open/dying_trapdoor = parent
|
||||
if((!IS_OPEN(dying_trapdoor) && !IS_OPEN(path)) || path == /turf/open/floor/plating) //not a process of the trapdoor, so this trapdoor has been destroyed
|
||||
if((flags & CHANGETURF_TRAPDOOR_INDUCED) == 0) //not a process of the trapdoor
|
||||
if(!IS_OPEN(parent) && !ispath(path, /turf/closed) && !ispath(path, /turf/open/openspace)) // allow people to place tiles on plating / change tiles without breaking the trapdoor
|
||||
post_change_callbacks += CALLBACK(src, /datum/component/trapdoor.proc/carry_over_trapdoor, path, conspicuous, assembly)
|
||||
return
|
||||
// otherwise, break trapdoor
|
||||
dying_trapdoor.visible_message(span_warning("The trapdoor mechanism in [dying_trapdoor] is broken!"))
|
||||
if(assembly)
|
||||
assembly.linked = FALSE
|
||||
assembly.stored_decals.Cut()
|
||||
assembly = null
|
||||
return
|
||||
post_change_callbacks += CALLBACK(assembly, /obj/item/assembly/trapdoor.proc/carry_over_trapdoor, trapdoor_turf_path)
|
||||
post_change_callbacks += CALLBACK(src, /datum/component/trapdoor.proc/carry_over_trapdoor, trapdoor_turf_path, conspicuous, assembly)
|
||||
|
||||
/**
|
||||
* ## carry_over_trapdoor
|
||||
@@ -111,8 +157,18 @@
|
||||
* applies the trapdoor to the new turf (created by the last trapdoor)
|
||||
* apparently callbacks with arguments on invoke and the callback itself have the callback args go first. interesting!
|
||||
*/
|
||||
/obj/item/assembly/trapdoor/proc/carry_over_trapdoor(trapdoor_turf_path, turf/new_turf)
|
||||
new_turf.AddComponent(/datum/component/trapdoor, FALSE, trapdoor_turf_path, src)
|
||||
/datum/component/trapdoor/proc/carry_over_trapdoor(trapdoor_turf_path, conspicuous, assembly, turf/new_turf)
|
||||
new_turf.AddComponent(/datum/component/trapdoor, FALSE, trapdoor_turf_path, assembly, conspicuous)
|
||||
|
||||
/**
|
||||
* ## on_examine
|
||||
*
|
||||
* examine message for conspicuous trapdoors that makes it obvious
|
||||
*/
|
||||
/datum/component/trapdoor/proc/on_examine(datum/source, mob/user, list/examine_text)
|
||||
SIGNAL_HANDLER
|
||||
if(conspicuous)
|
||||
examine_text += "There seems to be a tiny gap around this tile with some wires that you might be able to pulse with a <b>multitool</b>."
|
||||
|
||||
/**
|
||||
* ## try_opening
|
||||
@@ -127,7 +183,7 @@
|
||||
RegisterSignal(parent, COMSIG_TURF_DECAL_DETACHED, .proc/decal_detached)
|
||||
playsound(trapdoor_turf, 'sound/machines/trapdoor/trapdoor_open.ogg', 50)
|
||||
trapdoor_turf.visible_message(span_warning("[trapdoor_turf] swings open!"))
|
||||
trapdoor_turf.ChangeTurf(/turf/open/openspace, flags = CHANGETURF_INHERIT_AIR)
|
||||
trapdoor_turf.ChangeTurf(/turf/open/openspace, flags = CHANGETURF_INHERIT_AIR | CHANGETURF_TRAPDOOR_INDUCED)
|
||||
|
||||
/**
|
||||
* ## try_closing
|
||||
@@ -143,7 +199,7 @@
|
||||
return
|
||||
playsound(trapdoor_turf, 'sound/machines/trapdoor/trapdoor_shut.ogg', 50)
|
||||
trapdoor_turf.visible_message(span_warning("The trapdoor mechanism in [trapdoor_turf] swings shut!"))
|
||||
trapdoor_turf.ChangeTurf(trapdoor_turf_path, flags = CHANGETURF_INHERIT_AIR)
|
||||
trapdoor_turf.ChangeTurf(trapdoor_turf_path, flags = CHANGETURF_INHERIT_AIR | CHANGETURF_TRAPDOOR_INDUCED)
|
||||
|
||||
#undef IS_OPEN
|
||||
|
||||
@@ -280,3 +336,39 @@
|
||||
/obj/item/trapdoor_remote/preloaded/Initialize(mapload)
|
||||
. = ..()
|
||||
internals = new(src)
|
||||
|
||||
/// trapdoor parts kit, allows trapdoors to be made by players
|
||||
/obj/item/trapdoor_kit
|
||||
name = "trapdoor parts kit"
|
||||
desc = "A kit containing all the parts needed to build a trapdoor. Can only be used on open space."
|
||||
icon = 'icons/obj/improvised.dmi'
|
||||
icon_state = "kitsuitcase"
|
||||
var/in_use = FALSE
|
||||
|
||||
/obj/item/trapdoor_kit/Initialize(mapload)
|
||||
. = ..()
|
||||
AddElement(/datum/element/openspace_item_click_handler)
|
||||
|
||||
/obj/item/trapdoor_kit/handle_openspace_click(turf/target, mob/user, proximity_flag, click_parameters)
|
||||
afterattack(target, user, proximity_flag, click_parameters)
|
||||
|
||||
/obj/item/trapdoor_kit/afterattack(atom/target, mob/user, proximity_flag)
|
||||
. = ..()
|
||||
if(!proximity_flag)
|
||||
return
|
||||
var/turf/target_turf = get_turf(target)
|
||||
if(!isopenspaceturf(target_turf))
|
||||
return
|
||||
in_use = TRUE
|
||||
balloon_alert(user, "constructing trapdoor")
|
||||
if(!do_after(user, 5 SECONDS, target = target))
|
||||
in_use = FALSE
|
||||
return
|
||||
in_use = FALSE
|
||||
if(!isopenspaceturf(target_turf)) // second check to make sure nothing changed during constructions
|
||||
return
|
||||
var/turf/new_turf = target_turf.PlaceOnTop(/turf/open/floor/plating, flags = CHANGETURF_INHERIT_AIR)
|
||||
new_turf.AddComponent(/datum/component/trapdoor, starts_open = FALSE, conspicuous = TRUE)
|
||||
balloon_alert(user, "trapdoor constructed")
|
||||
qdel(src)
|
||||
return
|
||||
|
||||
@@ -674,6 +674,7 @@ INITIALIZE_IMMEDIATE(/obj/effect/mapping_helpers/no_lava)
|
||||
* ## trapdoor placer!
|
||||
*
|
||||
* This places an unlinked trapdoor in the tile its on (so someone with a remote needs to link it up first)
|
||||
* Pre-mapped trapdoors (unlike player-made ones) are not conspicuous by default so nothing stands out with them
|
||||
* Admins may spawn this in the round for additional trapdoors if they so desire
|
||||
* if YOU want to learn more about trapdoors, read about the component at trapdoor.dm
|
||||
* note: this is not a turf subtype because the trapdoor needs the type of the turf to turn back into
|
||||
@@ -685,7 +686,7 @@ INITIALIZE_IMMEDIATE(/obj/effect/mapping_helpers/no_lava)
|
||||
|
||||
/obj/effect/mapping_helpers/trapdoor_placer/LateInitialize()
|
||||
var/turf/component_target = get_turf(src)
|
||||
component_target.AddComponent(/datum/component/trapdoor, starts_open = FALSE)
|
||||
component_target.AddComponent(/datum/component/trapdoor, starts_open = FALSE, conspicuous = FALSE)
|
||||
qdel(src)
|
||||
|
||||
/obj/effect/mapping_helpers/ztrait_injector
|
||||
|
||||
@@ -223,6 +223,15 @@
|
||||
category = list(RND_CATEGORY_INITIAL, RND_CATEGORY_ELECTRONICS)
|
||||
departmental_flags = DEPARTMENT_BITFLAG_ENGINEERING
|
||||
|
||||
/datum/design/trapdoor_electronics
|
||||
name = "Trapdoor Controller Electronics"
|
||||
id = "trapdoor_electronics"
|
||||
build_type = AUTOLATHE | PROTOLATHE | AWAY_LATHE
|
||||
materials = list(/datum/material/iron = 50, /datum/material/glass = 50)
|
||||
build_path = /obj/item/assembly/trapdoor
|
||||
category = list("initial", "Electronics")
|
||||
departmental_flags = DEPARTMENT_BITFLAG_ENGINEERING
|
||||
|
||||
/datum/design/camera
|
||||
name = "Camera"
|
||||
id = "camera"
|
||||
|
||||
@@ -62,6 +62,7 @@
|
||||
"titaniumglass",
|
||||
"toner",
|
||||
"toner_large",
|
||||
"trapdoor_electronics",
|
||||
"turbine_part_compressor",
|
||||
"turbine_part_rotor",
|
||||
"turbine_part_stator",
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 6.0 KiB After Width: | Height: | Size: 6.0 KiB |
Reference in New Issue
Block a user