mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2025-12-16 04:34:21 +00:00
3591 individual conflicts Update build.js Update install_node.sh Update byond.js oh my fucking god hat slow huh holy shit we all fall down 2 more I missed 2900 individual conflicts 2700 Individual conflicts replaces yarn file with tg version, bumping us down to 2200-ish Down to 2000 individual conflicts 140 down mmm aaaaaaaaaaaaaaaaaaa not yt 575 soon 900 individual conflicts 600 individual conflicts, 121 file conflicts im not okay 160 across 19 files 29 in 4 files 0 conflicts, compiletime fix time some minor incap stuff missed ticks weird dupe definition stuff missed ticks 2 incap fixes undefs and pie fix Radio update and some extra minor stuff returns a single override no more dupe definitions, 175 compiletime errors Unticked file fix sound and emote stuff honk and more radio stuff
320 lines
12 KiB
Plaintext
320 lines
12 KiB
Plaintext
// Used by /turf/open/chasm and subtypes to implement the "dropping" mechanic
|
|
/datum/component/chasm
|
|
var/turf/target_turf
|
|
var/obj/effect/abstract/chasm_storage/storage
|
|
var/fall_message = "GAH! Ah... where are you?"
|
|
var/oblivion_message = "You stumble and stare into the abyss before you. It stares back, and you fall into the enveloping dark."
|
|
|
|
/// List of refs to falling objects -> how many levels deep we've fallen
|
|
var/static/list/falling_atoms = list()
|
|
var/static/list/forbidden_types = typecacheof(list(
|
|
/obj/docking_port,
|
|
/obj/effect/abstract,
|
|
/obj/effect/collapse,
|
|
/obj/effect/constructing_effect,
|
|
/obj/effect/dummy/phased_mob,
|
|
/obj/effect/ebeam,
|
|
/obj/effect/fishing_float,
|
|
/obj/effect/hotspot,
|
|
/obj/effect/landmark,
|
|
/obj/effect/light_emitter/tendril,
|
|
/obj/effect/mapping_helpers,
|
|
/obj/effect/particle_effect/ion_trails,
|
|
/obj/effect/particle_effect/sparks,
|
|
/obj/effect/portal,
|
|
/obj/effect/projectile,
|
|
/obj/effect/spectre_of_resurrection,
|
|
/obj/effect/temp_visual,
|
|
/obj/effect/wisp,
|
|
/obj/energy_ball,
|
|
/obj/narsie,
|
|
/obj/projectile,
|
|
/obj/singularity,
|
|
/obj/structure/lattice,
|
|
/obj/structure/stone_tile,
|
|
/obj/structure/ore_vent,
|
|
))
|
|
|
|
/datum/component/chasm/Initialize(turf/target, mapload)
|
|
if(!isturf(parent))
|
|
return COMPONENT_INCOMPATIBLE
|
|
RegisterSignal(parent, SIGNAL_ADDTRAIT(TRAIT_CHASM_STOPPED), PROC_REF(on_chasm_stopped))
|
|
RegisterSignal(parent, SIGNAL_REMOVETRAIT(TRAIT_CHASM_STOPPED), PROC_REF(on_chasm_no_longer_stopped))
|
|
target_turf = target
|
|
RegisterSignal(parent, COMSIG_ATOM_ABSTRACT_ENTERED, PROC_REF(entered))
|
|
RegisterSignal(parent, COMSIG_ATOM_ABSTRACT_EXITED, PROC_REF(exited))
|
|
RegisterSignal(parent, COMSIG_ATOM_AFTER_SUCCESSFUL_INITIALIZED_ON, PROC_REF(initialized_on))
|
|
RegisterSignal(parent, COMSIG_ATOM_INTERCEPT_TELEPORTING, PROC_REF(block_teleport))
|
|
//allow catwalks to give the turf the CHASM_STOPPED trait before dropping stuff when the turf is changed.
|
|
//otherwise don't do anything because turfs and areas are initialized before movables.
|
|
if(!mapload)
|
|
addtimer(CALLBACK(src, PROC_REF(drop_stuff)), 0)
|
|
parent.AddElement(/datum/element/lazy_fishing_spot, /datum/fish_source/chasm)
|
|
|
|
/datum/component/chasm/UnregisterFromParent()
|
|
storage = null
|
|
|
|
/datum/component/chasm/proc/entered(datum/source, atom/movable/arrived, atom/old_loc, list/atom/old_locs)
|
|
SIGNAL_HANDLER
|
|
drop_stuff()
|
|
|
|
/datum/component/chasm/proc/exited(datum/source, atom/movable/exited)
|
|
SIGNAL_HANDLER
|
|
UnregisterSignal(exited, list(COMSIG_MOVETYPE_FLAG_DISABLED, COMSIG_LIVING_SET_BUCKLED, COMSIG_MOVABLE_THROW_LANDED))
|
|
|
|
/datum/component/chasm/proc/initialized_on(datum/source, atom/movable/movable, mapload)
|
|
SIGNAL_HANDLER
|
|
drop_stuff(movable)
|
|
|
|
/datum/component/chasm/proc/block_teleport()
|
|
return COMPONENT_BLOCK_TELEPORT
|
|
|
|
/datum/component/chasm/proc/on_chasm_stopped(datum/source)
|
|
SIGNAL_HANDLER
|
|
UnregisterSignal(source, list(COMSIG_ATOM_ENTERED, COMSIG_ATOM_EXITED, COMSIG_ATOM_AFTER_SUCCESSFUL_INITIALIZED_ON))
|
|
for(var/atom/movable/movable as anything in source)
|
|
UnregisterSignal(movable, list(COMSIG_MOVETYPE_FLAG_DISABLED, COMSIG_LIVING_SET_BUCKLED, COMSIG_MOVABLE_THROW_LANDED))
|
|
|
|
/datum/component/chasm/proc/on_chasm_no_longer_stopped(datum/source)
|
|
SIGNAL_HANDLER
|
|
RegisterSignal(parent, COMSIG_ATOM_ENTERED, PROC_REF(entered))
|
|
RegisterSignal(parent, COMSIG_ATOM_EXITED, PROC_REF(exited))
|
|
RegisterSignal(parent, COMSIG_ATOM_AFTER_SUCCESSFUL_INITIALIZED_ON, PROC_REF(initialized_on))
|
|
drop_stuff()
|
|
|
|
#define CHASM_NOT_DROPPING 0
|
|
#define CHASM_DROPPING 1
|
|
///Doesn't drop the movable, but registers a few signals to try again if the conditions change.
|
|
#define CHASM_REGISTER_SIGNALS 2
|
|
|
|
/datum/component/chasm/proc/drop_stuff(atom/movable/dropped_thing)
|
|
if(HAS_TRAIT(parent, TRAIT_CHASM_STOPPED))
|
|
return
|
|
var/atom/atom_parent = parent
|
|
var/to_check = dropped_thing ? list(dropped_thing) : atom_parent.contents
|
|
for (var/atom/movable/thing as anything in to_check)
|
|
var/dropping = droppable(thing)
|
|
switch(dropping)
|
|
if(CHASM_DROPPING)
|
|
INVOKE_ASYNC(src, PROC_REF(drop), thing)
|
|
if(CHASM_REGISTER_SIGNALS)
|
|
RegisterSignals(thing, list(COMSIG_MOVETYPE_FLAG_DISABLED, COMSIG_LIVING_SET_BUCKLED, COMSIG_MOVABLE_THROW_LANDED), PROC_REF(drop_stuff), TRUE)
|
|
|
|
/datum/component/chasm/proc/droppable(atom/movable/dropped_thing)
|
|
var/datum/weakref/falling_ref = WEAKREF(dropped_thing)
|
|
// avoid an infinite loop, but allow falling a large distance
|
|
if(falling_atoms[falling_ref] && falling_atoms[falling_ref] > 30)
|
|
return CHASM_NOT_DROPPING
|
|
if(is_type_in_typecache(dropped_thing, forbidden_types) || (!isliving(dropped_thing) && !isobj(dropped_thing)))
|
|
return CHASM_NOT_DROPPING
|
|
if(dropped_thing.throwing || (dropped_thing.movement_type & MOVETYPES_NOT_TOUCHING_GROUND))
|
|
return CHASM_REGISTER_SIGNALS
|
|
for(var/atom/thing_to_check as anything in parent)
|
|
if(HAS_TRAIT(thing_to_check, TRAIT_CHASM_STOPPER))
|
|
return CHASM_NOT_DROPPING
|
|
|
|
//Flies right over the chasm
|
|
if(ismob(dropped_thing))
|
|
var/mob/M = dropped_thing
|
|
if(M.buckled) //middle statement to prevent infinite loops just in case!
|
|
var/mob/buckled_to = M.buckled
|
|
if((!ismob(M.buckled) || (buckled_to.buckled != M)) && !droppable(M.buckled))
|
|
return CHASM_REGISTER_SIGNALS
|
|
if(ishuman(dropped_thing))
|
|
var/mob/living/carbon/human/victim = dropped_thing
|
|
if(istype(victim.belt, /obj/item/wormhole_jaunter))
|
|
var/obj/item/wormhole_jaunter/jaunter = victim.belt
|
|
var/turf/chasm = get_turf(victim)
|
|
var/fall_into_chasm = jaunter.chasm_react(victim)
|
|
if(!fall_into_chasm)
|
|
chasm.visible_message(span_boldwarning("[victim] falls into the [chasm]!")) //To freak out any bystanders
|
|
return fall_into_chasm ? CHASM_DROPPING : CHASM_NOT_DROPPING
|
|
return CHASM_DROPPING
|
|
|
|
#undef CHASM_NOT_DROPPING
|
|
#undef CHASM_DROPPING
|
|
#undef CHASM_REGISTER_SIGNALS
|
|
|
|
/datum/component/chasm/proc/drop(atom/movable/dropped_thing)
|
|
var/datum/weakref/falling_ref = WEAKREF(dropped_thing)
|
|
//Make sure the item is still there after our sleep
|
|
if(!dropped_thing || !falling_ref?.resolve())
|
|
falling_atoms -= falling_ref
|
|
return
|
|
falling_atoms[falling_ref] = (falling_atoms[falling_ref] || 0) + 1
|
|
var/turf/below_turf = target_turf
|
|
var/atom/parent = src.parent
|
|
|
|
if(falling_atoms[falling_ref] > 1)
|
|
return // We're already handling this
|
|
|
|
if(below_turf)
|
|
if(HAS_TRAIT(dropped_thing, TRAIT_CHASM_DESTROYED))
|
|
qdel(dropped_thing)
|
|
return
|
|
|
|
// send to the turf below
|
|
dropped_thing.visible_message(span_boldwarning("[dropped_thing] falls into [parent]!"), span_userdanger("[fall_message]"))
|
|
below_turf.visible_message(span_boldwarning("[dropped_thing] falls from above!"))
|
|
dropped_thing.forceMove(below_turf)
|
|
if(isliving(dropped_thing))
|
|
var/mob/living/fallen = dropped_thing
|
|
fallen.Paralyze(100)
|
|
fallen.adjustBruteLoss(30)
|
|
falling_atoms -= falling_ref
|
|
return
|
|
|
|
// send to oblivion
|
|
dropped_thing.visible_message(span_boldwarning("[dropped_thing] falls into [parent]!"), span_userdanger("[oblivion_message]"))
|
|
if (isliving(dropped_thing))
|
|
var/mob/living/falling_mob = dropped_thing
|
|
ADD_TRAIT(falling_mob, TRAIT_NO_TRANSFORM, REF(src))
|
|
falling_mob.Paralyze(20 SECONDS)
|
|
|
|
var/oldtransform = dropped_thing.transform
|
|
var/oldcolor = dropped_thing.color
|
|
var/oldalpha = dropped_thing.alpha
|
|
var/oldoffset = dropped_thing.pixel_y
|
|
|
|
animate(dropped_thing, transform = matrix() - matrix(), alpha = 0, color = rgb(0, 0, 0), time = 10)
|
|
for(var/i in 1 to 5)
|
|
//Make sure the item is still there after our sleep
|
|
if(!dropped_thing || QDELETED(dropped_thing))
|
|
return
|
|
dropped_thing.pixel_y--
|
|
sleep(0.2 SECONDS)
|
|
|
|
//Make sure the item is still there after our sleep
|
|
if(!dropped_thing || QDELETED(dropped_thing))
|
|
return
|
|
|
|
if(HAS_TRAIT(dropped_thing, TRAIT_CHASM_DESTROYED))
|
|
qdel(dropped_thing)
|
|
return
|
|
|
|
if(!storage)
|
|
storage = (locate() in parent) || new(parent)
|
|
|
|
if(storage.contains(dropped_thing))
|
|
return
|
|
|
|
dropped_thing.alpha = oldalpha
|
|
dropped_thing.color = oldcolor
|
|
dropped_thing.transform = oldtransform
|
|
dropped_thing.pixel_y = oldoffset
|
|
|
|
if(!dropped_thing.forceMove(storage))
|
|
parent.visible_message(span_boldwarning("[parent] spits out [dropped_thing]!"))
|
|
dropped_thing.throw_at(get_edge_target_turf(parent, pick(GLOB.alldirs)), rand(1, 10), rand(1, 10))
|
|
|
|
else if(isliving(dropped_thing))
|
|
var/mob/living/fallen_mob = dropped_thing
|
|
REMOVE_TRAIT(fallen_mob, TRAIT_NO_TRANSFORM, REF(src))
|
|
if (fallen_mob.stat != DEAD)
|
|
fallen_mob.investigate_log("has died from falling into a chasm.", INVESTIGATE_DEATHS)
|
|
if(issilicon(fallen_mob))
|
|
//Silicons are held together by hopes and dreams, unfortunately, I'm having a nightmare
|
|
var/mob/living/silicon/robot/fallen_borg = fallen_mob
|
|
fallen_borg.mmi = null
|
|
fallen_mob.death(TRUE)
|
|
fallen_mob.apply_damage(300)
|
|
|
|
falling_atoms -= falling_ref
|
|
|
|
/**
|
|
* Called when something has left the chasm depths storage.
|
|
* Arguments
|
|
*
|
|
* * source - Chasm object holder.
|
|
* * gone - Item which has just left the chasm contents.
|
|
*/
|
|
/datum/component/chasm/proc/left_chasm(atom/source, atom/movable/gone)
|
|
SIGNAL_HANDLER
|
|
UnregisterSignal(gone, COMSIG_LIVING_REVIVE)
|
|
|
|
///Global list needed to let fishermen with a rescue hook fish fallen mobs from any place
|
|
GLOBAL_LIST_EMPTY(chasm_fallen_mobs)
|
|
|
|
/**
|
|
* An abstract object which is basically just a bag that the chasm puts people inside
|
|
*/
|
|
/obj/effect/abstract/chasm_storage
|
|
name = "chasm depths"
|
|
desc = "The bottom of a hole. You shouldn't be able to interact with this."
|
|
anchored = TRUE
|
|
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
|
|
|
|
/obj/effect/abstract/chasm_storage/Initialize(mapload)
|
|
. = ..()
|
|
ADD_TRAIT(src, TRAIT_SECLUDED_LOCATION, INNATE_TRAIT)
|
|
|
|
/obj/effect/abstract/chasm_storage/Entered(atom/movable/arrived)
|
|
. = ..()
|
|
if(isliving(arrived))
|
|
RegisterSignal(arrived, COMSIG_LIVING_REVIVE, PROC_REF(on_revive))
|
|
LAZYADD(GLOB.chasm_fallen_mobs[get_chasm_category(loc)], arrived)
|
|
|
|
/obj/effect/abstract/chasm_storage/Exited(atom/movable/gone)
|
|
. = ..()
|
|
if(isliving(gone))
|
|
UnregisterSignal(gone, COMSIG_LIVING_REVIVE)
|
|
LAZYREMOVE(GLOB.chasm_fallen_mobs[get_chasm_category(loc)], gone)
|
|
|
|
/obj/effect/abstract/chasm_storage/on_changed_z_level(turf/old_turf, turf/new_turf, same_z_layer, notify_contents)
|
|
. = ..()
|
|
var/old_cat = get_chasm_category(old_turf)
|
|
var/new_cat = get_chasm_category(new_turf)
|
|
var/list/mobs = list()
|
|
for(var/mob/fallen in src)
|
|
mobs += fallen
|
|
LAZYREMOVE(GLOB.chasm_fallen_mobs[old_cat], mobs)
|
|
LAZYADD(GLOB.chasm_fallen_mobs[new_cat], mobs)
|
|
|
|
/**
|
|
* Returns a key to store, remove and access fallen mobs depending on the z-level.
|
|
* This stops rescuing people from places that are waaaaaaaay too far-fetched.
|
|
*/
|
|
/proc/get_chasm_category(turf/turf)
|
|
var/z_level = turf?.z
|
|
var/area/area = get_area(turf)
|
|
if(istype(area, /area/shuttle)) //shuttle move between z-levels, so they're a special case.
|
|
return area
|
|
|
|
if(is_away_level(z_level))
|
|
return ZTRAIT_AWAY
|
|
if(is_mining_level(z_level))
|
|
return ZTRAIT_MINING
|
|
if(is_station_level(z_level))
|
|
return ZTRAIT_STATION
|
|
if(is_centcom_level(z_level))
|
|
return ZTRAIT_CENTCOM
|
|
if(is_reserved_level(z_level))
|
|
return ZTRAIT_RESERVED
|
|
|
|
return ZTRAIT_SPACE_RUINS
|
|
|
|
#define CHASM_TRAIT "chasm trait"
|
|
/**
|
|
* Called if something comes back to life inside the pit. Expected sources are badmins and changelings.
|
|
* Ethereals should take enough damage to be smashed and not revive.
|
|
* Arguments
|
|
* escapee - Lucky guy who just came back to life at the bottom of a hole.
|
|
*/
|
|
/obj/effect/abstract/chasm_storage/proc/on_revive(mob/living/escapee)
|
|
SIGNAL_HANDLER
|
|
var/turf/turf = get_turf(src)
|
|
if(turf.GetComponent(/datum/component/chasm))
|
|
turf.visible_message(span_boldwarning("After a long climb, [escapee] leaps out of [turf]!"))
|
|
else
|
|
playsound(turf, 'sound/effects/bang.ogg', 50, TRUE)
|
|
turf.visible_message(span_boldwarning("[escapee] busts through [turf], leaping out of the chasm below"))
|
|
turf.ScrapeAway(2, flags = CHANGETURF_INHERIT_AIR)
|
|
ADD_TRAIT(escapee, TRAIT_MOVE_FLYING, CHASM_TRAIT) //Otherwise they instantly fall back in
|
|
escapee.forceMove(turf)
|
|
escapee.throw_at(get_edge_target_turf(turf, pick(GLOB.alldirs)), rand(1, 10), rand(1, 10))
|
|
REMOVE_TRAIT(escapee, TRAIT_MOVE_FLYING, CHASM_TRAIT)
|
|
escapee.Paralyze(20 SECONDS, TRUE)
|
|
UnregisterSignal(escapee, COMSIG_LIVING_REVIVE)
|
|
|
|
#undef CHASM_TRAIT
|