mirror of
https://github.com/ParadiseSS13/Paradise.git
synced 2026-07-20 19:44:09 +01:00
Merge branch 'master' of https://github.com/ParadiseSS13/Paradise into ann2
# Conflicts: # code/_globalvars/lists/objects.dm
This commit is contained in:
@@ -91,6 +91,9 @@
|
||||
var/datum/announcement/priority/emergency_shuttle_called = new(0, new_sound = sound('sound/AI/shuttlecalled.ogg'))
|
||||
var/datum/announcement/priority/emergency_shuttle_recalled = new(0, new_sound = sound('sound/AI/shuttlerecalled.ogg'))
|
||||
|
||||
var/canRecall = TRUE //no bad condom, do not recall the crew transfer shuttle!
|
||||
|
||||
|
||||
/obj/docking_port/mobile/emergency/register()
|
||||
if(!..())
|
||||
return 0 //shuttle master not initialized
|
||||
@@ -98,6 +101,16 @@
|
||||
shuttle_master.emergency = src
|
||||
return 1
|
||||
|
||||
/obj/docking_port/mobile/emergency/Destroy(force)
|
||||
if(force)
|
||||
// This'll make the shuttle subsystem use the backup shuttle.
|
||||
if(shuttle_master.emergency == src)
|
||||
// If we're the selected emergency shuttle
|
||||
shuttle_master.emergencyDeregister()
|
||||
|
||||
|
||||
return ..()
|
||||
|
||||
/obj/docking_port/mobile/emergency/timeLeft(divisor)
|
||||
if(divisor <= 0)
|
||||
divisor = 10
|
||||
@@ -138,6 +151,9 @@
|
||||
emergency_shuttle_called.Announce("The emergency shuttle has been called. [redAlert ? "Red Alert state confirmed: Dispatching priority shuttle. " : "" ]It will arrive in [timeLeft(600)] minutes.[reason][shuttle_master.emergencyLastCallLoc ? "\n\nCall signal traced. Results can be viewed on any communications console." : "" ]")
|
||||
|
||||
/obj/docking_port/mobile/emergency/cancel(area/signalOrigin)
|
||||
if(!canRecall)
|
||||
return
|
||||
|
||||
if(mode != SHUTTLE_CALL)
|
||||
return
|
||||
|
||||
@@ -286,3 +302,19 @@
|
||||
var/list/turfs = get_area_turfs(target_area)
|
||||
var/turf/T = pick(turfs)
|
||||
src.loc = T
|
||||
|
||||
/obj/docking_port/mobile/emergency/backup
|
||||
name = "backup shuttle"
|
||||
id = "backup"
|
||||
dwidth = 2
|
||||
width = 8
|
||||
height = 8
|
||||
dir = 4
|
||||
|
||||
roundstart_move = "backup_away"
|
||||
|
||||
/obj/docking_port/mobile/emergency/backup/register()
|
||||
var/current_emergency = shuttle_master.emergency
|
||||
..()
|
||||
shuttle_master.emergency = current_emergency
|
||||
shuttle_master.backup_shuttle = src
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
// Shuttle on-movement //
|
||||
/atom/movable/proc/onShuttleMove(turf/T1, rotation)
|
||||
if(rotation)
|
||||
shuttleRotate(rotation)
|
||||
forceMove(T1)
|
||||
return 1
|
||||
|
||||
/atom/movable/lighting_overlay/onShuttleMove()
|
||||
return 0
|
||||
|
||||
/obj/onShuttleMove()
|
||||
if(invisibility >= 101)
|
||||
return 0
|
||||
. = ..()
|
||||
|
||||
/obj/machinery/door/onShuttleMove()
|
||||
. = ..()
|
||||
if(!.)
|
||||
return
|
||||
addtimer(src, "close", 0, TRUE, 0, 1)
|
||||
// Close any nearby airlocks as well
|
||||
for(var/obj/machinery/door/D in orange(1, src))
|
||||
addtimer(D, "close", 0, TRUE, 0, 1)
|
||||
|
||||
/obj/machinery/door/airlock/onShuttleMove()
|
||||
. = ..()
|
||||
if(id_tag == "s_docking_airlock")
|
||||
addtimer(src, "lock", 0, TRUE)
|
||||
|
||||
/mob/onShuttleMove()
|
||||
if(!move_on_shuttle)
|
||||
return 0
|
||||
. = ..()
|
||||
if(!.)
|
||||
return
|
||||
if(client)
|
||||
if(buckled)
|
||||
shake_camera(src, 2, 1) // turn it down a bit come on
|
||||
else
|
||||
shake_camera(src, 7, 1)
|
||||
|
||||
/mob/living/carbon/onShuttleMove()
|
||||
. = ..()
|
||||
if(!.)
|
||||
return
|
||||
if(!buckled)
|
||||
Weaken(3)
|
||||
|
||||
// After docking //
|
||||
/atom/proc/postDock(obj/docking_port/S1)
|
||||
if(smooth)
|
||||
smooth_icon(src)
|
||||
|
||||
/obj/machinery/door/airlock/postDock(obj/docking_port/stationary/S1)
|
||||
. = ..()
|
||||
if(!S1.lock_shuttle_doors && id_tag == "s_docking_airlock")
|
||||
addtimer(src, "unlock", 0, TRUE)
|
||||
|
||||
// Shuttle Rotation //
|
||||
/atom/proc/shuttleRotate(rotation)
|
||||
//rotate our direction
|
||||
dir = angle2dir(rotation+dir2angle(dir))
|
||||
|
||||
//rotate the pixel offsets too.
|
||||
if(pixel_x || pixel_y)
|
||||
if(rotation < 0)
|
||||
rotation += 360
|
||||
for(var/turntimes=rotation/90;turntimes>0;turntimes--)
|
||||
var/oldPX = pixel_x
|
||||
var/oldPY = pixel_y
|
||||
pixel_x = oldPY
|
||||
pixel_y = (oldPX*(-1))
|
||||
+151
-136
@@ -18,9 +18,18 @@
|
||||
var/dwidth = 0 //position relative to covered area, perpendicular to dir
|
||||
var/dheight = 0 //position relative to covered area, parallel to dir
|
||||
|
||||
// A timid shuttle will not register itself with the shuttle subsystem
|
||||
// All shuttle templates are timid
|
||||
var/timid = FALSE
|
||||
|
||||
//these objects are indestructable
|
||||
/obj/docking_port/Destroy()
|
||||
return QDEL_HINT_LETMELIVE
|
||||
/obj/docking_port/Destroy(force)
|
||||
if(force)
|
||||
..()
|
||||
. = QDEL_HINT_HARDDEL_NOW
|
||||
else
|
||||
|
||||
return QDEL_HINT_LETMELIVE
|
||||
|
||||
/obj/docking_port/singularity_pull()
|
||||
return
|
||||
@@ -212,6 +221,14 @@
|
||||
highlight("#0f0")
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
/obj/docking_port/mobile/initialize()
|
||||
if(!timid)
|
||||
register()
|
||||
..()
|
||||
|
||||
/obj/docking_port/mobile/register()
|
||||
if(!shuttle_master)
|
||||
throw EXCEPTION("docking port [src] could not initialize.")
|
||||
@@ -226,6 +243,13 @@
|
||||
|
||||
return 1
|
||||
|
||||
/obj/docking_port/mobile/Destroy(force)
|
||||
if(force)
|
||||
shuttle_master.mobile -= src
|
||||
areaInstance = null
|
||||
destination = null
|
||||
previous = null
|
||||
return ..()
|
||||
|
||||
//this is a hook for custom behaviour. Maybe at some point we could add checks to see if engines are intact
|
||||
/obj/docking_port/mobile/proc/canMove()
|
||||
@@ -234,29 +258,50 @@
|
||||
//this is to check if this shuttle can physically dock at dock S
|
||||
/obj/docking_port/mobile/proc/canDock(obj/docking_port/stationary/S)
|
||||
if(!istype(S))
|
||||
return 1
|
||||
return SHUTTLE_NOT_A_DOCKING_PORT
|
||||
if(istype(S, /obj/docking_port/stationary/transit))
|
||||
return 0
|
||||
return SHUTTLE_CAN_DOCK
|
||||
//check dock is big enough to contain us
|
||||
if(dwidth > S.dwidth)
|
||||
return 2
|
||||
return SHUTTLE_DWIDTH_TOO_LARGE
|
||||
if(width-dwidth > S.width-S.dwidth)
|
||||
return 3
|
||||
return SHUTTLE_WIDTH_TOO_LARGE
|
||||
if(dheight > S.dheight)
|
||||
return 4
|
||||
return SHUTTLE_DHEIGHT_TOO_LARGE
|
||||
if(height-dheight > S.height-S.dheight)
|
||||
return 5
|
||||
return SHUTTLE_HEIGHT_TOO_LARGE
|
||||
//check the dock isn't occupied
|
||||
if(S.get_docked())
|
||||
return 6
|
||||
return 0 //0 means we can dock
|
||||
var/currently_docked = S.get_docked()
|
||||
if(currently_docked)
|
||||
// by someone other than us
|
||||
if(currently_docked != src)
|
||||
return SHUTTLE_SOMEONE_ELSE_DOCKED
|
||||
else
|
||||
// This isn't an error, per se, but we can't let the shuttle code
|
||||
// attempt to move us where we currently are, it will get weird.
|
||||
return SHUTTLE_ALREADY_DOCKED
|
||||
return SHUTTLE_CAN_DOCK
|
||||
|
||||
/obj/docking_port/mobile/proc/check_dock(obj/docking_port/stationary/S)
|
||||
var/status = canDock(S)
|
||||
if(status == SHUTTLE_CAN_DOCK)
|
||||
return TRUE
|
||||
else if(status == SHUTTLE_ALREADY_DOCKED)
|
||||
// We're already docked there, don't need to do anything.
|
||||
// Triggering shuttle movement code in place is weird
|
||||
return FALSE
|
||||
else
|
||||
var/msg = "check_dock(): shuttle [src] cannot dock at [S], error: [status]"
|
||||
message_admins(msg)
|
||||
throw EXCEPTION(msg)
|
||||
return FALSE
|
||||
|
||||
|
||||
//call the shuttle to destination S
|
||||
/obj/docking_port/mobile/proc/request(obj/docking_port/stationary/S)
|
||||
if(canDock(S))
|
||||
. = 1
|
||||
throw EXCEPTION("request(): shuttle cannot dock")
|
||||
return 1 //we can't dock at S
|
||||
|
||||
if(!check_dock(S))
|
||||
return
|
||||
|
||||
switch(mode)
|
||||
if(SHUTTLE_CALL)
|
||||
@@ -301,36 +346,48 @@
|
||||
else
|
||||
WARNING("shuttle \"[id]\" could not enter transit space. S0=[S0 ? S0.id : "null"] S1=[S1 ? S1.id : "null"]")
|
||||
|
||||
//default shuttleRotate
|
||||
/atom/proc/shuttleRotate(rotation)
|
||||
//rotate our direction
|
||||
dir = angle2dir(rotation+dir2angle(dir))
|
||||
|
||||
//rotate the pixel offsets too.
|
||||
if(pixel_x || pixel_y)
|
||||
if(rotation < 0)
|
||||
rotation += 360
|
||||
for(var/turntimes=rotation/90;turntimes>0;turntimes--)
|
||||
var/oldPX = pixel_x
|
||||
var/oldPY = pixel_y
|
||||
pixel_x = oldPY
|
||||
pixel_y = (oldPX*(-1))
|
||||
|
||||
/atom/proc/postDock()
|
||||
if(smooth)
|
||||
smooth_icon(src)
|
||||
/obj/docking_port/mobile/proc/jumpToNullSpace()
|
||||
// Destroys the docking port and the shuttle contents.
|
||||
// Not in a fancy way, it just ceases.
|
||||
var/obj/docking_port/stationary/S0 = get_docked()
|
||||
var/turf_type = /turf/space
|
||||
var/area_type = /area/space
|
||||
if(S0)
|
||||
if(S0.turf_type)
|
||||
turf_type = S0.turf_type
|
||||
if(S0.area_type)
|
||||
area_type = S0.area_type
|
||||
|
||||
var/list/L0 = return_ordered_turfs(x, y, z, dir, areaInstance)
|
||||
|
||||
//remove area surrounding docking port
|
||||
if(areaInstance.contents.len)
|
||||
var/area/A0 = locate("[area_type]")
|
||||
if(!A0)
|
||||
A0 = new area_type(null)
|
||||
for(var/turf/T0 in L0)
|
||||
A0.contents += T0
|
||||
|
||||
for(var/i in L0)
|
||||
var/turf/T0 = i
|
||||
if(!T0)
|
||||
continue
|
||||
T0.empty(turf_type)
|
||||
|
||||
qdel(src, force=TRUE)
|
||||
|
||||
//this is the main proc. It instantly moves our mobile port to stationary port S1
|
||||
//it handles all the generic behaviour, such as sanity checks, closing doors on the shuttle, stunning mobs, etc
|
||||
/obj/docking_port/mobile/proc/dock(obj/docking_port/stationary/S1)
|
||||
. = canDock(S1)
|
||||
if(.)
|
||||
throw EXCEPTION("dock(): shuttle cannot dock")
|
||||
return .
|
||||
/obj/docking_port/mobile/proc/dock(obj/docking_port/stationary/S1, force=FALSE)
|
||||
// Crashing this ship with NO SURVIVORS
|
||||
if(!force)
|
||||
if(!check_dock(S1))
|
||||
return -1
|
||||
|
||||
if(canMove())
|
||||
return -1
|
||||
if(canMove())
|
||||
return -1
|
||||
|
||||
// //rotate transit docking ports, so we don't need zillions of variants
|
||||
// if(istype(S1, /obj/docking_port/stationary/transit))
|
||||
@@ -367,9 +424,7 @@
|
||||
A0.contents += T0
|
||||
|
||||
//move or squish anything in the way ship at destination
|
||||
roadkill(L1, S1.dir)
|
||||
|
||||
var/list/door_unlock_list = list()
|
||||
roadkill(L0, L1, S1.dir)
|
||||
|
||||
for(var/i in 1 to L0.len)
|
||||
var/turf/T0 = L0[i]
|
||||
@@ -388,49 +443,8 @@
|
||||
Ts1.copy_air_with_tile(T0)
|
||||
|
||||
//move mobile to new location
|
||||
|
||||
|
||||
|
||||
for(var/atom/movable/AM in T0)
|
||||
if(rotation)
|
||||
AM.shuttleRotate(rotation)
|
||||
|
||||
if(istype(AM,/obj))
|
||||
var/obj/O = AM
|
||||
if(istype(O, /obj/docking_port/stationary))
|
||||
continue
|
||||
O.forceMove(T1)
|
||||
|
||||
//close open doors
|
||||
if(istype(O, /obj/machinery/door))
|
||||
var/obj/machinery/door/Door = O
|
||||
spawn(-1)
|
||||
if(Door)
|
||||
if(istype(Door, /obj/machinery/door/airlock))
|
||||
var/obj/machinery/door/airlock/A = Door
|
||||
A.close(0,1)
|
||||
if(A.id_tag == "s_docking_airlock")
|
||||
A.lock()
|
||||
door_unlock_list += A
|
||||
else
|
||||
Door.close()
|
||||
else if(istype(AM,/mob))
|
||||
var/mob/M = AM
|
||||
if(!M.move_on_shuttle)
|
||||
continue
|
||||
M.forceMove(T1)
|
||||
|
||||
//docking turbulence
|
||||
if(M.client)
|
||||
spawn(0)
|
||||
if(M.buckled)
|
||||
shake_camera(M, 2, 1) // turn it down a bit come on
|
||||
else
|
||||
shake_camera(M, 7, 1)
|
||||
if(istype(M, /mob/living/carbon))
|
||||
if(!M.buckled)
|
||||
M.Weaken(3)
|
||||
|
||||
AM.onShuttleMove(T1, rotation)
|
||||
|
||||
if(rotation)
|
||||
T1.shuttleRotate(rotation)
|
||||
@@ -448,40 +462,39 @@
|
||||
|
||||
for(var/A1 in L1)
|
||||
var/turf/T1 = A1
|
||||
T1.postDock()
|
||||
T1.postDock(S1)
|
||||
for(var/atom/movable/M in T1)
|
||||
M.postDock()
|
||||
M.postDock(S1)
|
||||
|
||||
loc = S1.loc
|
||||
dir = S1.dir
|
||||
|
||||
unlockPortDoors(S1)
|
||||
if(S1 && !S1.lock_shuttle_doors)
|
||||
for(var/obj/machinery/door/airlock/A in door_unlock_list)
|
||||
spawn(-1)
|
||||
A.unlock()
|
||||
|
||||
/*
|
||||
if(istype(S1, /obj/docking_port/stationary/transit))
|
||||
var/d = turn(dir, 180 + travelDir)
|
||||
for(var/turf/space/transit/T in S1.return_ordered_turfs())
|
||||
T.pushdirection = d
|
||||
T.update_icon()
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/obj/docking_port/mobile/proc/findTransitDock()
|
||||
var/obj/docking_port/stationary/transit/T = shuttle_master.getDock("[id]_transit")
|
||||
if(T && !canDock(T))
|
||||
if(T && check_dock(T))
|
||||
return T
|
||||
/* commented out due to issues with rotation
|
||||
for(var/obj/docking_port/stationary/transit/S in shuttle_master.transit)
|
||||
if(S.id)
|
||||
continue
|
||||
if(!canDock(S))
|
||||
return S
|
||||
*/
|
||||
|
||||
|
||||
/obj/docking_port/mobile/proc/findRoundstartDock()
|
||||
var/obj/docking_port/stationary/D
|
||||
D = shuttle_master.getDock(roundstart_move)
|
||||
|
||||
if(D)
|
||||
return D
|
||||
|
||||
/obj/docking_port/mobile/proc/dockRoundstart()
|
||||
// Instead of spending a lot of time trying to work out where to place
|
||||
// our shuttle, just create it somewhere empty and send it to where
|
||||
// it should go
|
||||
var/obj/docking_port/stationary/D = findRoundstartDock()
|
||||
return dock(D)
|
||||
|
||||
/obj/effect/landmark/shuttle_import
|
||||
name = "Shuttle Import"
|
||||
|
||||
|
||||
|
||||
//shuttle-door closing is handled in the dock() proc whilst looping through turfs
|
||||
@@ -506,41 +519,43 @@
|
||||
if(A.locked)
|
||||
A.unlock()
|
||||
|
||||
/obj/docking_port/mobile/proc/roadkill(list/L, dir, x, y)
|
||||
for(var/turf/T in L)
|
||||
for(var/atom/movable/AM in T)
|
||||
if(ismob(AM))
|
||||
if(istype(AM, /mob/living))
|
||||
var/mob/living/M = AM
|
||||
M.Paralyse(10)
|
||||
M.take_organ_damage(80)
|
||||
M.anchored = 0
|
||||
else
|
||||
continue
|
||||
/obj/docking_port/mobile/proc/roadkill(list/L0, list/L1, dir)
|
||||
var/list/hurt_mobs = list()
|
||||
for(var/i in 1 to L0.len)
|
||||
var/turf/T0 = L0[i]
|
||||
var/turf/T1 = L1[i]
|
||||
if(!T0 || !T1)
|
||||
continue
|
||||
|
||||
for(var/atom/movable/AM in T1)
|
||||
if(AM.pulledby)
|
||||
AM.pulledby.stop_pulling()
|
||||
if(ismob(AM))
|
||||
var/mob/M = AM
|
||||
if(M.buckled)
|
||||
M.buckled.unbuckle_mob(M, 1)
|
||||
if(isliving(AM))
|
||||
var/mob/living/L = AM
|
||||
L.stop_pulling()
|
||||
if(L.anchored)
|
||||
L.gib()
|
||||
else
|
||||
if(!(L in hurt_mobs))
|
||||
hurt_mobs |= L
|
||||
L.visible_message("<span class='warning'>[L] is hit by \
|
||||
a hyperspace ripple[L.anchored ? "":" and is thrown clear"]!</span>",
|
||||
"<span class='userdanger'>You feel an immense \
|
||||
crushing pressure as the space around you ripples.</span>")
|
||||
L.Paralyse(10)
|
||||
L.ex_act(2)
|
||||
|
||||
// Move unanchored atoms
|
||||
if(!AM.anchored)
|
||||
step(AM, dir)
|
||||
else
|
||||
if(AM.simulated) //lighting overlays are static
|
||||
if(AM.simulated) // Don't qdel lighting overlays, they are static
|
||||
qdel(AM)
|
||||
/*
|
||||
//used to check if atom/A is within the shuttle's bounding box
|
||||
/obj/docking_port/mobile/proc/onShuttleCheck(atom/A)
|
||||
var/turf/T = get_turf(A)
|
||||
if(!T)
|
||||
return 0
|
||||
|
||||
var/list/L = return_coords()
|
||||
if(L[1] > L[3])
|
||||
L.Swap(1,3)
|
||||
if(L[2] > L[4])
|
||||
L.Swap(2,4)
|
||||
|
||||
if(L[1] <= T.x && T.x <= L[3])
|
||||
if(L[2] <= T.y && T.y <= L[4])
|
||||
return 1
|
||||
return 0
|
||||
*/
|
||||
//used by shuttle subsystem to check timers
|
||||
/obj/docking_port/mobile/proc/check()
|
||||
var/timeLeft = timeLeft(1)
|
||||
@@ -667,7 +682,7 @@
|
||||
for(var/obj/docking_port/stationary/S in shuttle_master.stationary)
|
||||
if(!options.Find(S.id))
|
||||
continue
|
||||
if(M.canDock(S))
|
||||
if(!M.check_dock(S))
|
||||
continue
|
||||
destination_found = 1
|
||||
dat += "<A href='?src=[UID()];move=[S.id]'>Send to [S.name]</A><br>"
|
||||
|
||||
@@ -0,0 +1,321 @@
|
||||
|
||||
/obj/machinery/shuttle_manipulator
|
||||
name = "shuttle manipulator"
|
||||
desc = "I shall be telling this with a sigh\n\
|
||||
Somewhere ages and ages hence:\n\
|
||||
Two roads diverged in a wood, and I,\n\
|
||||
I took the one less traveled by,\n\
|
||||
And that has made all the difference."
|
||||
|
||||
icon = 'icons/obj/machines/shuttle_manipulator.dmi'
|
||||
icon_state = "holograph_on"
|
||||
|
||||
var/selected_menu_key = "stat"
|
||||
var/busy
|
||||
// UI state variables
|
||||
var/datum/map_template/shuttle/selected
|
||||
|
||||
var/obj/docking_port/mobile/existing_shuttle
|
||||
|
||||
var/obj/docking_port/mobile/preview_shuttle
|
||||
var/datum/map_template/shuttle/preview_template
|
||||
var/list/templates = list()
|
||||
var/list/shuttle_data = list()
|
||||
|
||||
/obj/machinery/shuttle_manipulator/New()
|
||||
. = ..()
|
||||
update_icon()
|
||||
|
||||
/obj/machinery/shuttle_manipulator/update_icon()
|
||||
overlays.Cut()
|
||||
var/image/hologram_projection = image(icon, "hologram_on")
|
||||
hologram_projection.pixel_y = 22
|
||||
var/image/hologram_ship = image(icon, "hologram_whiteship")
|
||||
hologram_ship.pixel_y = 27
|
||||
overlays += hologram_projection
|
||||
overlays += hologram_ship
|
||||
|
||||
/obj/machinery/shuttle_manipulator/attack_ghost(user as mob)
|
||||
attack_hand(user)
|
||||
|
||||
/proc/shuttlemode2str(mode)
|
||||
switch(mode)
|
||||
if(SHUTTLE_IDLE)
|
||||
. = "idle"
|
||||
if(SHUTTLE_RECALL)
|
||||
. = "recalled"
|
||||
if(SHUTTLE_CALL)
|
||||
. = "called"
|
||||
if(SHUTTLE_DOCKED)
|
||||
. = "docked"
|
||||
if(SHUTTLE_STRANDED)
|
||||
. = "stranded"
|
||||
if(SHUTTLE_ESCAPE)
|
||||
. = "escape"
|
||||
if(!.)
|
||||
throw EXCEPTION("shuttlemode2str(): invalid mode")
|
||||
|
||||
/obj/machinery/shuttle_manipulator/attack_hand(mob/user)
|
||||
ui_interact(user)
|
||||
|
||||
/obj/machinery/shuttle_manipulator/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
|
||||
// update the ui if it exists, returns null if no ui is passed/found
|
||||
ui = nanomanager.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if(!ui)
|
||||
// the ui does not exist, so we'll create a new() one
|
||||
// for a list of parameters and their descriptions see the code docs in \code\modules\nano\nanoui.dm
|
||||
ui = new(user, src, ui_key, "shuttle_manipulator.tmpl", "Shuttle Manipulator", 660, 700, null, null, admin_state)
|
||||
// when the ui is first opened this is the data it will use
|
||||
// open the new ui window
|
||||
ui.open()
|
||||
// auto update every Master Controller tick
|
||||
ui.set_auto_update(1)
|
||||
|
||||
/obj/machinery/shuttle_manipulator/ui_data(mob/user, datum/topic_state/state)
|
||||
var/data[0]
|
||||
data["selectedMenuKey"] = selected_menu_key
|
||||
|
||||
data["templates"] = list()
|
||||
var/list/templates = data["templates"]
|
||||
data["templates_tabs"] = list()
|
||||
data["selected"] = null
|
||||
|
||||
for(var/shuttle_id in shuttle_templates)
|
||||
var/datum/map_template/shuttle/S = shuttle_templates[shuttle_id]
|
||||
|
||||
if(!templates[S.port_id])
|
||||
data["templates_tabs"] += S.port_id
|
||||
// The first found shuttle type will be our default
|
||||
if(!existing_shuttle)
|
||||
existing_shuttle = shuttle_master.getShuttle(S.port_id)
|
||||
templates[S.port_id] = list(
|
||||
"port_id" = S.port_id,
|
||||
"templates" = list()
|
||||
)
|
||||
|
||||
var/list/L = list()
|
||||
L["name"] = S.name
|
||||
L["shuttle_id"] = S.shuttle_id
|
||||
L["port_id"] = S.port_id
|
||||
L["description"] = S.description
|
||||
L["admin_notes"] = S.admin_notes
|
||||
|
||||
if(selected == S)
|
||||
data["selected"] = L
|
||||
|
||||
templates[S.port_id]["templates"] += list(L)
|
||||
|
||||
data["templates_tabs"] = sortList(data["templates_tabs"])
|
||||
|
||||
data["existing_shuttle"] = null
|
||||
|
||||
// Status panel
|
||||
data["shuttles"] = list()
|
||||
for(var/i in shuttle_master.mobile)
|
||||
var/obj/docking_port/mobile/M = i
|
||||
var/list/L = list()
|
||||
L["name"] = M.name
|
||||
L["id"] = M.id
|
||||
L["timer"] = M.timer
|
||||
L["timeleft"] = M.getTimerStr()
|
||||
var/can_fast_travel = FALSE
|
||||
if(M.timer && M.timeLeft() >= 50)
|
||||
can_fast_travel = TRUE
|
||||
L["can_fast_travel"] = can_fast_travel
|
||||
L["mode"] = capitalize(shuttlemode2str(M.mode))
|
||||
L["status"] = M.getStatusText()
|
||||
if(M == existing_shuttle)
|
||||
data["existing_shuttle"] = L
|
||||
|
||||
data["shuttles"] += list(L)
|
||||
return data
|
||||
|
||||
/obj/machinery/shuttle_manipulator/Topic(href, href_list)
|
||||
if(..())
|
||||
return
|
||||
|
||||
var/mob/user = usr
|
||||
|
||||
// Preload some common parameters
|
||||
var/shuttle_id = href_list["shuttle_id"]
|
||||
var/datum/map_template/shuttle/S = shuttle_templates[shuttle_id]
|
||||
|
||||
|
||||
if(href_list["selectMenuKey"])
|
||||
selected_menu_key = href_list["selectMenuKey"]
|
||||
return 1 // return 1 forces an update to all Nano uis attached to src
|
||||
|
||||
if(href_list["select_template_category"])
|
||||
var/chosen_shuttle_id = href_list["select_template_category"]
|
||||
selected = null
|
||||
existing_shuttle = shuttle_master.getShuttle(chosen_shuttle_id)
|
||||
return 1
|
||||
|
||||
if(href_list["select_template"])
|
||||
if(S)
|
||||
existing_shuttle = shuttle_master.getShuttle(S.port_id)
|
||||
selected = S
|
||||
. = TRUE
|
||||
|
||||
if(href_list["jump_to"])
|
||||
|
||||
if(href_list["type"] == "mobile")
|
||||
for(var/i in shuttle_master.mobile)
|
||||
var/obj/docking_port/mobile/M = i
|
||||
if(M.id == href_list["id"])
|
||||
user.forceMove(get_turf(M))
|
||||
. = TRUE
|
||||
break
|
||||
|
||||
|
||||
if(href_list["fast_travel"])
|
||||
|
||||
for(var/i in shuttle_master.mobile)
|
||||
var/obj/docking_port/mobile/M = i
|
||||
if(M.id == href_list["id"] && M.timer && M.timeLeft() >= 50)
|
||||
M.setTimer(50)
|
||||
. = TRUE
|
||||
message_admins("[key_name_admin(usr)] fast travelled \
|
||||
[M]")
|
||||
log_admin("[key_name(usr)] fast travelled [M]")
|
||||
feedback_add_details("shuttle_fasttravel", M.name)
|
||||
break
|
||||
|
||||
|
||||
if(href_list["preview"])
|
||||
if(S)
|
||||
. = TRUE
|
||||
unload_preview()
|
||||
load_template(S)
|
||||
if(preview_shuttle)
|
||||
preview_template = S
|
||||
user.forceMove(get_turf(preview_shuttle))
|
||||
|
||||
if(href_list["load"])
|
||||
if(existing_shuttle == shuttle_master.backup_shuttle)
|
||||
// TODO make the load button disabled
|
||||
WARNING("The shuttle that the selected shuttle will replace \
|
||||
is the backup shuttle. Backup shuttle is required to be \
|
||||
intact for round sanity.")
|
||||
else if(S)
|
||||
. = TRUE
|
||||
// If successful, returns the mobile docking port
|
||||
var/obj/docking_port/mobile/mdp = action_load(S)
|
||||
if(mdp)
|
||||
user.forceMove(get_turf(mdp))
|
||||
message_admins("[key_name_admin(usr)] loaded [mdp] \
|
||||
with the shuttle manipulator.")
|
||||
log_admin("[key_name(usr)] loaded [mdp] with the \
|
||||
shuttle manipulator.</span>")
|
||||
feedback_add_details("shuttle_manipulator", mdp.name)
|
||||
|
||||
|
||||
/obj/machinery/shuttle_manipulator/proc/action_load(datum/map_template/shuttle/loading_template)
|
||||
// Check for an existing preview
|
||||
if(preview_shuttle && (loading_template != preview_template))
|
||||
preview_shuttle.jumpToNullSpace()
|
||||
preview_shuttle = null
|
||||
preview_template = null
|
||||
|
||||
if(!preview_shuttle)
|
||||
load_template(loading_template)
|
||||
preview_template = loading_template
|
||||
|
||||
// get the existing shuttle information, if any
|
||||
var/timer = 0
|
||||
var/mode = SHUTTLE_IDLE
|
||||
var/obj/docking_port/stationary/D
|
||||
|
||||
if(existing_shuttle)
|
||||
timer = existing_shuttle.timer
|
||||
mode = existing_shuttle.mode
|
||||
D = existing_shuttle.get_docked()
|
||||
else
|
||||
D = preview_shuttle.findRoundstartDock()
|
||||
|
||||
if(!D)
|
||||
var/m = "No dock found for preview shuttle, aborting."
|
||||
WARNING(m)
|
||||
throw EXCEPTION(m)
|
||||
|
||||
var/result = preview_shuttle.canDock(D)
|
||||
// truthy value means that it cannot dock for some reason
|
||||
// but we can ignore the someone else docked error because we'll
|
||||
// be moving into their place shortly
|
||||
if((result != SHUTTLE_CAN_DOCK) && (result != SHUTTLE_SOMEONE_ELSE_DOCKED))
|
||||
|
||||
var/m = "Unsuccessful dock of [preview_shuttle] ([result])."
|
||||
message_admins("[m]")
|
||||
WARNING(m)
|
||||
return
|
||||
|
||||
existing_shuttle.jumpToNullSpace()
|
||||
|
||||
preview_shuttle.dock(D)
|
||||
. = preview_shuttle
|
||||
|
||||
// Shuttle state involves a mode and a timer based on world.time, so
|
||||
// plugging the existing shuttles old values in works fine.
|
||||
preview_shuttle.timer = timer
|
||||
preview_shuttle.mode = mode
|
||||
|
||||
preview_shuttle.register()
|
||||
|
||||
// TODO indicate to the user that success happened, rather than just
|
||||
// blanking the modification tab
|
||||
existing_shuttle = null
|
||||
preview_shuttle = null
|
||||
preview_template = null
|
||||
selected = null
|
||||
|
||||
return preview_shuttle
|
||||
|
||||
/obj/machinery/shuttle_manipulator/proc/load_template(datum/map_template/shuttle/S)
|
||||
// load shuttle template, centred at shuttle import landmark,
|
||||
var/turf/landmark_turf = get_turf(locate("landmark*Shuttle Import"))
|
||||
S.load(landmark_turf, centered = TRUE)
|
||||
|
||||
var/affected = S.get_affected_turfs(landmark_turf, centered=TRUE)
|
||||
|
||||
var/found = 0
|
||||
// Search the turfs for docking ports
|
||||
// - We need to find the mobile docking port because that is the heart of
|
||||
// the shuttle.
|
||||
// - We need to check that no additional ports have slipped in from the
|
||||
// template, because that causes unintended behaviour.
|
||||
for(var/T in affected)
|
||||
for(var/obj/docking_port/P in T)
|
||||
if(istype(P, /obj/docking_port/mobile))
|
||||
var/obj/docking_port/mobile/M = P
|
||||
found++
|
||||
if(found > 1)
|
||||
qdel(P, force=TRUE)
|
||||
world.log << "Map warning: Shuttle Template [S.mappath] \
|
||||
has multiple mobile docking ports."
|
||||
else if(!M.timid)
|
||||
// The shuttle template we loaded isn't "timid" which means
|
||||
// it's already registered with the shuttles subsystem.
|
||||
// This is a bad thing.
|
||||
var/m = "Template [S] is non-timid! Unloading."
|
||||
WARNING(m)
|
||||
M.jumpToNullSpace()
|
||||
return
|
||||
else
|
||||
preview_shuttle = P
|
||||
if(istype(P, /obj/docking_port/stationary))
|
||||
world.log << "Map warning: Shuttle Template [S.mappath] has a \
|
||||
stationary docking port."
|
||||
if(!found)
|
||||
var/msg = "load_template(): Shuttle Template [S.mappath] has no \
|
||||
mobile docking port. Aborting import."
|
||||
for(var/T in affected)//wot do?
|
||||
var/turf/T0 = T
|
||||
T0.contents = null
|
||||
|
||||
message_admins(msg)
|
||||
WARNING(msg)
|
||||
|
||||
/obj/machinery/shuttle_manipulator/proc/unload_preview()
|
||||
if(preview_shuttle)
|
||||
preview_shuttle.jumpToNullSpace()
|
||||
preview_shuttle = null
|
||||
@@ -631,11 +631,11 @@
|
||||
data["can_launch"] = !shuttle_master.supply.canMove()
|
||||
return data
|
||||
|
||||
/obj/machinery/computer/supplycomp/proc/is_authorized(user)
|
||||
/obj/machinery/computer/supplycomp/proc/is_authorized(mob/user)
|
||||
if(allowed(user))
|
||||
return 1
|
||||
|
||||
if(isobserver(user) && check_rights(R_ADMIN, 0))
|
||||
if(user.can_admin_interact())
|
||||
return 1
|
||||
|
||||
return 0
|
||||
|
||||
Reference in New Issue
Block a user