mirror of
https://github.com/Aurorastation/Aurora.3.git
synced 2025-12-23 16:42:13 +00:00
282 lines
10 KiB
Plaintext
282 lines
10 KiB
Plaintext
//shuttle moving state defines are in setup.dm
|
|
|
|
/datum/shuttle
|
|
var/name = ""
|
|
var/warmup_time = 0
|
|
var/moving_status = SHUTTLE_IDLE
|
|
|
|
var/list/shuttle_area //can be both single area type or a list of areas
|
|
var/obj/effect/shuttle_landmark/current_location //This variable is type-abused initially: specify the landmark_tag, not the actual landmark.
|
|
|
|
var/arrive_time = 0 //the time at which the shuttle arrives when long jumping
|
|
var/flags = 0
|
|
var/process_state = IDLE_STATE //Used with SHUTTLE_FLAGS_PROCESS, as well as to store current state.
|
|
var/category = /datum/shuttle
|
|
var/multiz = 0 //how many multiz levels, starts at 0
|
|
|
|
var/ceiling_type = /turf/simulated/floor/airless/ceiling
|
|
|
|
var/sound_takeoff = 'sound/effects/shuttle_takeoff.ogg'
|
|
var/sound_landing = 'sound/effects/shuttle_landing.ogg'
|
|
|
|
var/knockdown = TRUE //whether shuttle downs non-buckled people when it moves
|
|
|
|
var/defer_initialisation = FALSE //this shuttle will/won't be initialised automatically. If set to true, you are responsible for initialzing the shuttle manually.
|
|
//Useful for shuttles that are initialed by map_template loading, or shuttles that are created in-game or not used.
|
|
var/logging_home_tag //Whether in-game logs will be generated whenever the shuttle leaves/returns to the landmark with this landmark_tag.
|
|
var/logging_access //Controls who has write access to log-related stuff; should correlate with pilot access.
|
|
|
|
var/mothershuttle //tag of mothershuttle
|
|
var/motherdock //tag of mothershuttle landmark, defaults to starting location
|
|
|
|
var/squishes = TRUE //decides whether or not things get squished when it moves.
|
|
|
|
/datum/shuttle/New(_name, var/obj/effect/shuttle_landmark/initial_location)
|
|
..()
|
|
if(_name)
|
|
src.name = _name
|
|
|
|
var/list/areas = list()
|
|
if(!islist(shuttle_area))
|
|
shuttle_area = list(shuttle_area)
|
|
for(var/T in shuttle_area)
|
|
var/area/A = locate(T)
|
|
if(!istype(A))
|
|
CRASH("Shuttle \"[name]\" couldn't locate area [T].")
|
|
areas += A
|
|
shuttle_area = areas
|
|
|
|
if(initial_location)
|
|
current_location = initial_location
|
|
else
|
|
current_location = SSshuttle.get_landmark(current_location)
|
|
if(!istype(current_location))
|
|
CRASH("Shuttle \"[name]\" could not find its starting location.")
|
|
|
|
if(src.name in SSshuttle.shuttles)
|
|
CRASH("A shuttle with the name '[name]' is already defined.")
|
|
SSshuttle.shuttles[src.name] = src
|
|
if(flags & SHUTTLE_FLAGS_PROCESS)
|
|
SSshuttle.process_shuttles += src
|
|
if(flags & SHUTTLE_FLAGS_SUPPLY)
|
|
if(SScargo.shuttle)
|
|
CRASH("A supply shuttle is already defined.")
|
|
SScargo.shuttle = src
|
|
|
|
/datum/shuttle/Destroy()
|
|
current_location = null
|
|
|
|
SSshuttle.shuttles -= src.name
|
|
SSshuttle.process_shuttles -= src
|
|
if(SScargo.shuttle == src)
|
|
SScargo.shuttle = null
|
|
|
|
. = ..()
|
|
|
|
/datum/shuttle/proc/short_jump(var/obj/effect/shuttle_landmark/destination)
|
|
if(moving_status != SHUTTLE_IDLE) return
|
|
|
|
var/obj/effect/shuttle_landmark/start_location = current_location
|
|
|
|
moving_status = SHUTTLE_WARMUP
|
|
callHook("shuttle_moved", list(start_location,destination))
|
|
if(sound_takeoff)
|
|
playsound(current_location, sound_takeoff, 50, 20, is_global = TRUE)
|
|
spawn(warmup_time*10)
|
|
if(moving_status == SHUTTLE_IDLE)
|
|
return FALSE //someone cancelled the launch
|
|
|
|
if(!fuel_check()) //fuel error (probably out of fuel) occured, so cancel the launch
|
|
var/datum/shuttle/autodock/S = src
|
|
if(istype(S))
|
|
S.cancel_launch(null)
|
|
return
|
|
|
|
moving_status = SHUTTLE_INTRANSIT //shouldn't matter but just to be safe
|
|
attempt_move(destination)
|
|
moving_status = SHUTTLE_IDLE
|
|
|
|
/datum/shuttle/proc/long_jump(var/obj/effect/shuttle_landmark/destination, var/obj/effect/shuttle_landmark/interim, var/travel_time)
|
|
if(moving_status != SHUTTLE_IDLE)
|
|
return
|
|
|
|
var/obj/effect/shuttle_landmark/start_location = current_location
|
|
|
|
moving_status = SHUTTLE_WARMUP
|
|
callHook("shuttle_moved", list(start_location, destination))
|
|
if(sound_takeoff)
|
|
playsound(current_location, sound_takeoff, 100, 20, is_global = TRUE)
|
|
spawn(warmup_time*10)
|
|
if(moving_status == SHUTTLE_IDLE)
|
|
return //someone cancelled the launch
|
|
|
|
if(!fuel_check()) //fuel error (probably out of fuel) occured, so cancel the launch
|
|
var/datum/shuttle/autodock/S = src
|
|
if(istype(S))
|
|
S.cancel_launch(null)
|
|
return
|
|
|
|
arrive_time = world.time + travel_time*10
|
|
moving_status = SHUTTLE_INTRANSIT
|
|
if(attempt_move(interim))
|
|
var/fwooshed = 0
|
|
while (world.time < arrive_time)
|
|
if(!fwooshed && (arrive_time - world.time) < 100)
|
|
fwooshed = 1
|
|
playsound(destination, sound_landing, 100, 20, is_global = TRUE)
|
|
sleep(5)
|
|
if(!attempt_move(destination))
|
|
attempt_move(start_location) //try to go back to where we started. If that fails, I guess we're stuck in the interim location
|
|
|
|
moving_status = SHUTTLE_IDLE
|
|
|
|
/datum/shuttle/proc/fuel_check()
|
|
return 1 //fuel check should always pass in non-overmap shuttles (they have magic engines)
|
|
|
|
/*****************
|
|
* Shuttle Moved Handling * (Observer Pattern Implementation: Shuttle Moved)
|
|
* Shuttle Pre Move Handling * (Observer Pattern Implementation: Shuttle Pre Move)
|
|
*****************/
|
|
|
|
/datum/shuttle/proc/attempt_move(var/obj/effect/shuttle_landmark/destination)
|
|
if(current_location == destination)
|
|
return FALSE
|
|
|
|
if(!destination.is_valid(src))
|
|
return FALSE
|
|
if(current_location.cannot_depart(src))
|
|
return FALSE
|
|
testing("[src] moving to [destination]. Areas are [english_list(shuttle_area)]")
|
|
var/list/translation = list()
|
|
for(var/area/A in shuttle_area)
|
|
testing("Moving [A]")
|
|
translation += get_turf_translation(get_turf(current_location), get_turf(destination), A.contents)
|
|
shuttle_moved(destination, translation)
|
|
destination.shuttle_arrived(src)
|
|
return TRUE
|
|
|
|
//just moves the shuttle from A to B, if it can be moved
|
|
//A note to anyone overriding move in a subtype. shuttle_moved() must absolutely not, under any circumstances, fail to move the shuttle.
|
|
//If you want to conditionally cancel shuttle launches, that logic must go in short_jump(), long_jump() or attempt_move()
|
|
/datum/shuttle/proc/shuttle_moved(var/obj/effect/shuttle_landmark/destination, var/list/turf_translation)
|
|
|
|
// log_debug("move_shuttle() called for [shuttle_tag] leaving [origin] en route to [destination].")
|
|
// log_debug("area_coming_from: [origin]")
|
|
// log_debug("destination: [destination]")
|
|
if((flags & SHUTTLE_FLAGS_ZERO_G))
|
|
var/new_grav = 1
|
|
if(destination.landmark_flags & SLANDMARK_FLAG_ZERO_G)
|
|
var/area/new_area = get_area(destination)
|
|
new_grav = new_area.has_gravity
|
|
for(var/area/our_area in shuttle_area)
|
|
if(our_area.has_gravity != new_grav)
|
|
our_area.gravitychange(new_grav)
|
|
|
|
for(var/turf/src_turf in turf_translation)
|
|
var/turf/dst_turf = turf_translation[src_turf]
|
|
if(squishes && src_turf.is_solid_structure()) //in case someone put a hole in the shuttle and you were lucky enough to be under it
|
|
for(var/atom/movable/AM in dst_turf)
|
|
if(!AM.simulated)
|
|
continue
|
|
if(isliving(AM))
|
|
var/mob/living/bug = AM
|
|
bug.gib()
|
|
else
|
|
qdel(AM) //it just gets atomized I guess? TODO throw it into space somewhere, prevents people from using shuttles as an atom-smasher
|
|
var/list/powernets = list()
|
|
for(var/area/A in shuttle_area)
|
|
// if there was a zlevel above our origin, erase our ceiling now we're leaving
|
|
if(HasAbove(current_location.z))
|
|
for(var/turf/TO in A.contents)
|
|
var/turf/TA = GetAbove(TO)
|
|
if(istype(TA, ceiling_type))
|
|
TA.ChangeTurf(get_base_turf_by_area(TA), 1, 1)
|
|
if(knockdown)
|
|
for(var/mob/M in A)
|
|
spawn(0)
|
|
if(istype(M, /mob/living/carbon))
|
|
if(M.buckled)
|
|
to_chat(M, "<span class='warning'>Sudden acceleration presses you into your chair!</span>")
|
|
shake_camera(M, 3, 1)
|
|
else
|
|
to_chat(M, "<span class='warning'>The floor lurches beneath you!</span>")
|
|
shake_camera(M, 10, 1)
|
|
M.visible_message("<span class='warning'>[M.name] is tossed around by the sudden acceleration!</span>")
|
|
M.throw_at_random(FALSE, 4, 1)
|
|
|
|
for(var/obj/structure/cable/C in A)
|
|
powernets |= C.powernet
|
|
|
|
translate_turfs(turf_translation, current_location.base_area, current_location.base_turf)
|
|
current_location = destination
|
|
|
|
// if there's a zlevel above our destination, paint in a ceiling on it so we retain our air
|
|
if(HasAbove(current_location.z))
|
|
for(var/area/A in shuttle_area)
|
|
for(var/turf/TD in A.contents)
|
|
TD.update_above()
|
|
TD.update_icon()
|
|
var/turf/TA = GetAbove(TD)
|
|
if(istype(TA, get_base_turf_by_area(TA)) || istype(TA, /turf/simulated/open))
|
|
if(get_area(TA) in shuttle_area)
|
|
continue
|
|
TA.ChangeTurf(ceiling_type, TRUE, TRUE, TRUE)
|
|
|
|
for(var/area/sub_area in shuttle_area)
|
|
for(var/obj/structure/shuttle_part/part in sub_area)
|
|
var/turf/target_turf = get_turf(part)
|
|
if(part.outside_part)
|
|
target_turf.ChangeTurf(destination.base_turf)
|
|
for(var/obj/structure/window/shuttle/unique/SW in sub_area)
|
|
if(SW.outside_window)
|
|
var/turf/target_turf = get_turf(SW)
|
|
target_turf.ChangeTurf(destination.base_turf)
|
|
for(var/obj/effect/energy_field/ef in sub_area)
|
|
qdel(ef)
|
|
|
|
// Remove all powernets that were affected, and rebuild them.
|
|
var/list/cables = list()
|
|
for(var/datum/powernet/P in powernets)
|
|
cables |= P.cables
|
|
qdel(P)
|
|
for(var/obj/structure/cable/C in cables)
|
|
if(!C.powernet)
|
|
var/datum/powernet/NewPN = new()
|
|
NewPN.add_cable(C)
|
|
propagate_network(C,C.powernet)
|
|
|
|
if(mothershuttle)
|
|
var/datum/shuttle/mothership = SSshuttle.shuttles[mothershuttle]
|
|
if(mothership)
|
|
if(current_location.landmark_tag == motherdock)
|
|
mothership.shuttle_area |= shuttle_area
|
|
else
|
|
mothership.shuttle_area -= shuttle_area
|
|
|
|
//returns 1 if the shuttle has a valid arrive time
|
|
/datum/shuttle/proc/has_arrive_time()
|
|
return (moving_status == SHUTTLE_INTRANSIT)
|
|
|
|
/datum/shuttle/proc/find_children()
|
|
. = list()
|
|
for(var/shuttle_name in SSshuttle.shuttles)
|
|
var/datum/shuttle/shuttle = SSshuttle.shuttles[shuttle_name]
|
|
if(shuttle.mothershuttle == name)
|
|
. += shuttle
|
|
|
|
//Returns those areas that are not actually child shuttles.
|
|
/datum/shuttle/proc/find_childfree_areas()
|
|
. = shuttle_area.Copy()
|
|
for(var/datum/shuttle/child in find_children())
|
|
. -= child.shuttle_area
|
|
|
|
/datum/shuttle/autodock/proc/get_location_name()
|
|
if(moving_status == SHUTTLE_INTRANSIT)
|
|
return "In transit"
|
|
return current_location.name
|
|
|
|
/datum/shuttle/autodock/proc/get_destination_name()
|
|
if(!next_location)
|
|
return "None"
|
|
return next_location.name
|