mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-06-21 22:24:09 +01:00
e0827de4b5
## About The Pull Request This PR adds a change to a pretty prevalent feature that's been around since #66588 (April 28th, 2022). Although it has been controversial to some extent, I believe that it was a good change in principle for reasons I will later get into. For now, this is what the PR does: * All _station_ unrestricted door helpers (e.g. those in maintenance) have been replaced with a subtype that adds a random 2-3 second delay to opening the door, using a new "unrestricted latch" feature. **This does not occur if the user has regular access to that door.** * The unrestricted side will initiate a do_after and plays a distinct small hissing sound (because I presume you're disengaging some hydraulic lever on that side), after which the door will open as players have come to expect. * While you're engaging the lever, you will be resistant to pressure movements as you are presumably holding onto the lever or something. All other movements (e.g. voluntary, being shoved, etc.) will continue to function as expected. * We will statistically tabulate each time someone attempts to use the unrestricted "lever", and every time one successfully occurs. This is just for analysis to see player trends as we have lacked this over the last 3.5 years. Here's a link to the sound I added: https://freesound.org/people/Usernameis1337/sounds/632755, the version in this PR was converted using OGG Vorbis. https://github.com/user-attachments/assets/4167bda4-63b5-4dc0-a7b2-694a9e3d3201 ## Why It's Good For The Game Back in 2022, I was one of the major proponents for adding such a change to the game. This is for a few reasons: * It doesn't really make human sense for a station to have hallways/spaces that you can enter and then just get completely trapped in. The station is a deathtrap because of _who_ is on it, not because it _is_ a death trap. I have always maintained that we should assume that the station is competently made to give the hijinx a much more jarring background. To me, maintenance isn't old sections of a station (although it can have those elements), but vital side pathways in the event of emergencies, like having extra fire stairs in a building. The doors to those fire stairs are always unlocked because they need to ensure that people are able to efflux to save themselves from danger rather than die. * It was easily subvertable anyways. You can easily ask the HoP for maintenance access or AI to let you out of maintenance (although the latter was a bit harder to articulate). I don't find myself agreeing with this as much nowadays but I remember the frustration I felt waiting for minutes for someone to open the door had something occurred for me to have found myself in maintenance. It's simply not fun and doesn't make sense for a station to have this. * I thought that it added a unique element to antagonism. You can't drag someone in maintenance and then have the whole entire subsection of the station be your den. It's important for you to secure your base should you be dragging people in there instead of just always being able to win via dragging. * People tend to forget this point, but it actually did cause a lot _more_ deaths in situations where threats originate outside the station/in maintenance. It was much easier for the killy-stabby mass murderers to ingress into main hallways and get to killing faster. This is why the change felt "equal" in a way. ### Why not remove it outright? I believe that a lot of balance changes over the last 3.5 years (30000 issues ago!) have been weighting for these interactions, and I think removing it all cold-turkey like will cause a huge upturn in deadliness and just not be what players are looking for in the new game loop. To me, this was a vital step in getting more towards 90-minute rounds, and I think we would see a drop in that. I also have those above three reasons that I am still a firm believer in, but I am still interested in seeing what a different system might entail and how that could play out. I added stat gathering so after we get 4-6 weeks of data, we can determine to keep or shelve this feature. I will probably always be on the "blocking" side of removing it outright unless there's some severe data that can convince me (which will probably need it's own test-merged PR, while this is meant to be added into the game right now). ### Why are we changing it? I think not enough people are dying. I played a few rounds yesterday and while a decent chunk of people were dying, I saw a few follies in my original line of thought. Maintenance should be a bit creepier and not auxiliary hallways (in normal circumstances), I already thought we did a really good job of that but I noticed that it wasn't as good as memory served me. I think maintenance should have a little bit more difficulty to navigate (i.e. if you're being chased down by someone and it's taking 2.5 seconds to open, that would be an excellent heart-pounding tension moment) and would overall be more interesting than the status quo. It is a bit sillier to me but some IRL buildings do have to have you hold down the push bar for a few seconds until it disengages, so this is agreeable. I also don't think the unidirectional exit design flow standards are where they were due to drift in application, so this is also a better way to uniformly apply it. ## Changelog 🆑 balance: After noticing it was too easy for animals to crawl through maintenance by abusing the Easy-Exit sensors, Nanotrasen has replaced all unrestricted door sensors (like in maintenance) with a pull-down lever that should take around 2-3 seconds to engage. It has been designed to allow the employee to actuate it despite any pressure differentials within an area. balance: The above change does not apply to select doors in the medical section of the station, which will continue to use the "older" Ready-Exit system. sound: In order to ensure that staff in high-traffic areas don't go bonkers due to this new change, sound dampeners have been installed to prevent the hydraulics from being heard for super long distances. However, they skimped out on the quality for the ones in maintenance... /🆑 FYI Mappers/Tweakers: This PR replaces all station map unres mapping helpers with the new subtype. You are welcome to replace certain doors with the old helper (the base type) to get the old behavior as you see fit, just explain why that behavior is desired in that location. Otherwise, it would be appreciated if we have this new behavior >95% of the time.
1537 lines
55 KiB
Plaintext
1537 lines
55 KiB
Plaintext
//Landmarks and other helpers which speed up the mapping process and reduce the number of unique instances/subtypes of items/turf/ect
|
|
|
|
|
|
|
|
/obj/effect/baseturf_helper //Set the baseturfs of every turf in the /area/ it is placed.
|
|
name = "baseturf editor"
|
|
icon = 'icons/effects/mapping_helpers.dmi'
|
|
icon_state = ""
|
|
/// Replacing a specific turf
|
|
var/list/baseturf_to_replace
|
|
/// The desired bottom turf
|
|
var/baseturf
|
|
|
|
plane = POINT_PLANE
|
|
|
|
/obj/effect/baseturf_helper/Initialize(mapload)
|
|
. = ..()
|
|
return INITIALIZE_HINT_LATELOAD
|
|
|
|
/obj/effect/baseturf_helper/LateInitialize()
|
|
if(!baseturf_to_replace)
|
|
baseturf_to_replace = typecacheof(list(/turf/open/space,/turf/baseturf_bottom))
|
|
else if(!length(baseturf_to_replace))
|
|
baseturf_to_replace = list(baseturf_to_replace = TRUE)
|
|
else if(baseturf_to_replace[baseturf_to_replace[1]] != TRUE) // It's not associative
|
|
var/list/formatted = list()
|
|
for(var/i in baseturf_to_replace)
|
|
formatted[i] = TRUE
|
|
baseturf_to_replace = formatted
|
|
|
|
var/area/our_area = get_area(src)
|
|
for(var/i in get_area_turfs(our_area, z))
|
|
replace_baseturf(i)
|
|
|
|
qdel(src)
|
|
|
|
/// Replaces all the requested baseturfs (usually space/baseturfbottom) with the desired baseturf. Skips if its already there
|
|
/obj/effect/baseturf_helper/proc/replace_baseturf(turf/thing)
|
|
thing.remove_baseturfs_from_typecache(baseturf_to_replace)
|
|
|
|
if(length(thing.baseturfs))
|
|
var/turf/tile = thing.baseturfs[1]
|
|
if(tile == baseturf)
|
|
return
|
|
|
|
thing.place_on_bottom(baseturf)
|
|
|
|
/obj/effect/baseturf_helper/space
|
|
name = "space baseturf editor"
|
|
baseturf = /turf/open/space
|
|
|
|
/obj/effect/baseturf_helper/asteroid
|
|
name = "asteroid baseturf editor"
|
|
baseturf = /turf/open/misc/asteroid
|
|
|
|
/obj/effect/baseturf_helper/asteroid/airless
|
|
name = "asteroid airless baseturf editor"
|
|
baseturf = /turf/open/misc/asteroid/airless
|
|
|
|
/obj/effect/baseturf_helper/asteroid/basalt
|
|
name = "asteroid basalt baseturf editor"
|
|
baseturf = /turf/open/misc/asteroid/basalt
|
|
|
|
/obj/effect/baseturf_helper/asteroid/snow
|
|
name = "asteroid snow baseturf editor"
|
|
baseturf = /turf/open/misc/asteroid/snow
|
|
|
|
/obj/effect/baseturf_helper/asteroid/moon
|
|
name = "lunar sand baseturf editor"
|
|
baseturf = /turf/open/misc/asteroid/moon
|
|
|
|
/obj/effect/baseturf_helper/beach/sand
|
|
name = "beach sand baseturf editor"
|
|
baseturf = /turf/open/misc/beach/sand
|
|
|
|
/obj/effect/baseturf_helper/beach/water
|
|
name = "water baseturf editor"
|
|
baseturf = /turf/open/water/beach
|
|
|
|
/obj/effect/baseturf_helper/lava
|
|
name = "lava baseturf editor"
|
|
baseturf = /turf/open/lava/smooth
|
|
|
|
/obj/effect/baseturf_helper/lava_land/surface
|
|
name = "lavaland baseturf editor"
|
|
baseturf = /turf/open/lava/smooth/lava_land_surface
|
|
|
|
/obj/effect/baseturf_helper/reinforced_plating
|
|
name = "reinforced plating baseturf editor"
|
|
baseturf = /turf/open/floor/plating/reinforced
|
|
baseturf_to_replace = list(/turf/open/floor/plating)
|
|
|
|
/obj/effect/baseturf_helper/reinforced_plating/replace_baseturf(turf/thing)
|
|
if(istype(thing, /turf/open/floor/plating))
|
|
return //Plates should not be placed under other plates
|
|
thing.stack_ontop_of_baseturf(/turf/open/floor/plating, baseturf)
|
|
|
|
//This applies the reinforced plating to the above Z level for every tile in the area where this is placed
|
|
/obj/effect/baseturf_helper/reinforced_plating/ceiling
|
|
name = "reinforced ceiling plating baseturf editor"
|
|
|
|
/obj/effect/baseturf_helper/reinforced_plating/ceiling/replace_baseturf(turf/thing)
|
|
var/turf/ceiling = get_step_multiz(thing, UP)
|
|
if(isnull(ceiling))
|
|
CRASH("baseturf helper is attempting to modify the Z level above but there is no Z level above it.")
|
|
if(isspaceturf(ceiling) || istype(ceiling, /turf/open/openspace))
|
|
return
|
|
return ..(ceiling)
|
|
|
|
///Used for marking mapping errors. These should only be created by cases explicitly caught by unit tests, and should NEVER actually appear in production.
|
|
/obj/effect/mapping_error
|
|
name = "I AM ERROR"
|
|
desc = "IF YOU SEE ME, YELL AT A MAPPER!!!"
|
|
icon = 'icons/effects/mapping_helpers.dmi'
|
|
icon_state = "mapping_error"
|
|
|
|
/obj/effect/mapping_helpers
|
|
icon = 'icons/effects/mapping_helpers.dmi'
|
|
icon_state = ""
|
|
anchored = TRUE
|
|
// Unless otherwise specified, layer above everything
|
|
layer = ABOVE_ALL_MOB_LAYER
|
|
var/late = FALSE
|
|
|
|
/obj/effect/mapping_helpers/Initialize(mapload)
|
|
..()
|
|
return late ? INITIALIZE_HINT_LATELOAD : INITIALIZE_HINT_QDEL
|
|
|
|
//airlock helpers
|
|
/obj/effect/mapping_helpers/airlock
|
|
layer = DOOR_HELPER_LAYER
|
|
late = TRUE
|
|
/// If TRUE we will apply to every windoor in the loc if we can't find an airlock.
|
|
var/apply_to_windoors = FALSE
|
|
|
|
/obj/effect/mapping_helpers/airlock/Initialize(mapload)
|
|
. = ..()
|
|
if(!mapload)
|
|
log_mapping("[src] spawned outside of mapload!")
|
|
return
|
|
|
|
var/obj/machinery/door/airlock/airlock = locate(/obj/machinery/door/airlock) in loc
|
|
if(!airlock)
|
|
if(apply_to_windoors)
|
|
var/any_found = FALSE
|
|
for(var/obj/machinery/door/window/windoor in loc)
|
|
payload(windoor)
|
|
any_found = TRUE
|
|
if(!any_found)
|
|
log_mapping("[src] failed to find an airlock at [AREACOORD(src)], AND no windoors were found.")
|
|
return
|
|
|
|
log_mapping("[src] failed to find an airlock at [AREACOORD(src)]")
|
|
return
|
|
|
|
payload(airlock)
|
|
|
|
/obj/effect/mapping_helpers/airlock/LateInitialize()
|
|
var/obj/machinery/door/airlock/airlock = locate(/obj/machinery/door/airlock) in loc
|
|
if(!airlock)
|
|
qdel(src)
|
|
return
|
|
if(airlock.cyclelinkeddir)
|
|
airlock.cyclelinkairlock()
|
|
if(airlock.closeOtherId)
|
|
airlock.update_other_id()
|
|
if(airlock.abandoned)
|
|
var/outcome = rand(1,100)
|
|
switch(outcome)
|
|
if(1 to 9)
|
|
var/turf/here = get_turf(src)
|
|
for(var/turf/closed/T in range(2, src))
|
|
here.place_on_top(T.type)
|
|
qdel(airlock)
|
|
qdel(src)
|
|
return
|
|
here.place_on_top(/turf/closed/wall)
|
|
qdel(airlock)
|
|
qdel(src)
|
|
return
|
|
if(9 to 11)
|
|
airlock.feedback = FALSE
|
|
// These do not use airlock.bolt() because we want to pretend it was always locked. That means no sound effects.
|
|
airlock.locked = TRUE
|
|
if(12 to 15)
|
|
airlock.locked = TRUE
|
|
if(16 to 23)
|
|
airlock.welded = TRUE
|
|
if(24 to 30)
|
|
airlock.set_panel_open(TRUE)
|
|
if(airlock.cutAiWire)
|
|
airlock.wires.cut(WIRE_AI)
|
|
if(airlock.autoname)
|
|
airlock.name = get_area_name(src, TRUE)
|
|
airlock.update_appearance()
|
|
qdel(src)
|
|
|
|
/obj/effect/mapping_helpers/airlock/proc/payload(obj/machinery/door/airlock/payload)
|
|
return
|
|
|
|
/obj/effect/mapping_helpers/airlock/cyclelink_helper
|
|
name = "airlock cyclelink helper"
|
|
icon_state = "airlock_cyclelink_helper"
|
|
|
|
/obj/effect/mapping_helpers/airlock/cyclelink_helper/payload(obj/machinery/door/airlock/airlock)
|
|
if(airlock.cyclelinkeddir)
|
|
log_mapping("[src] at [AREACOORD(src)] tried to set [airlock] cyclelinkeddir, but it's already set!")
|
|
else
|
|
airlock.cyclelinkeddir = dir
|
|
|
|
/obj/effect/mapping_helpers/airlock/cyclelink_helper_multi
|
|
name = "airlock multi-cyclelink helper"
|
|
icon_state = "airlock_multicyclelink_helper"
|
|
var/cycle_id
|
|
|
|
/obj/effect/mapping_helpers/airlock/cyclelink_helper_multi/payload(obj/machinery/door/airlock/airlock)
|
|
if(airlock.closeOtherId)
|
|
log_mapping("[src] at [AREACOORD(src)] tried to set [airlock] closeOtherId, but it's already set!")
|
|
else if(!cycle_id)
|
|
log_mapping("[src] at [AREACOORD(src)] doesn't have a cycle_id to assign to [airlock]!")
|
|
else
|
|
airlock.closeOtherId = cycle_id
|
|
|
|
/obj/effect/mapping_helpers/airlock/locked
|
|
name = "airlock lock helper"
|
|
icon_state = "airlock_locked_helper"
|
|
|
|
/obj/effect/mapping_helpers/airlock/locked/payload(obj/machinery/door/airlock/airlock)
|
|
if(airlock.locked)
|
|
log_mapping("[src] at [AREACOORD(src)] tried to bolt [airlock] but it's already locked!")
|
|
else
|
|
// Used instead of bolt so that we can pretend it was always locked, i.e. no sound effects on init.
|
|
airlock.locked = TRUE
|
|
|
|
/obj/effect/mapping_helpers/airlock/unres
|
|
name = "airlock unrestricted side helper"
|
|
icon_state = "airlock_unres_helper"
|
|
|
|
/obj/effect/mapping_helpers/airlock/unres/payload(obj/machinery/door/airlock/airlock)
|
|
airlock.unres_sides ^= dir
|
|
airlock.unres_latch = TRUE
|
|
|
|
/obj/effect/mapping_helpers/airlock/unres/delayed
|
|
name = "airlock unrestricted side delayed helper"
|
|
icon_state = "airlock_unres_delayed_helper"
|
|
|
|
/obj/effect/mapping_helpers/airlock/unres/delayed/payload(obj/machinery/door/airlock/airlock)
|
|
. = ..()
|
|
airlock.delayed_unres_open = TRUE
|
|
|
|
/obj/effect/mapping_helpers/airlock/abandoned
|
|
name = "airlock abandoned helper"
|
|
icon_state = "airlock_abandoned"
|
|
|
|
/obj/effect/mapping_helpers/airlock/abandoned/payload(obj/machinery/door/airlock/airlock)
|
|
if(airlock.abandoned)
|
|
log_mapping("[src] at [AREACOORD(src)] tried to make [airlock] abandoned but it's already abandoned!")
|
|
else
|
|
airlock.abandoned = TRUE
|
|
|
|
/obj/effect/mapping_helpers/airlock/welded
|
|
name = "airlock welded helper"
|
|
icon_state = "airlock_welded"
|
|
|
|
/obj/effect/mapping_helpers/airlock/welded/payload(obj/machinery/door/airlock/airlock)
|
|
if(airlock.welded)
|
|
log_mapping("[src] at [AREACOORD(src)] tried to make [airlock] welded but it's already welded closed!")
|
|
airlock.welded = TRUE
|
|
|
|
/obj/effect/mapping_helpers/airlock/cutaiwire
|
|
name = "airlock cut ai wire helper"
|
|
icon_state = "airlock_cutaiwire"
|
|
|
|
/obj/effect/mapping_helpers/airlock/cutaiwire/payload(obj/machinery/door/airlock/airlock)
|
|
if(airlock.cutAiWire)
|
|
log_mapping("[src] at [AREACOORD(src)] tried to cut the ai wire on [airlock] but it's already cut!")
|
|
else
|
|
airlock.cutAiWire = TRUE
|
|
|
|
/obj/effect/mapping_helpers/airlock/autoname
|
|
name = "airlock autoname helper"
|
|
icon_state = "airlock_autoname"
|
|
|
|
/obj/effect/mapping_helpers/airlock/autoname/payload(obj/machinery/door/airlock/airlock)
|
|
if(airlock.autoname)
|
|
log_mapping("[src] at [AREACOORD(src)] tried to autoname the [airlock] but it's already autonamed!")
|
|
else
|
|
airlock.autoname = TRUE
|
|
|
|
/obj/effect/mapping_helpers/airlock/inaccessible
|
|
name = "airlock inaccessible helper"
|
|
icon_state = "airlock_inaccessible"
|
|
|
|
/obj/effect/mapping_helpers/airlock/inaccessible/payload(obj/machinery/door/airlock/airlock)
|
|
if(airlock.req_one_access != null)
|
|
log_mapping("[src] at [AREACOORD(src)] tried to set req_access, but req__one_access was already set!")
|
|
else
|
|
airlock.req_access += list(ACCESS_INACCESSIBLE)
|
|
|
|
/obj/effect/mapping_helpers/airlock/red_alert_access
|
|
name = "airlock red alert access helper"
|
|
icon_state = "airlock_red_alert_access"
|
|
apply_to_windoors = TRUE
|
|
|
|
/obj/effect/mapping_helpers/airlock/red_alert_access/payload(obj/machinery/door/airlock)
|
|
airlock.red_alert_access = TRUE
|
|
|
|
//air alarm helpers
|
|
/obj/effect/mapping_helpers/airalarm
|
|
desc = "You shouldn't see this. Report it please."
|
|
late = TRUE
|
|
|
|
/obj/effect/mapping_helpers/airalarm/Initialize(mapload)
|
|
. = ..()
|
|
if(!mapload)
|
|
log_mapping("[src] spawned outside of mapload!")
|
|
return INITIALIZE_HINT_QDEL
|
|
|
|
var/obj/machinery/airalarm/target = locate(/obj/machinery/airalarm) in loc
|
|
if(isnull(target))
|
|
var/area/target_area = get_area(src)
|
|
log_mapping("[src] failed to find an air alarm at [AREACOORD(src)] ([target_area.type]).")
|
|
else
|
|
payload(target)
|
|
|
|
return INITIALIZE_HINT_LATELOAD
|
|
|
|
/obj/effect/mapping_helpers/airalarm/LateInitialize()
|
|
var/obj/machinery/airalarm/target = locate(/obj/machinery/airalarm) in loc
|
|
|
|
if(isnull(target))
|
|
qdel(src)
|
|
return
|
|
if(target.unlocked)
|
|
target.unlock()
|
|
|
|
if(target.tlv_cold_room)
|
|
target.set_tlv_cold_room()
|
|
if(target.tlv_kitchen)
|
|
target.set_tlv_kitchen()
|
|
if(target.tlv_no_checks)
|
|
target.set_tlv_no_checks()
|
|
if(target.tlv_no_checks + target.tlv_cold_room + target.tlv_kitchen > 1)
|
|
CRASH("Tried to apply incompatible air alarm threshold helpers!")
|
|
|
|
if(target.syndicate_access)
|
|
target.give_syndicate_access()
|
|
if(target.away_general_access)
|
|
target.give_away_general_access()
|
|
if(target.engine_access)
|
|
target.give_engine_access()
|
|
if(target.mixingchamber_access)
|
|
target.give_mixingchamber_access()
|
|
if(target.all_access)
|
|
target.give_all_access()
|
|
if(target.syndicate_access + target.away_general_access + target.engine_access + target.mixingchamber_access + target.all_access > 1)
|
|
CRASH("Tried to combine incompatible air alarm access helpers!")
|
|
|
|
target.update_appearance()
|
|
qdel(src)
|
|
|
|
/obj/effect/mapping_helpers/airalarm/proc/payload(obj/machinery/airalarm/target)
|
|
return
|
|
|
|
/obj/effect/mapping_helpers/airalarm/unlocked
|
|
name = "airalarm unlocked interface helper"
|
|
icon_state = "airalarm_unlocked_interface_helper"
|
|
|
|
/obj/effect/mapping_helpers/airalarm/unlocked/payload(obj/machinery/airalarm/target)
|
|
if(target.unlocked)
|
|
var/area/area = get_area(target)
|
|
log_mapping("[src] at [AREACOORD(src)] [(area.type)] tried to unlock the [target] but it's already unlocked!")
|
|
target.unlocked = TRUE
|
|
|
|
/obj/effect/mapping_helpers/airalarm/syndicate_access
|
|
name = "airalarm syndicate access helper"
|
|
icon_state = "airalarm_syndicate_access_helper"
|
|
|
|
/obj/effect/mapping_helpers/airalarm/syndicate_access/payload(obj/machinery/airalarm/target)
|
|
if(target.syndicate_access)
|
|
var/area/area = get_area(target)
|
|
log_mapping("[src] at [AREACOORD(src)] [(area.type)] tried to adjust [target]'s access to syndicate but it's already changed!")
|
|
target.syndicate_access = TRUE
|
|
|
|
/obj/effect/mapping_helpers/airalarm/away_general_access
|
|
name = "airalarm away access helper"
|
|
icon_state = "airalarm_away_general_access_helper"
|
|
|
|
/obj/effect/mapping_helpers/airalarm/away_general_access/payload(obj/machinery/airalarm/target)
|
|
if(target.away_general_access)
|
|
var/area/area = get_area(target)
|
|
log_mapping("[src] at [AREACOORD(src)] [(area.type)] tried to adjust [target]'s access to away_general but it's already changed!")
|
|
target.away_general_access = TRUE
|
|
|
|
/obj/effect/mapping_helpers/airalarm/engine_access
|
|
name = "airalarm engine access helper"
|
|
icon_state = "airalarm_engine_access_helper"
|
|
|
|
/obj/effect/mapping_helpers/airalarm/engine_access/payload(obj/machinery/airalarm/target)
|
|
if(target.engine_access)
|
|
var/area/area = get_area(target)
|
|
log_mapping("[src] at [AREACOORD(src)] [(area.type)] tried to adjust [target]'s access to engine_access but it's already changed!")
|
|
target.engine_access = TRUE
|
|
|
|
/obj/effect/mapping_helpers/airalarm/mixingchamber_access
|
|
name = "airalarm mixingchamber access helper"
|
|
icon_state = "airalarm_mixingchamber_access_helper"
|
|
|
|
/obj/effect/mapping_helpers/airalarm/mixingchamber_access/payload(obj/machinery/airalarm/target)
|
|
if(target.mixingchamber_access)
|
|
var/area/area = get_area(target)
|
|
log_mapping("[src] at [AREACOORD(src)] [(area.type)] tried to adjust [target]'s access to mixingchamber_access but it's already changed!")
|
|
target.mixingchamber_access = TRUE
|
|
|
|
/obj/effect/mapping_helpers/airalarm/all_access
|
|
name = "airalarm all access helper"
|
|
icon_state = "airalarm_all_access_helper"
|
|
|
|
/obj/effect/mapping_helpers/airalarm/all_access/payload(obj/machinery/airalarm/target)
|
|
if(target.all_access)
|
|
var/area/area = get_area(target)
|
|
log_mapping("[src] at [AREACOORD(src)] [(area.type)] tried to adjust [target]'s access to all_access but it's already changed!")
|
|
target.all_access = TRUE
|
|
|
|
/obj/effect/mapping_helpers/airalarm/tlv_cold_room
|
|
name = "airalarm cold room tlv helper"
|
|
icon_state = "airalarm_tlv_cold_room_helper"
|
|
|
|
/obj/effect/mapping_helpers/airalarm/tlv_cold_room/payload(obj/machinery/airalarm/target)
|
|
if(target.tlv_cold_room)
|
|
var/area/area = get_area(target)
|
|
log_mapping("[src] at [AREACOORD(src)] [(area.type)] tried to adjust [target]'s tlv to cold_room but it's already changed!")
|
|
target.tlv_cold_room = TRUE
|
|
|
|
/obj/effect/mapping_helpers/airalarm/tlv_kitchen
|
|
name = "airalarm kitchen tlv helper"
|
|
icon_state = "airalarm_tlv_kitchen_helper"
|
|
|
|
/obj/effect/mapping_helpers/airalarm/tlv_kitchen/payload(obj/machinery/airalarm/target)
|
|
if(target.tlv_kitchen)
|
|
var/area/area = get_area(target)
|
|
log_mapping("[src] at [AREACOORD(src)] [(area.type)] tried to adjust [target]'s tlv to kitchen but it's already changed!")
|
|
target.tlv_kitchen = TRUE
|
|
|
|
/obj/effect/mapping_helpers/airalarm/tlv_no_checks
|
|
name = "airalarm no checks tlv helper"
|
|
icon_state = "airalarm_tlv_no_checks_helper"
|
|
|
|
/obj/effect/mapping_helpers/airalarm/tlv_no_checks/payload(obj/machinery/airalarm/target)
|
|
if(target.tlv_no_checks)
|
|
var/area/area = get_area(target)
|
|
log_mapping("[src] at [AREACOORD(src)] [(area.type)] tried to adjust [target]'s tlv to no_checks but it's already changed!")
|
|
target.tlv_no_checks = TRUE
|
|
|
|
/obj/effect/mapping_helpers/airalarm/link
|
|
name = "airalarm link helper"
|
|
icon_state = "airalarm_link_helper"
|
|
late = TRUE
|
|
var/chamber_id = ""
|
|
var/allow_link_change = FALSE
|
|
|
|
/obj/effect/mapping_helpers/airalarm/link/Initialize(mapload)
|
|
. = ..()
|
|
if(!mapload)
|
|
log_mapping("[src] spawned outside of mapload!")
|
|
return INITIALIZE_HINT_QDEL
|
|
|
|
/obj/effect/mapping_helpers/airalarm/link/LateInitialize(mapload)
|
|
var/obj/machinery/airalarm/alarm = locate(/obj/machinery/airalarm) in loc
|
|
if(!isnull(alarm))
|
|
alarm.air_sensor_chamber_id = chamber_id
|
|
alarm.allow_link_change = allow_link_change
|
|
alarm.setup_chamber_link()
|
|
else
|
|
log_mapping("[src] failed to find air alarm at [AREACOORD(src)].")
|
|
qdel(src)
|
|
|
|
/obj/effect/mapping_helpers/airalarm/surgery
|
|
name = "airalarm surgery helper"
|
|
icon_state = "airalarm_surgery_helper"
|
|
|
|
/obj/effect/mapping_helpers/airalarm/surgery/LateInitialize()
|
|
var/obj/machinery/airalarm/target = locate() in loc
|
|
for(var/obj/machinery/atmospherics/components/unary/vent_scrubber/scrubber as anything in target?.my_area?.air_scrubbers)
|
|
scrubber.filter_types |= /datum/gas/nitrous_oxide
|
|
scrubber.set_widenet(TRUE)
|
|
return ..()
|
|
|
|
//apc helpers
|
|
/obj/effect/mapping_helpers/apc
|
|
desc = "You shouldn't see this. Report it please."
|
|
late = TRUE
|
|
|
|
/obj/effect/mapping_helpers/apc/Initialize(mapload)
|
|
. = ..()
|
|
if(!mapload)
|
|
log_mapping("[src] spawned outside of mapload!")
|
|
return INITIALIZE_HINT_QDEL
|
|
|
|
var/obj/machinery/power/apc/target = locate(/obj/machinery/power/apc) in loc
|
|
if(isnull(target))
|
|
var/area/target_area = get_area(src)
|
|
log_mapping("[src] failed to find an apc at [AREACOORD(src)] ([target_area.type]).")
|
|
else
|
|
payload(target)
|
|
|
|
return INITIALIZE_HINT_LATELOAD
|
|
|
|
/obj/effect/mapping_helpers/apc/LateInitialize()
|
|
var/obj/machinery/power/apc/target = locate(/obj/machinery/power/apc) in loc
|
|
|
|
if(isnull(target))
|
|
qdel(src)
|
|
return
|
|
if(target.cut_AI_wire)
|
|
target.wires.cut(WIRE_AI)
|
|
if(target.cell_5k)
|
|
target.install_cell_5k()
|
|
if(target.cell_10k)
|
|
target.install_cell_10k()
|
|
if(target.unlocked)
|
|
target.unlock()
|
|
if(target.syndicate_access)
|
|
target.give_syndicate_access()
|
|
if(target.away_general_access)
|
|
target.give_away_general_access()
|
|
if(target.no_charge)
|
|
target.set_no_charge()
|
|
if(target.full_charge)
|
|
target.set_full_charge()
|
|
if(target.cell_5k && target.cell_10k)
|
|
CRASH("Tried to combine non-combinable cell_5k and cell_10k APC helpers!")
|
|
if(target.syndicate_access && target.away_general_access)
|
|
CRASH("Tried to combine non-combinable syndicate_access and away_general_access APC helpers!")
|
|
if(target.no_charge && target.full_charge)
|
|
CRASH("Tried to combine non-combinable no_charge and full_charge APC helpers!")
|
|
target.update_appearance()
|
|
qdel(src)
|
|
|
|
/obj/effect/mapping_helpers/apc/proc/payload(obj/machinery/power/apc/target)
|
|
return
|
|
|
|
/obj/effect/mapping_helpers/apc/cut_AI_wire
|
|
name = "apc AI wire mended helper"
|
|
icon_state = "apc_cut_AIwire_helper"
|
|
|
|
/obj/effect/mapping_helpers/apc/cut_AI_wire/payload(obj/machinery/power/apc/target)
|
|
if(target.cut_AI_wire)
|
|
var/area/apc_area = get_area(target)
|
|
log_mapping("[src] at [AREACOORD(src)] [(apc_area.type)] tried to mend the AI wire on the [target] but it's already cut!")
|
|
target.cut_AI_wire = TRUE
|
|
|
|
/obj/effect/mapping_helpers/apc/cell_5k
|
|
name = "apc 5k cell helper"
|
|
icon_state = "apc_5k_cell_helper"
|
|
|
|
/obj/effect/mapping_helpers/apc/cell_5k/payload(obj/machinery/power/apc/target)
|
|
if(target.cell_5k)
|
|
var/area/apc_area = get_area(target)
|
|
log_mapping("[src] at [AREACOORD(src)] [(apc_area.type)] tried to change [target]'s cell to cell_5k but it's already changed!")
|
|
target.cell_5k = TRUE
|
|
|
|
/obj/effect/mapping_helpers/apc/cell_10k
|
|
name = "apc 10k cell helper"
|
|
icon_state = "apc_10k_cell_helper"
|
|
|
|
/obj/effect/mapping_helpers/apc/cell_10k/payload(obj/machinery/power/apc/target)
|
|
if(target.cell_10k)
|
|
var/area/apc_area = get_area(target)
|
|
log_mapping("[src] at [AREACOORD(src)] [(apc_area.type)] tried to change [target]'s cell to cell_10k but it's already changed!")
|
|
target.cell_10k = TRUE
|
|
|
|
/obj/effect/mapping_helpers/apc/syndicate_access
|
|
name = "apc syndicate access helper"
|
|
icon_state = "apc_syndicate_access_helper"
|
|
|
|
/obj/effect/mapping_helpers/apc/syndicate_access/payload(obj/machinery/power/apc/target)
|
|
if(target.syndicate_access)
|
|
var/area/apc_area = get_area(target)
|
|
log_mapping("[src] at [AREACOORD(src)] [(apc_area.type)] tried to adjust [target]'s access to syndicate but it's already changed!")
|
|
target.syndicate_access = TRUE
|
|
|
|
/obj/effect/mapping_helpers/apc/away_general_access
|
|
name = "apc away access helper"
|
|
icon_state = "apc_away_general_access_helper"
|
|
|
|
/obj/effect/mapping_helpers/apc/away_general_access/payload(obj/machinery/power/apc/target)
|
|
if(target.away_general_access)
|
|
var/area/apc_area = get_area(target)
|
|
log_mapping("[src] at [AREACOORD(src)] [(apc_area.type)] tried to adjust [target]'s access to away_general but it's already changed!")
|
|
target.away_general_access = TRUE
|
|
|
|
/obj/effect/mapping_helpers/apc/unlocked
|
|
name = "apc unlocked interface helper"
|
|
icon_state = "apc_unlocked_interface_helper"
|
|
|
|
/obj/effect/mapping_helpers/apc/unlocked/payload(obj/machinery/power/apc/target)
|
|
if(target.unlocked)
|
|
var/area/apc_area = get_area(target)
|
|
log_mapping("[src] at [AREACOORD(src)] [(apc_area.type)] tried to unlock the [target] but it's already unlocked!")
|
|
target.unlocked = TRUE
|
|
|
|
/obj/effect/mapping_helpers/apc/no_charge
|
|
name = "apc no charge helper"
|
|
icon_state = "apc_no_charge_helper"
|
|
|
|
/obj/effect/mapping_helpers/apc/no_charge/payload(obj/machinery/power/apc/target)
|
|
if(target.no_charge)
|
|
var/area/apc_area = get_area(target)
|
|
log_mapping("[src] at [AREACOORD(src)] [(apc_area.type)] tried to set [target]'s charge to 0 but it's already at 0!")
|
|
target.no_charge = TRUE
|
|
|
|
/obj/effect/mapping_helpers/apc/full_charge
|
|
name = "apc full charge helper"
|
|
icon_state = "apc_full_charge_helper"
|
|
|
|
/obj/effect/mapping_helpers/apc/full_charge/payload(obj/machinery/power/apc/target)
|
|
if(target.full_charge)
|
|
var/area/apc_area = get_area(target)
|
|
log_mapping("[src] at [AREACOORD(src)] [(apc_area.type)] tried to set [target]'s charge to 100 but it's already at 100!")
|
|
target.full_charge = TRUE
|
|
|
|
//Used to turn off lights with lightswitch in areas.
|
|
/obj/effect/mapping_helpers/turn_off_lights_with_lightswitch
|
|
name = "area turned off lights helper"
|
|
icon_state = "lights_off"
|
|
|
|
/obj/effect/mapping_helpers/turn_off_lights_with_lightswitch/Initialize(mapload)
|
|
. = ..()
|
|
if(!mapload)
|
|
log_mapping("[src] spawned outside of mapload!")
|
|
return INITIALIZE_HINT_QDEL
|
|
return INITIALIZE_HINT_LATELOAD
|
|
|
|
/obj/effect/mapping_helpers/turn_off_lights_with_lightswitch/LateInitialize()
|
|
var/area/needed_area = get_area(src)
|
|
if(!needed_area.lightswitch)
|
|
stack_trace("[src] at [AREACOORD(src)] [(needed_area.type)] tried to turn lights off but they are already off!")
|
|
var/obj/machinery/light_switch/light_switch = locate(/obj/machinery/light_switch) in needed_area
|
|
if(!light_switch)
|
|
CRASH("Trying to turn off lights with lightswitch in area without lightswitches. In [(needed_area.type)] to be precise.")
|
|
light_switch.set_lights(FALSE)
|
|
qdel(src)
|
|
|
|
//needs to do its thing before spawn_rivers() is called
|
|
INITIALIZE_IMMEDIATE(/obj/effect/mapping_helpers/no_lava)
|
|
|
|
/obj/effect/mapping_helpers/no_lava
|
|
icon_state = "no_lava"
|
|
|
|
/obj/effect/mapping_helpers/no_lava/Initialize(mapload)
|
|
. = ..()
|
|
var/turf/T = get_turf(src)
|
|
T.turf_flags |= NO_LAVA_GEN
|
|
|
|
INITIALIZE_IMMEDIATE(/obj/effect/mapping_helpers/no_atoms_ontop)
|
|
/obj/effect/mapping_helpers/no_atoms_ontop
|
|
icon_state = "no_atoms_ontop"
|
|
|
|
/obj/effect/mapping_helpers/no_atoms_ontop/Initialize(mapload)
|
|
. = ..()
|
|
var/turf/loc_turf = get_turf(src)
|
|
loc_turf.turf_flags |= TURF_BLOCKS_POPULATE_TERRAIN_FLORAFEATURES
|
|
|
|
///Helpers used for injecting stuff into atoms on the map.
|
|
/obj/effect/mapping_helpers/atom_injector
|
|
name = "Atom Injector"
|
|
icon_state = "injector"
|
|
late = TRUE
|
|
///Will inject into all fitting the criteria if false, otherwise first found.
|
|
var/first_match_only = TRUE
|
|
///Will inject into atoms of this type.
|
|
var/target_type
|
|
///Will inject into atoms with this name.
|
|
var/target_name
|
|
|
|
//Late init so everything is likely ready and loaded (no warranty)
|
|
/obj/effect/mapping_helpers/atom_injector/LateInitialize()
|
|
if(!check_validity())
|
|
return
|
|
var/turf/target_turf = get_turf(src)
|
|
var/matches_found = 0
|
|
for(var/atom/atom_on_turf as anything in target_turf.get_all_contents())
|
|
if(atom_on_turf == src)
|
|
continue
|
|
if(target_name && atom_on_turf.name != target_name)
|
|
continue
|
|
if(target_type && !istype(atom_on_turf, target_type))
|
|
continue
|
|
inject(atom_on_turf)
|
|
matches_found++
|
|
if(first_match_only)
|
|
qdel(src)
|
|
return
|
|
if(!matches_found)
|
|
stack_trace(generate_stack_trace())
|
|
qdel(src)
|
|
|
|
///Checks if whatever we are trying to inject with is valid
|
|
/obj/effect/mapping_helpers/atom_injector/proc/check_validity()
|
|
return TRUE
|
|
|
|
///Injects our stuff into the atom
|
|
/obj/effect/mapping_helpers/atom_injector/proc/inject(atom/target)
|
|
return
|
|
|
|
///Generates text for our stack trace
|
|
/obj/effect/mapping_helpers/atom_injector/proc/generate_stack_trace()
|
|
. = "[name] found no targets at ([x], [y], [z]). First Match Only: [first_match_only ? "true" : "false"] target type: [target_type] | target name: [target_name]"
|
|
|
|
/obj/effect/mapping_helpers/atom_injector/obj_flag
|
|
name = "Obj Flag Injector"
|
|
icon_state = "objflag_helper"
|
|
var/inject_flags = NONE
|
|
|
|
/obj/effect/mapping_helpers/atom_injector/obj_flag/inject(atom/target)
|
|
if(!isobj(target))
|
|
return
|
|
var/obj/obj_target = target
|
|
obj_target.obj_flags |= inject_flags
|
|
|
|
///This helper applies components to things on the map directly.
|
|
/obj/effect/mapping_helpers/atom_injector/component_injector
|
|
name = "Component Injector"
|
|
icon_state = "component"
|
|
///Typepath of the component.
|
|
var/component_type
|
|
///Arguments for the component.
|
|
var/list/component_args = list()
|
|
|
|
/obj/effect/mapping_helpers/atom_injector/component_injector/check_validity()
|
|
if(!ispath(component_type, /datum/component))
|
|
CRASH("Wrong component type in [type] - [component_type] is not a component")
|
|
return TRUE
|
|
|
|
/obj/effect/mapping_helpers/atom_injector/component_injector/inject(atom/target)
|
|
var/arguments = list(component_type)
|
|
arguments += component_args
|
|
target._AddComponent(arguments)
|
|
|
|
/obj/effect/mapping_helpers/atom_injector/component_injector/generate_stack_trace()
|
|
. = ..()
|
|
. += " | component type: [component_type] | component arguments: [list2params(component_args)]"
|
|
|
|
///This helper applies elements to things on the map directly.
|
|
/obj/effect/mapping_helpers/atom_injector/element_injector
|
|
name = "Element Injector"
|
|
icon_state = "element"
|
|
///Typepath of the element.
|
|
var/element_type
|
|
///Arguments for the element.
|
|
var/list/element_args = list()
|
|
|
|
/obj/effect/mapping_helpers/atom_injector/element_injector/check_validity()
|
|
if(!ispath(element_type, /datum/element))
|
|
CRASH("Wrong element type in [type] - [element_type] is not a element")
|
|
return TRUE
|
|
|
|
/obj/effect/mapping_helpers/atom_injector/element_injector/inject(atom/target)
|
|
var/arguments = list(element_type)
|
|
arguments += element_args
|
|
target._AddElement(arguments)
|
|
|
|
/obj/effect/mapping_helpers/atom_injector/element_injector/generate_stack_trace()
|
|
. = ..()
|
|
. += " | element type: [element_type] | element arguments: [list2params(element_args)]"
|
|
|
|
///This helper applies traits to things on the map directly.
|
|
/obj/effect/mapping_helpers/atom_injector/trait_injector
|
|
name = "Trait Injector"
|
|
icon_state = "trait"
|
|
///Name of the trait, in the lower-case text (NOT the upper-case define) form.
|
|
var/trait_name
|
|
|
|
/obj/effect/mapping_helpers/atom_injector/trait_injector/check_validity()
|
|
if(!istext(trait_name))
|
|
CRASH("Wrong trait in [type] - [trait_name] is not a trait")
|
|
if(!GLOB.global_trait_name_map)
|
|
GLOB.global_trait_name_map = generate_global_trait_name_map()
|
|
if(!GLOB.global_trait_name_map.Find(trait_name))
|
|
stack_trace("Possibly wrong trait in [type] - [trait_name] is not a trait in the global trait list")
|
|
return TRUE
|
|
|
|
/obj/effect/mapping_helpers/atom_injector/trait_injector/inject(atom/target)
|
|
ADD_TRAIT(target, trait_name, MAPPING_HELPER_TRAIT)
|
|
|
|
/obj/effect/mapping_helpers/atom_injector/trait_injector/generate_stack_trace()
|
|
. = ..()
|
|
. += " | trait name: [trait_name]"
|
|
|
|
///This helper applies dynamic human icons to things on the map
|
|
/obj/effect/mapping_helpers/atom_injector/human_icon_injector
|
|
name = "Human Icon Injector"
|
|
icon_state = "icon"
|
|
/// Path of the outfit we give the human.
|
|
var/outfit_path
|
|
/// Path of the species we give the human.
|
|
var/species_path = /datum/species/human
|
|
/// Path of the mob spawner we base the human off of.
|
|
var/mob_spawn_path
|
|
/// Path of the right hand item we give the human.
|
|
var/r_hand = NO_REPLACE
|
|
/// Path of the left hand item we give the human.
|
|
var/l_hand = NO_REPLACE
|
|
/// Which slots on the mob should be bloody?
|
|
var/bloody_slots = NONE
|
|
/// Do we draw more than one frame for the mob?
|
|
var/animated = TRUE
|
|
|
|
/obj/effect/mapping_helpers/atom_injector/human_icon_injector/check_validity()
|
|
if(!ispath(species_path, /datum/species))
|
|
CRASH("Wrong species path in [type] - [species_path] is not a species")
|
|
if(outfit_path && !ispath(outfit_path, /datum/outfit))
|
|
CRASH("Wrong outfit path in [type] - [species_path] is not an outfit")
|
|
if(mob_spawn_path && !ispath(mob_spawn_path, /obj/effect/mob_spawn))
|
|
CRASH("Wrong mob spawn path in [type] - [mob_spawn_path] is not a mob spawner")
|
|
if(l_hand && !ispath(l_hand, /obj/item))
|
|
CRASH("Wrong left hand item path in [type] - [l_hand] is not an item")
|
|
if(r_hand && !ispath(r_hand, /obj/item))
|
|
CRASH("Wrong left hand item path in [type] - [r_hand] is not an item")
|
|
return TRUE
|
|
|
|
/obj/effect/mapping_helpers/atom_injector/human_icon_injector/inject(atom/target)
|
|
apply_dynamic_human_appearance(target, outfit_path, species_path, mob_spawn_path, r_hand, l_hand, bloody_slots, animated)
|
|
|
|
/obj/effect/mapping_helpers/atom_injector/human_icon_injector/generate_stack_trace()
|
|
. = ..()
|
|
. += " | outfit path: [outfit_path] | species path: [species_path] | mob spawner path: [mob_spawn_path] | right/left hand path: [r_hand]/[l_hand]"
|
|
|
|
///Fetches an external dmi and applies to the target object
|
|
/obj/effect/mapping_helpers/atom_injector/custom_icon
|
|
name = "Custom Icon Injector"
|
|
icon_state = "icon"
|
|
///This is the var that will be set with the fetched icon. In case you want to set some secondary icon sheets like inhands and such.
|
|
var/target_variable = "icon"
|
|
///This should return raw dmi in response to http get request. For example: "https://github.com/tgstation/SS13-sprites/raw/master/mob/medu.dmi?raw=true"
|
|
var/icon_url
|
|
///The icon file we fetched from the http get request.
|
|
var/icon_file
|
|
|
|
/obj/effect/mapping_helpers/atom_injector/custom_icon/check_validity()
|
|
var/static/icon_cache = list()
|
|
var/static/query_in_progress = FALSE //We're using a single tmp file so keep it linear.
|
|
if(query_in_progress)
|
|
UNTIL(!query_in_progress)
|
|
if(icon_cache[icon_url])
|
|
icon_file = icon_cache[icon_url]
|
|
return TRUE
|
|
log_asset("Custom Icon Helper fetching dmi from: [icon_url]")
|
|
var/datum/http_request/request = new()
|
|
var/file_name = "tmp/custom_map_icon.dmi"
|
|
request.prepare(RUSTG_HTTP_METHOD_GET, icon_url, "", "", file_name)
|
|
query_in_progress = TRUE
|
|
request.begin_async()
|
|
UNTIL(request.is_complete())
|
|
var/datum/http_response/response = request.into_response()
|
|
if(response.errored || response.status_code != 200)
|
|
query_in_progress = FALSE
|
|
CRASH("Failed to fetch mapped custom icon from url [icon_url], code: [response.status_code], error: [response.error]")
|
|
var/icon/new_icon = new(file_name)
|
|
icon_cache[icon_url] = new_icon
|
|
query_in_progress = FALSE
|
|
icon_file = new_icon
|
|
return TRUE
|
|
|
|
/obj/effect/mapping_helpers/atom_injector/custom_icon/inject(atom/target)
|
|
if(IsAdminAdvancedProcCall())
|
|
return
|
|
target.vars[target_variable] = icon_file
|
|
|
|
/obj/effect/mapping_helpers/atom_injector/custom_icon/generate_stack_trace()
|
|
. = ..()
|
|
. += " | target variable: [target_variable] | icon url: [icon_url]"
|
|
|
|
///Fetches an external sound and applies to the target object
|
|
/obj/effect/mapping_helpers/atom_injector/custom_sound
|
|
name = "Custom Sound Injector"
|
|
icon_state = "sound"
|
|
///This is the var that will be set with the fetched sound.
|
|
var/target_variable = "hitsound"
|
|
///This should return raw sound in response to http get request. For example: "https://github.com/tgstation/tgstation/blob/master/sound/misc/bang.ogg?raw=true"
|
|
var/sound_url
|
|
///The sound file we fetched from the http get request.
|
|
var/sound_file
|
|
|
|
/obj/effect/mapping_helpers/atom_injector/custom_sound/check_validity()
|
|
var/static/sound_cache = list()
|
|
var/static/query_in_progress = FALSE //We're using a single tmp file so keep it linear.
|
|
if(query_in_progress)
|
|
UNTIL(!query_in_progress)
|
|
if(sound_cache[sound_url])
|
|
sound_file = sound_cache[sound_url]
|
|
return TRUE
|
|
log_asset("Custom Sound Helper fetching sound from: [sound_url]")
|
|
var/datum/http_request/request = new()
|
|
var/file_name = "tmp/custom_map_sound.ogg"
|
|
request.prepare(RUSTG_HTTP_METHOD_GET, sound_url, "", "", file_name)
|
|
query_in_progress = TRUE
|
|
request.begin_async()
|
|
UNTIL(request.is_complete())
|
|
var/datum/http_response/response = request.into_response()
|
|
if(response.errored || response.status_code != 200)
|
|
query_in_progress = FALSE
|
|
CRASH("Failed to fetch mapped custom sound from url [sound_url], code: [response.status_code], error: [response.error]")
|
|
var/sound/new_sound = new(file_name)
|
|
sound_cache[sound_url] = new_sound
|
|
query_in_progress = FALSE
|
|
sound_file = new_sound
|
|
return TRUE
|
|
|
|
/obj/effect/mapping_helpers/atom_injector/custom_sound/inject(atom/target)
|
|
if(IsAdminAdvancedProcCall())
|
|
return
|
|
target.vars[target_variable] = sound_file
|
|
|
|
/obj/effect/mapping_helpers/atom_injector/custom_sound/generate_stack_trace()
|
|
. = ..()
|
|
. += " | target variable: [target_variable] | sound url: [sound_url]"
|
|
|
|
/obj/effect/mapping_helpers/dead_body_placer
|
|
name = "Dead Body placer"
|
|
late = TRUE
|
|
icon_state = "deadbodyplacer"
|
|
///if TRUE, was spawned out of mapload.
|
|
var/admin_spawned
|
|
///number of bodies to spawn
|
|
var/bodycount = 3
|
|
/// Corpse type we spawn thats always human
|
|
var/datum/corpse_damage_class/morgue_body_class = /datum/corpse_damage_class/station/morgue
|
|
|
|
/obj/effect/mapping_helpers/dead_body_placer/Initialize(mapload)
|
|
. = ..()
|
|
if(mapload)
|
|
return
|
|
admin_spawned = TRUE
|
|
|
|
/obj/effect/mapping_helpers/dead_body_placer/LateInitialize()
|
|
var/area/morgue_area = get_area(src)
|
|
var/list/obj/structure/bodycontainer/morgue/trays = list()
|
|
for (var/list/zlevel_turfs as anything in morgue_area.get_zlevel_turf_lists())
|
|
for(var/turf/area_turf as anything in zlevel_turfs)
|
|
var/obj/structure/bodycontainer/morgue/morgue_tray = locate() in area_turf
|
|
if(isnull(morgue_tray) || !morgue_tray.beeper || morgue_tray.connected.loc != morgue_tray)
|
|
continue
|
|
trays += morgue_tray
|
|
|
|
var/numtrays = length(trays)
|
|
if(numtrays == 0)
|
|
if(admin_spawned)
|
|
message_admins("[src] spawned at [ADMIN_VERBOSEJMP(src)] failed to find a closed morgue to spawn a body!")
|
|
else
|
|
log_mapping("[src] at [x],[y] could not find any morgues.")
|
|
return
|
|
|
|
var/reuse_trays = (numtrays < bodycount) //are we going to spawn more trays than bodies?
|
|
|
|
for (var/i in 1 to bodycount)
|
|
var/obj/structure/bodycontainer/morgue/morgue_tray = reuse_trays ? pick(trays) : pick_n_take(trays)
|
|
var/obj/structure/closet/body_bag/body_bag = new(morgue_tray.loc)
|
|
var/mob/living/carbon/human/new_human = GLOB.lost_crew_manager.create_lost_crew(revivable = FALSE, forced_class = morgue_body_class)
|
|
|
|
body_bag.insert(new_human, TRUE)
|
|
body_bag.close()
|
|
body_bag.tag_name = "[new_human.real_name][new_human.dna?.species ? " - [new_human.dna.species.name]" : " - Human"]"
|
|
body_bag.AddComponent(/datum/component/rename, "[initial(body_bag.name)][body_bag.tag_name? " - [body_bag.tag_name]" : null]", body_bag.desc)
|
|
body_bag.update_icon()
|
|
body_bag.forceMove(morgue_tray)
|
|
|
|
morgue_tray.update_appearance()
|
|
|
|
qdel(src)
|
|
|
|
//On Ian's birthday, the hop's office is decorated.
|
|
/obj/effect/mapping_helpers/ianbirthday
|
|
name = "Ian's Bday Helper"
|
|
late = TRUE
|
|
icon_state = "iansbdayhelper"
|
|
/// How many clusters of balloons to spawn.
|
|
var/balloon_clusters = 2
|
|
/// if TRUE, we give a map log warning if we can't find Ian's dogbed.
|
|
var/map_warning = TRUE
|
|
|
|
/obj/effect/mapping_helpers/ianbirthday/LateInitialize()
|
|
if(check_holidays(IAN_HOLIDAY))
|
|
birthday()
|
|
qdel(src)
|
|
|
|
/obj/effect/mapping_helpers/ianbirthday/proc/birthday()
|
|
var/area/celebration_area = get_area(src)
|
|
var/list/table_turfs = list()
|
|
var/list/open_turfs = list()
|
|
var/turf/dogbed_turf
|
|
for (var/list/zlevel_turfs as anything in celebration_area.get_zlevel_turf_lists())
|
|
for(var/turf/area_turf as anything in zlevel_turfs)
|
|
if(locate(/obj/structure/table/reinforced) in area_turf)
|
|
table_turfs += area_turf
|
|
if(locate(/obj/structure/bed/dogbed/ian) in area_turf)
|
|
dogbed_turf = area_turf
|
|
if(isopenturf(area_turf))
|
|
new /obj/effect/decal/cleanable/confetti(area_turf)
|
|
open_turfs += area_turf
|
|
|
|
if(isnull(dogbed_turf) && map_warning)
|
|
log_mapping("[src] in [celebration_area] could not find Ian's dogbed.")
|
|
|
|
else
|
|
new /obj/item/toy/balloon/corgi(dogbed_turf)
|
|
var/turf/food_turf = length(table_turfs) ? pick(table_turfs) : dogbed_turf
|
|
new /obj/item/knife/kitchen(food_turf)
|
|
var/obj/item/food/cake/birthday/iancake = new(food_turf)
|
|
iancake.desc = "Happy birthday, Ian!"
|
|
|
|
if(!length(open_turfs))
|
|
return
|
|
|
|
//some balloons! this picks an open turf and pops a few balloons in and around that turf, yay.
|
|
for(var/i in 1 to balloon_clusters)
|
|
var/turf/clusterspot = pick_n_take(open_turfs)
|
|
new /obj/item/toy/balloon(clusterspot)
|
|
var/balloons_left_to_give = 3 //the amount of balloons around the cluster
|
|
var/list/dirs_to_balloon = GLOB.cardinals.Copy()
|
|
while(balloons_left_to_give > 0)
|
|
balloons_left_to_give--
|
|
var/chosen_dir = pick_n_take(dirs_to_balloon)
|
|
var/turf/balloonstep = get_step(clusterspot, chosen_dir)
|
|
var/placed = FALSE
|
|
if(isopenturf(balloonstep))
|
|
var/obj/item/toy/balloon/B = new(balloonstep)//this clumps the cluster together
|
|
placed = TRUE
|
|
if(chosen_dir == NORTH)
|
|
B.pixel_y -= 10
|
|
if(chosen_dir == SOUTH)
|
|
B.pixel_y += 10
|
|
if(chosen_dir == EAST)
|
|
B.pixel_x -= 10
|
|
if(chosen_dir == WEST)
|
|
B.pixel_x += 10
|
|
if(!placed)
|
|
new /obj/item/toy/balloon(clusterspot)
|
|
//remind me to add wall decor!
|
|
|
|
/obj/effect/mapping_helpers/ianbirthday/admin//so admins may birthday any room
|
|
name = "generic birthday setup"
|
|
icon_state = "bdayhelper"
|
|
map_warning = FALSE
|
|
|
|
/obj/effect/mapping_helpers/ianbirthday/admin/LateInitialize()
|
|
birthday()
|
|
qdel(src)
|
|
|
|
//Ian, like most dogs, loves a good new years eve party.
|
|
/obj/effect/mapping_helpers/iannewyear
|
|
name = "Ian's New Years Helper"
|
|
late = TRUE
|
|
icon_state = "iansnewyrshelper"
|
|
|
|
/obj/effect/mapping_helpers/iannewyear/LateInitialize()
|
|
if(check_holidays(NEW_YEAR))
|
|
fireworks()
|
|
qdel(src)
|
|
|
|
/obj/effect/mapping_helpers/iannewyear/proc/fireworks()
|
|
var/area/celebration_area = get_area(src)
|
|
var/list/table_turfs = list()
|
|
var/turf/dogbed_turf
|
|
for (var/list/zlevel_turfs as anything in celebration_area.get_zlevel_turf_lists())
|
|
for(var/turf/area_turf as anything in zlevel_turfs)
|
|
if(locate(/obj/structure/table/reinforced) in area_turf)
|
|
table_turfs += area_turf
|
|
if(locate(/obj/structure/bed/dogbed/ian) in area_turf)
|
|
dogbed_turf = area_turf
|
|
|
|
if(isnull(dogbed_turf))
|
|
log_mapping("[src] in [celebration_area] could not find Ian's dogbed.")
|
|
return
|
|
|
|
new /obj/item/clothing/head/costume/festive(dogbed_turf)
|
|
var/obj/item/reagent_containers/cup/glass/bottle/champagne/iandrink = new(dogbed_turf)
|
|
iandrink.name = "dog champagne"
|
|
iandrink.pixel_y += 8
|
|
iandrink.pixel_x += 8
|
|
|
|
var/turf/fireworks_turf = length(table_turfs) ? pick(table_turfs) : dogbed_turf
|
|
var/obj/item/storage/box/matches/matchbox = new(fireworks_turf)
|
|
matchbox.pixel_y += 8
|
|
matchbox.pixel_x -= 3
|
|
new /obj/item/storage/box/fireworks/dangerous(fireworks_turf) //dangerous version for extra holiday memes.
|
|
|
|
//lets mappers place notes on airlocks with custom info or a pre-made note from a path
|
|
/obj/effect/mapping_helpers/airlock_note_placer
|
|
name = "Airlock Note Placer"
|
|
late = TRUE
|
|
icon_state = "airlocknoteplacer"
|
|
var/note_info //for writing out custom notes without creating an extra paper subtype
|
|
var/note_name //custom note name
|
|
var/note_path //if you already have something wrote up in a paper subtype, put the path here
|
|
|
|
/obj/effect/mapping_helpers/airlock_note_placer/LateInitialize()
|
|
var/turf/turf = get_turf(src)
|
|
if(note_path && !ispath(note_path, /obj/item/paper)) //don't put non-paper in the paper slot thank you
|
|
log_mapping("[src] at [x],[y] had an improper note_path path, could not place paper note.")
|
|
qdel(src)
|
|
return
|
|
if(locate(/obj/machinery/door/airlock) in turf)
|
|
var/obj/machinery/door/airlock/found_airlock = locate(/obj/machinery/door/airlock) in turf
|
|
if(note_path)
|
|
var/obj/item/paper/paper = new note_path(src)
|
|
found_airlock.note = paper
|
|
paper.forceMove(found_airlock)
|
|
found_airlock.update_appearance()
|
|
qdel(src)
|
|
return
|
|
if(note_info)
|
|
var/obj/item/paper/paper = new /obj/item/paper(src)
|
|
if(note_name)
|
|
paper.name = note_name
|
|
paper.add_raw_text("[note_info]")
|
|
paper.update_appearance()
|
|
found_airlock.note = paper
|
|
paper.forceMove(found_airlock)
|
|
found_airlock.update_appearance()
|
|
qdel(src)
|
|
return
|
|
log_mapping("[src] at [x],[y] had no note_path or note_info, cannot place paper note.")
|
|
qdel(src)
|
|
return
|
|
log_mapping("[src] at [x],[y] could not find an airlock on current turf, cannot place paper note.")
|
|
qdel(src)
|
|
|
|
/**
|
|
* ## 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
|
|
*/
|
|
/obj/effect/mapping_helpers/trapdoor_placer
|
|
name = "trapdoor placer"
|
|
icon_state = "trapdoor"
|
|
late = TRUE
|
|
|
|
/obj/effect/mapping_helpers/trapdoor_placer/LateInitialize()
|
|
var/turf/component_target = get_turf(src)
|
|
component_target.AddComponent(/datum/component/trapdoor, starts_open = FALSE, conspicuous = FALSE)
|
|
qdel(src)
|
|
|
|
/obj/effect/mapping_helpers/ztrait_injector
|
|
name = "ztrait injector"
|
|
icon_state = "ztrait"
|
|
late = TRUE
|
|
/// List of traits to add to this Z-level.
|
|
var/list/traits_to_add = list()
|
|
|
|
/obj/effect/mapping_helpers/ztrait_injector/LateInitialize()
|
|
var/datum/space_level/level = SSmapping.z_list[z]
|
|
if(!level || !length(traits_to_add))
|
|
return
|
|
level.traits |= traits_to_add
|
|
SSweather.update_z_level(level) //in case of someone adding a weather for the level, we want SSweather to update for that
|
|
|
|
/obj/effect/mapping_helpers/circuit_spawner
|
|
name = "circuit spawner"
|
|
icon_state = "circuit"
|
|
/// The shell for the circuit.
|
|
var/atom/movable/circuit_shell
|
|
/// Capacity of the shell.
|
|
var/shell_capacity = SHELL_CAPACITY_VERY_LARGE
|
|
/// The url for the json. Example: "https://pastebin.com/raw/eH7VnP9d"
|
|
var/json_url
|
|
|
|
/obj/effect/mapping_helpers/circuit_spawner/Initialize(mapload)
|
|
. = ..()
|
|
INVOKE_ASYNC(src, PROC_REF(spawn_circuit))
|
|
|
|
/obj/effect/mapping_helpers/circuit_spawner/proc/spawn_circuit()
|
|
var/list/errors = list()
|
|
var/obj/item/integrated_circuit/loaded/new_circuit = new(loc)
|
|
var/json_data = load_data()
|
|
new_circuit.load_circuit_data(json_data, errors)
|
|
if(!circuit_shell)
|
|
return
|
|
circuit_shell = new(loc)
|
|
var/datum/component/shell/shell_component = circuit_shell.GetComponent(/datum/component/shell)
|
|
if(shell_component)
|
|
shell_component.shell_flags |= SHELL_FLAG_CIRCUIT_UNMODIFIABLE|SHELL_FLAG_CIRCUIT_UNREMOVABLE
|
|
shell_component.attach_circuit(new_circuit)
|
|
else
|
|
shell_component = circuit_shell.AddComponent(/datum/component/shell, \
|
|
capacity = shell_capacity, \
|
|
shell_flags = SHELL_FLAG_CIRCUIT_UNMODIFIABLE|SHELL_FLAG_CIRCUIT_UNREMOVABLE, \
|
|
starting_circuit = new_circuit, \
|
|
)
|
|
|
|
/obj/effect/mapping_helpers/circuit_spawner/proc/load_data()
|
|
var/static/json_cache = list()
|
|
var/static/query_in_progress = FALSE //We're using a single tmp file so keep it linear.
|
|
if(query_in_progress)
|
|
UNTIL(!query_in_progress)
|
|
if(json_cache[json_url])
|
|
return json_cache[json_url]
|
|
log_asset("Circuit Spawner fetching json from: [json_url]")
|
|
var/datum/http_request/request = new()
|
|
request.prepare(RUSTG_HTTP_METHOD_GET, json_url, "")
|
|
query_in_progress = TRUE
|
|
request.begin_async()
|
|
UNTIL(request.is_complete())
|
|
var/datum/http_response/response = request.into_response()
|
|
if(response.errored || response.status_code != 200)
|
|
query_in_progress = FALSE
|
|
CRASH("Failed to fetch mapped custom json from url [json_url], code: [response.status_code], error: [response.error]")
|
|
var/json_data = response.body
|
|
json_cache[json_url] = json_data
|
|
query_in_progress = FALSE
|
|
return json_data
|
|
|
|
/obj/effect/mapping_helpers/broken_floor
|
|
name = "broken floor"
|
|
icon = 'icons/turf/damaged.dmi'
|
|
icon_state = "damaged1"
|
|
layer = ABOVE_NORMAL_TURF_LAYER
|
|
late = TRUE
|
|
|
|
/obj/effect/mapping_helpers/broken_floor/LateInitialize()
|
|
var/turf/open/floor/floor = get_turf(src)
|
|
floor.break_tile()
|
|
qdel(src)
|
|
|
|
/obj/effect/mapping_helpers/burnt_floor
|
|
name = "burnt floor"
|
|
icon = 'icons/turf/damaged.dmi'
|
|
icon_state = "floorscorched1"
|
|
layer = ABOVE_NORMAL_TURF_LAYER
|
|
late = TRUE
|
|
|
|
/obj/effect/mapping_helpers/burnt_floor/LateInitialize()
|
|
var/turf/open/floor/floor = get_turf(src)
|
|
floor.burn_tile()
|
|
qdel(src)
|
|
|
|
///Applies BROKEN flag to the first found machine on a tile
|
|
/obj/effect/mapping_helpers/broken_machine
|
|
name = "broken machine helper"
|
|
icon_state = "broken_machine"
|
|
late = TRUE
|
|
|
|
/obj/effect/mapping_helpers/broken_machine/Initialize(mapload)
|
|
. = ..()
|
|
if(!mapload)
|
|
log_mapping("[src] spawned outside of mapload!")
|
|
return INITIALIZE_HINT_QDEL
|
|
|
|
var/obj/machinery/target = locate(/obj/machinery) in loc
|
|
if(isnull(target))
|
|
var/area/target_area = get_area(src)
|
|
log_mapping("[src] failed to find a machine at [AREACOORD(src)] ([target_area.type]).")
|
|
else
|
|
payload(target)
|
|
|
|
return INITIALIZE_HINT_LATELOAD
|
|
|
|
/obj/effect/mapping_helpers/broken_machine/LateInitialize()
|
|
var/obj/machinery/target = locate(/obj/machinery) in loc
|
|
|
|
if(isnull(target))
|
|
qdel(src)
|
|
return
|
|
|
|
target.update_appearance()
|
|
qdel(src)
|
|
|
|
/obj/effect/mapping_helpers/broken_machine/proc/payload(obj/machinery/airalarm/target)
|
|
if(target.machine_stat & BROKEN)
|
|
var/area/area = get_area(target)
|
|
log_mapping("[src] at [AREACOORD(src)] [(area.type)] tried to break [target] but it's already broken!")
|
|
target.set_machine_stat(target.machine_stat | BROKEN)
|
|
|
|
///Deals random damage to the first window found on a tile to appear cracked
|
|
/obj/effect/mapping_helpers/damaged_window
|
|
name = "damaged window helper"
|
|
icon_state = "damaged_window"
|
|
late = TRUE
|
|
/// Minimum roll of integrity damage in percents needed to show cracks
|
|
var/integrity_damage_min = 0.25
|
|
/// Maximum roll of integrity damage in percents needed to show cracks
|
|
var/integrity_damage_max = 0.85
|
|
|
|
/obj/effect/mapping_helpers/damaged_window/Initialize(mapload)
|
|
. = ..()
|
|
if(!mapload)
|
|
log_mapping("[src] spawned outside of mapload!")
|
|
return INITIALIZE_HINT_QDEL
|
|
return INITIALIZE_HINT_LATELOAD
|
|
|
|
/obj/effect/mapping_helpers/damaged_window/LateInitialize()
|
|
var/obj/structure/window/target = locate(/obj/structure/window) in loc
|
|
|
|
if(isnull(target))
|
|
var/area/target_area = get_area(src)
|
|
log_mapping("[src] failed to find a window at [AREACOORD(src)] ([target_area.type]).")
|
|
qdel(src)
|
|
return
|
|
else
|
|
payload(target)
|
|
|
|
target.update_appearance()
|
|
qdel(src)
|
|
|
|
/obj/effect/mapping_helpers/damaged_window/proc/payload(obj/structure/window/target)
|
|
if(target.get_integrity() < target.max_integrity)
|
|
var/area/area = get_area(target)
|
|
log_mapping("[src] at [AREACOORD(src)] [(area.type)] tried to damage [target] but it's already damaged!")
|
|
target.take_damage(rand(target.max_integrity * integrity_damage_min, target.max_integrity * integrity_damage_max))
|
|
|
|
//requests console helpers
|
|
/obj/effect/mapping_helpers/requests_console
|
|
desc = "You shouldn't see this. Report it please."
|
|
late = TRUE
|
|
|
|
/obj/effect/mapping_helpers/requests_console/Initialize(mapload)
|
|
. = ..()
|
|
if(!mapload)
|
|
log_mapping("[src] spawned outside of mapload!")
|
|
return INITIALIZE_HINT_QDEL
|
|
|
|
return INITIALIZE_HINT_LATELOAD
|
|
|
|
/obj/effect/mapping_helpers/requests_console/LateInitialize()
|
|
var/obj/machinery/airalarm/target = locate(/obj/machinery/requests_console) in loc
|
|
if(isnull(target))
|
|
var/area/target_area = get_area(src)
|
|
log_mapping("[src] failed to find a requests console at [AREACOORD(src)] ([target_area.type]).")
|
|
else
|
|
payload(target)
|
|
|
|
qdel(src)
|
|
|
|
/// Fills out the request console's variables
|
|
/obj/effect/mapping_helpers/requests_console/proc/payload(obj/machinery/requests_console/console)
|
|
return
|
|
|
|
/obj/effect/mapping_helpers/requests_console/announcement
|
|
name = "request console announcement helper"
|
|
icon_state = "requests_console_announcement_helper"
|
|
|
|
/obj/effect/mapping_helpers/requests_console/announcement/payload(obj/machinery/requests_console/console)
|
|
console.can_send_announcements = TRUE
|
|
|
|
/obj/effect/mapping_helpers/requests_console/assistance
|
|
name = "request console assistance requestable helper"
|
|
icon_state = "requests_console_assistance_helper"
|
|
|
|
/obj/effect/mapping_helpers/requests_console/assistance/payload(obj/machinery/requests_console/console)
|
|
GLOB.req_console_assistance |= console.department
|
|
|
|
/obj/effect/mapping_helpers/requests_console/supplies
|
|
name = "request console supplies requestable helper"
|
|
icon_state = "requests_console_supplies_helper"
|
|
|
|
/obj/effect/mapping_helpers/requests_console/supplies/payload(obj/machinery/requests_console/console)
|
|
GLOB.req_console_supplies |= console.department
|
|
|
|
/obj/effect/mapping_helpers/requests_console/information
|
|
name = "request console information relayable helper"
|
|
icon_state = "requests_console_information_helper"
|
|
|
|
/obj/effect/mapping_helpers/requests_console/information/payload(obj/machinery/requests_console/console)
|
|
GLOB.req_console_information |= console.department
|
|
|
|
/obj/effect/mapping_helpers/requests_console/ore_update
|
|
name = "request console ore update helper"
|
|
icon_state = "requests_console_ore_update_helper"
|
|
|
|
/obj/effect/mapping_helpers/requests_console/ore_update/payload(obj/machinery/requests_console/console)
|
|
console.receive_ore_updates = TRUE
|
|
|
|
/obj/effect/mapping_helpers/engraving
|
|
name = "engraving helper"
|
|
icon = 'icons/turf/wall_overlays.dmi'
|
|
icon_state = "engraving2"
|
|
late = TRUE
|
|
layer = ABOVE_NORMAL_TURF_LAYER
|
|
|
|
/obj/effect/mapping_helpers/engraving/Initialize(mapload)
|
|
. = ..()
|
|
return INITIALIZE_HINT_LATELOAD
|
|
|
|
/obj/effect/mapping_helpers/engraving/LateInitialize()
|
|
var/turf/closed/engraved_wall = get_turf(src)
|
|
|
|
if(!isclosedturf(engraved_wall) || !SSpersistence.saved_engravings.len || HAS_TRAIT(engraved_wall, TRAIT_NOT_ENGRAVABLE))
|
|
qdel(src)
|
|
return
|
|
|
|
var/engraving = pick_n_take(SSpersistence.saved_engravings)
|
|
if(!islist(engraving))
|
|
stack_trace("something's wrong with the engraving data! one of the saved engravings wasn't a list!")
|
|
qdel(src)
|
|
return
|
|
|
|
engraved_wall.AddComponent(/datum/component/engraved, engraving["story"], FALSE, engraving["story_value"])
|
|
qdel(src)
|
|
|
|
/// Apply to a wall (or floor, technically) to ensure it is instantly destroyed by any explosion, even if usually invulnerable
|
|
/obj/effect/mapping_helpers/bombable_wall
|
|
name = "bombable wall helper"
|
|
icon = 'icons/turf/overlays.dmi'
|
|
icon_state = "explodable"
|
|
|
|
/obj/effect/mapping_helpers/bombable_wall/Initialize(mapload)
|
|
. = ..()
|
|
if(!mapload)
|
|
log_mapping("[src] spawned outside of mapload!")
|
|
return
|
|
|
|
var/turf/our_turf = get_turf(src) // In case a locker ate us or something
|
|
our_turf.AddElement(/datum/element/bombable_turf)
|
|
return INITIALIZE_HINT_QDEL
|
|
|
|
/// this helper buckles all mobs on the tile to the first buckleable object
|
|
/obj/effect/mapping_helpers/mob_buckler
|
|
name = "Buckle Mob"
|
|
icon_state = "buckle"
|
|
late = TRUE
|
|
///whether we force a buckle
|
|
var/force_buckle = FALSE
|
|
|
|
/obj/effect/mapping_helpers/mob_buckler/Initialize(mapload)
|
|
. = ..()
|
|
if(!mapload)
|
|
log_mapping("[src] spawned outside of mapload!")
|
|
return INITIALIZE_HINT_QDEL
|
|
|
|
return INITIALIZE_HINT_LATELOAD
|
|
|
|
/obj/effect/mapping_helpers/mob_buckler/LateInitialize()
|
|
var/atom/movable/buckle_to
|
|
var/list/mobs = list()
|
|
for(var/atom/movable/possible_buckle as anything in loc)
|
|
if(isnull(buckle_to) && possible_buckle.can_buckle)
|
|
buckle_to = possible_buckle
|
|
continue
|
|
|
|
if(isliving(possible_buckle))
|
|
mobs += possible_buckle
|
|
|
|
if(isnull(buckle_to))
|
|
log_mapping("[type] at [x] [y] [z] did not find anything to buckle to")
|
|
qdel(src)
|
|
return
|
|
|
|
for(var/mob/living/mob as anything in mobs)
|
|
buckle_to.buckle_mob(mob, force = force_buckle)
|
|
|
|
qdel(src)
|
|
|
|
///Basic mob flag helpers for things like deleting on death.
|
|
/obj/effect/mapping_helpers/basic_mob_flags
|
|
name = "Basic mob flags helper"
|
|
desc = "Used to apply basic_mob_flags to basic mobs on the same turf."
|
|
late = TRUE
|
|
|
|
///The basic mob flag that we're adding to all basic mobs on the turf.
|
|
var/flag_to_give
|
|
|
|
/obj/effect/mapping_helpers/basic_mob_flags/Initialize(mapload)
|
|
. = ..()
|
|
if(!mapload)
|
|
log_mapping("[src] spawned outside of mapload!")
|
|
return INITIALIZE_HINT_QDEL
|
|
|
|
/obj/effect/mapping_helpers/basic_mob_flags/LateInitialize()
|
|
var/had_any_mobs = FALSE
|
|
for(var/mob/living/basic/basic_mobs in loc)
|
|
had_any_mobs = TRUE
|
|
basic_mobs.basic_mob_flags |= flag_to_give
|
|
if(!had_any_mobs)
|
|
CRASH("[src] called on a turf without any basic mobs.")
|
|
qdel(src)
|
|
|
|
/obj/effect/mapping_helpers/basic_mob_flags/del_on_death
|
|
name = "Basic mob del on death flag helper"
|
|
icon_state = "basic_mob_del_on_death"
|
|
flag_to_give = DEL_ON_DEATH
|
|
|
|
/obj/effect/mapping_helpers/basic_mob_flags/flip_on_death
|
|
name = "Basic mob flip on death flag helper"
|
|
icon_state = "basic_mob_flip_on_death"
|
|
flag_to_give = FLIP_ON_DEATH
|
|
|
|
/obj/effect/mapping_helpers/basic_mob_flags/remain_dense_while_dead
|
|
name = "Basic mob remain dense while dead flag helper"
|
|
icon_state = "basic_mob_remain_dense_while_dead"
|
|
flag_to_give = REMAIN_DENSE_WHILE_DEAD
|
|
|
|
/obj/effect/mapping_helpers/basic_mob_flags/flammable_mob
|
|
name = "Basic mob flammable flag helper"
|
|
icon_state = "basic_mob_flammable"
|
|
flag_to_give = FLAMMABLE_MOB
|
|
|
|
/obj/effect/mapping_helpers/basic_mob_flags/immune_to_fists
|
|
name = "Basic mob immune to fists flag helper"
|
|
icon_state = "basic_mob_immune_to_fists"
|
|
flag_to_give = IMMUNE_TO_FISTS
|
|
|
|
/obj/effect/mapping_helpers/basic_mob_flags/immune_to_getting_wet
|
|
name = "Basic mob immune to getting wet flag helper"
|
|
icon_state = "basic_mob_immune_to_getting_wet"
|
|
flag_to_give = IMMUNE_TO_GETTING_WET
|
|
|
|
/obj/effect/mapping_helpers/wall_dent
|
|
name = "bullet impact dent"
|
|
icon = 'icons/effects/effects.dmi'
|
|
icon_state = "bullet_hole"
|
|
/// Dent type to spawn
|
|
var/dent_type = WALL_DENT_SHOT
|
|
|
|
/obj/effect/mapping_helpers/wall_dent/Initialize(mapload)
|
|
. = ..()
|
|
if(!mapload)
|
|
log_mapping("[src] spawned outside of mapload!")
|
|
return
|
|
|
|
var/turf/closed/wall/our_turf = get_turf(src) // In case a locker ate us or something
|
|
if (!istype(our_turf))
|
|
log_mapping("[src] placed on a non-wall turf!")
|
|
return
|
|
|
|
our_turf.add_dent(dent_type, pixel_x + pixel_w - ICON_SIZE_X / 2, pixel_y + pixel_z - ICON_SIZE_Y / 2)
|
|
return INITIALIZE_HINT_QDEL
|
|
|
|
/obj/effect/mapping_helpers/wall_dent/impact
|
|
name = "blunt impact dent"
|
|
icon_state = "impact1"
|
|
dent_type = WALL_DENT_HIT
|