mirror of
https://github.com/vgstation-coders/vgstation13.git
synced 2025-12-10 10:21:11 +00:00
modify all the maps, replace restaurant with icecream truck add rewards to ice cream truck and satelite, defines fix maps remove cursed satelite of doom Add hivebot factory to replace haunted satelite. Fix minimaps for good maploader lighting woops Adds clown base remove exclamation marks nerd Adds a ruined R-UST vault. Remove vaults from z1, fix hivebot factory
814 lines
27 KiB
Plaintext
814 lines
27 KiB
Plaintext
#define NO_TRANSIT 0 //Don't use transit areas
|
|
#define TRANSIT_ACROSS_Z_LEVELS 1 //Only use transit areas if moving to another z-level
|
|
#define TRANSIT_ALWAYS 2 //Always use transit areas
|
|
|
|
//Whether this shuttle can be linked to a shuttle control console.
|
|
#define LINK_FREE 0
|
|
#define LINK_PASSWORD_ONLY 1
|
|
#define LINK_FORBIDDEN 2
|
|
|
|
//Whether the shuttle destroys stuff it collides with, or displaces it
|
|
#define COLLISION_DESTROY 0
|
|
#define COLLISION_DISPLACE 1 //this is same as COLLISION_DISPLACE as for now
|
|
|
|
//One of these values is returned at initialize()
|
|
#define INIT_SUCCESS 1 //everything is good
|
|
#define INIT_NO_AREA 2 //can't find starting area
|
|
#define INIT_NO_PORT 3 //can't find shuttle's docking port
|
|
#define INIT_NO_START 4 //shuttle's docking port isn't connected to a destination port
|
|
|
|
/datum/shuttle
|
|
var/name = "shuttle"
|
|
|
|
//List of ALL docking ports the shuttle can move to
|
|
var/list/docking_ports = list()
|
|
|
|
//The shuttle's main area - it contains the linked_port
|
|
var/area/linked_area
|
|
|
|
//The shuttle's linked shuttle docking port - essential
|
|
var/obj/structure/docking_port/shuttle/linked_port
|
|
|
|
//The shuttle's current location
|
|
var/obj/structure/docking_port/destination/current_port
|
|
|
|
//The shuttle's transit location
|
|
var/obj/structure/docking_port/destination/transit_port
|
|
|
|
//The shuttle's destination
|
|
var/obj/structure/docking_port/destination/destination_port
|
|
|
|
//List of ALL docking ports on the shuttle. Setup at initialize(), the shuttle can only move docking ports in this list
|
|
//(which means those which are placed in the shuttle's area on the map). This exists to prevent shuttles from moving on top
|
|
//of another docking port and then moving it away
|
|
var/list/docking_ports_aboard = list()
|
|
|
|
var/use_transit = TRANSIT_ACROSS_Z_LEVELS
|
|
|
|
var/dir = NORTH
|
|
|
|
var/can_rotate = 1
|
|
|
|
//This is the time it takes for the shuttle to depart (if there's a transit area) or to travel (if there are no transit areas)
|
|
var/pre_flight_delay = 50
|
|
|
|
//If there is a transit port, this is the time the shuttle spends in it
|
|
//If there isn't a transit port, this has no effect. Use the pre_flight_delay var instead
|
|
var/transit_delay = 100
|
|
|
|
//If the shuttle is currently moving
|
|
var/moving = 0
|
|
|
|
var/list/cant_leave_zlevel = list(
|
|
/obj/item/weapon/disk/nuclear = "The nuclear authentication disk can't be transported on a shuttle.",
|
|
)
|
|
|
|
//This list is transferred to all linked shuttle control consoles
|
|
var/list/req_access = list()
|
|
|
|
var/last_moved = 0
|
|
var/cooldown = 100
|
|
|
|
//When the shuttle moves, coordinates of its final location will be offset by rand(-innacuracy, innacuracy)
|
|
var/innacuracy = 0
|
|
|
|
//When the shuttle moves, if stable is 0 then all unbuckled mobs will be stunned
|
|
var/stable = 0
|
|
|
|
var/password = 28011
|
|
var/can_link_to_computer = LINK_FORBIDDEN
|
|
|
|
//Whether the shuttle gibs or displaces stuff. Change this to COLLISION_DISPLACE to make all shuttles displace stuff by default
|
|
var/collision_type = COLLISION_DESTROY
|
|
|
|
var/list/control_consoles = list()
|
|
|
|
var/lockdown = 0
|
|
|
|
var/destroy_everything = 0
|
|
|
|
/datum/shuttle/New(var/area/starting_area)
|
|
.=..()
|
|
|
|
if(starting_area)
|
|
if(ispath(starting_area))
|
|
linked_area = locate(starting_area)
|
|
else if(isarea(starting_area))
|
|
linked_area = starting_area
|
|
else
|
|
linked_area = starting_area
|
|
warning("Unable to find area [starting_area] in world - [src.type] ([src.name]) won't be able to function properly.")
|
|
|
|
if(istype(linked_area) && linked_area.contents.len) //Only add the shuttle to the list if its area exists and it has something in it
|
|
shuttles |= src
|
|
|
|
password = rand(10000,99999)
|
|
|
|
//initialize() proc - called automatically in proc/setup_shuttles() below.
|
|
//Returns INIT_SUCCESS, INIT_NO_AREA, INIT_NO_START or INIT_NO_PORT, depending on whether there were any errors
|
|
/datum/shuttle/proc/initialize()
|
|
. = INIT_SUCCESS
|
|
src.docking_ports = list()
|
|
src.docking_ports_aboard = list()
|
|
src.transit_port = null
|
|
|
|
if(!linked_area || !istype(linked_area))
|
|
//No linked area - the shuttle doesn't exist (very bad)
|
|
return INIT_NO_AREA
|
|
|
|
//This line below used to cause weird bugs with some maps (https://github.com/d3athrow/vgstation13/issues/6773)
|
|
|
|
//var/obj/structure/docking_port/shuttle/shuttle_docking_port = locate() in linked_area.contents.Copy()
|
|
|
|
//I have no idea what was causing it, but after replacing it with the following five lines everything started working as intended
|
|
var/obj/structure/docking_port/shuttle/shuttle_docking_port
|
|
|
|
for(var/obj/structure/docking_port/shuttle/S in linked_area)
|
|
shuttle_docking_port = S
|
|
break
|
|
//
|
|
|
|
if(shuttle_docking_port)
|
|
//In case this shuttle already has a shuttle docking port, unlink it
|
|
if(linked_port)
|
|
linked_port.unlink_from_shuttle(src)
|
|
|
|
shuttle_docking_port.link_to_shuttle(src)
|
|
|
|
//The following few lines ensure that if there's a docking port at the shuttle's starting location, the shuttle is docked to it
|
|
var/turf/check_turf = shuttle_docking_port.get_docking_turf()
|
|
if(check_turf)
|
|
for(var/obj/structure/docking_port/P in check_turf.contents)
|
|
shuttle_docking_port.dock(P)
|
|
src.current_port = shuttle_docking_port.docked_with
|
|
break
|
|
|
|
if(!src.current_port)
|
|
//This isn't really a problem, but if the shuttle moves somewhere it won't be able to return to its starting location
|
|
. = INIT_NO_START
|
|
|
|
src.dir = turn(linked_port.dir, 180)
|
|
else
|
|
//No docking port - the shuttle can't be moved (bad but fixable with admin intervention)
|
|
. = INIT_NO_PORT
|
|
|
|
|
|
for(var/obj/structure/docking_port/D in linked_area)
|
|
docking_ports_aboard |= D
|
|
|
|
return
|
|
|
|
/datum/shuttle/Destroy()
|
|
shuttles -= src
|
|
..()
|
|
|
|
/datum/shuttle/proc/get_transit_delay()
|
|
return transit_delay
|
|
|
|
/datum/shuttle/proc/get_pre_flight_delay()
|
|
return pre_flight_delay
|
|
|
|
/datum/shuttle/proc/get_cooldown()
|
|
return cooldown
|
|
|
|
//Shuttles like the emergency shuttle (which moves to pre-defined locations) and vox shuttle (which ends the round once moved to a pre-defined location)
|
|
//should have this proc return 1, so they can't be deleted.
|
|
/datum/shuttle/proc/is_special()
|
|
return 0
|
|
|
|
//Adds a docking port to list of travel destinations, accepts path or the port itself
|
|
/datum/shuttle/proc/add_dock(var/D)
|
|
if(ispath(D))
|
|
for(var/obj/structure/docking_port/destination/dock in all_docking_ports)
|
|
if(istype(dock,D))
|
|
dock.link_to_shuttle(src)
|
|
return dock
|
|
else if(istype(D,/obj/structure/docking_port/destination))
|
|
var/obj/structure/docking_port/destination/dock = D
|
|
dock.link_to_shuttle(src)
|
|
return dock
|
|
|
|
return D
|
|
|
|
//Adds a docking port as a transit area, accepts path or the port itself
|
|
/datum/shuttle/proc/set_transit_dock(var/D)
|
|
if(ispath(D))
|
|
for(var/obj/structure/docking_port/destination/dock in all_docking_ports)
|
|
if(istype(dock,D))
|
|
transit_port = dock
|
|
return dock
|
|
else if(istype(D,/obj/structure/docking_port/destination))
|
|
transit_port = D
|
|
return D
|
|
|
|
/datum/shuttle/proc/can_move()
|
|
if(lockdown)
|
|
return 0
|
|
if(last_moved + cooldown < world.time)
|
|
return 1
|
|
|
|
//Checks the shuttle for any offending atoms
|
|
/datum/shuttle/proc/forbid_movement()
|
|
var/atom/A = linked_area.contains_atom_from_list(cant_leave_zlevel) //code/game/atoms.dm, 243
|
|
if(A)
|
|
return A
|
|
return 0
|
|
|
|
//This is the proc you generally want to use when moving a shuttle. Runs all sorts of checks (cooldown, if already moving, etc)
|
|
//If you want to bypass it, set destination_port to something and call pre_flight()
|
|
//Alternatively, call move_to_dock(destination)
|
|
/datum/shuttle/proc/travel_to(var/obj/structure/docking_port/D, var/obj/machinery/computer/shuttle_control/broadcast = null, var/mob/user)
|
|
if(!D) return 0 //no docking port
|
|
if(!linked_port) return 0 //no shuttle port
|
|
|
|
if(destination_port)
|
|
if(broadcast)
|
|
broadcast.announce( "The shuttle is currently in process of moving." )
|
|
else if(user)
|
|
to_chat(user, "The shuttle is currently moving")
|
|
return 0 //shuttle already travelling
|
|
|
|
if(lockdown)
|
|
if(broadcast)
|
|
broadcast.announce( "This shuttle is locked down." )
|
|
else if(user)
|
|
to_chat(user, "The shuttle can't move (locked down)")
|
|
return 0
|
|
|
|
if(!can_move())
|
|
if(broadcast)
|
|
broadcast.announce( "The engines are still cooling down from the previous trip." )
|
|
else if(user)
|
|
to_chat(user, "The shuttle can't move (on cooldown)")
|
|
return 0
|
|
|
|
if(D.docked_with)
|
|
if(broadcast)
|
|
broadcast.announce( "[capitalize(D.areaname)] is currently used by another shuttle. Please wait until the docking port is free, or select another destination." )
|
|
else if(user)
|
|
to_chat(user, "The shuttle can't move ([D.areaname] is used by another shuttle)")
|
|
return 0
|
|
|
|
//Handle the message
|
|
var/time = "as soon as possible"
|
|
switch(pre_flight_delay)
|
|
if(0)
|
|
time = "immediately"
|
|
if(1 to 30)
|
|
time = "in a few seconds"
|
|
if(31 to 50)
|
|
time = "shortly"
|
|
if(51 to 80)
|
|
time = "after a short delay"
|
|
if(81 to INFINITY)
|
|
time = "in [max(round((pre_flight_delay) / 10, 1), 0)] seconds"
|
|
if(broadcast)
|
|
broadcast.announce("The shuttle has received your message and will be sent [time].")
|
|
|
|
//If moving to another zlevel, check for items which can't leave the zlevel (nuke disk, primarily)
|
|
if(linked_port.z != D.z)
|
|
var/atom/A = forbid_movement()
|
|
if( A )
|
|
if(cant_leave_zlevel[A.type])
|
|
if(broadcast)
|
|
broadcast.announce("ERROR: [cant_leave_zlevel[A.type]]")
|
|
else if(user)
|
|
to_chat(user, cant_leave_zlevel[A.type])
|
|
return 0
|
|
else
|
|
if(broadcast)
|
|
broadcast.announce("ERROR: [A.name] is preventing the shuttle from departing.")
|
|
else if(user)
|
|
to_chat(user, "[A.name] is preventing the shuttle from departing.")
|
|
return 0
|
|
|
|
destination_port = D
|
|
last_moved = world.time
|
|
moving = 1
|
|
|
|
log_game("[usr ? key_name(usr) : "Something"] sent [name] ([type]) to [D.areaname]")
|
|
|
|
spawn(get_pre_flight_delay())
|
|
if(transit_port && get_transit_delay())
|
|
if(broadcast)
|
|
broadcast.announce( "The shuttle has departed and is now moving towards [D.areaname]." )
|
|
else if(user)
|
|
to_chat(user, "The shuttle has departed towards [D.areaname]")
|
|
else
|
|
if(broadcast)
|
|
broadcast.announce( "The shuttle has arrived at [D.areaname]." )
|
|
else if(user)
|
|
to_chat(user, "The shuttle has arrived at [D.areaname]")
|
|
|
|
pre_flight()
|
|
|
|
return 1
|
|
|
|
/datum/shuttle/proc/pre_flight()
|
|
if(!destination_port) return
|
|
|
|
if(transit_port && get_transit_delay())
|
|
if(use_transit == TRANSIT_ALWAYS || (use_transit == TRANSIT_ACROSS_Z_LEVELS && (linked_area.z != destination_port.z)))
|
|
move_to_dock(transit_port)
|
|
sleep(get_transit_delay())
|
|
|
|
if(destination_port)
|
|
move_to_dock(destination_port)
|
|
destination_port = null
|
|
|
|
moving = 0
|
|
|
|
//This is the proc you want to use to FORCE a shuttle to move. It always moves it, unless the shuttle or its area don't exist. Transit is skipped, after_flight() is called
|
|
/datum/shuttle/proc/move_to_dock(var/obj/structure/docking_port/D, var/ignore_innacuracy = 0) //A direct proc with no bullshit
|
|
if(!D) return
|
|
if(!linked_port) return
|
|
|
|
//List of all shuttles docked to this shuttle. They will be moved together with their parent.
|
|
//In the list, shuttles are associated with the docking port they are docked to
|
|
var/list/docked_shuttles = list()
|
|
|
|
//To prevent two shuttles that are docked to each other from potentially breaking everything, all moved shuttles are added to this list
|
|
var/list/moved_shuttles = list()
|
|
|
|
moved_shuttles += src
|
|
|
|
//See all destination ports in current area
|
|
for(var/obj/structure/docking_port/destination/dock in linked_area)
|
|
//If somebody is docked to it (and it isn't us (that would be weird but better be sure))
|
|
if(dock.docked_with && !(dock.docked_with == linked_port))
|
|
//Get the docking port that's docked to it, and then its shuttle
|
|
var/obj/structure/docking_port/shuttle/S = dock.docked_with
|
|
if(!S || !S.linked_shuttle) continue
|
|
|
|
docked_shuttles |= S.linked_shuttle
|
|
docked_shuttles[S.linked_shuttle]=dock
|
|
|
|
//******Handle rotation*********
|
|
var/rotate = 0
|
|
if(src.can_rotate)
|
|
|
|
if(linked_port.dir != turn(D.dir,180))
|
|
|
|
rotate = dir2angle(turn(D.dir,180)) - dir2angle(linked_port.dir)
|
|
|
|
if(rotate < 0)
|
|
rotate += 360
|
|
else if(rotate >= 360)
|
|
rotate -= 360
|
|
|
|
//******Get the turf to move to**
|
|
var/turf/target_turf = D.get_docking_turf()
|
|
|
|
if(!ignore_innacuracy && innacuracy) //Handle innacuracy
|
|
var/list/turf_list = list()
|
|
|
|
for(var/turf/T in orange(innacuracy,D.get_docking_turf()))
|
|
turf_list|=T
|
|
|
|
target_turf = pick(turf_list)
|
|
|
|
//****Finally, move the area***
|
|
if(move_area_to(get_turf(linked_port), target_turf, rotate))
|
|
|
|
linked_port.dock(D) //Dock our docking port with the destination
|
|
|
|
//****Move shuttles docked to us**
|
|
if(docked_shuttles.len)
|
|
for(var/datum/shuttle/S in docked_shuttles)
|
|
if(S in moved_shuttles) continue
|
|
var/obj/structure/docking_port/destination/our_moved_dock = docked_shuttles[S]
|
|
if(!our_moved_dock) continue
|
|
|
|
moved_shuttles |= S
|
|
S.move_to_dock(our_moved_dock, ignore_innacuracy = 1)
|
|
|
|
log_game("[name] ([type]) moved to [D.areaname]")
|
|
|
|
current_port = D
|
|
|
|
after_flight() //Shake the shuttle, weaken unbuckled mobs, etc.
|
|
|
|
return 1
|
|
|
|
return
|
|
|
|
/datum/shuttle/proc/close_all_doors()
|
|
for(var/obj/machinery/door/unpowered/shuttle/D in linked_area)
|
|
spawn(0)
|
|
D.close()
|
|
|
|
/datum/shuttle/proc/open_all_doors()
|
|
for(var/obj/machinery/door/unpowered/shuttle/D in linked_area)
|
|
spawn(0)
|
|
D.open()
|
|
|
|
//Shakes cameras for mobs
|
|
/datum/shuttle/proc/after_flight()
|
|
for(var/atom/movable/AM in linked_area)
|
|
if(AM.anchored) continue
|
|
|
|
if(istype(AM,/mob/living))
|
|
var/mob/living/M = AM
|
|
|
|
if(!M.locked_to)
|
|
shake_camera(M, 10, 1) // unbuckled, HOLY SHIT SHAKE THE ROOM
|
|
|
|
if(!src.stable)
|
|
if(istype(M, /mob/living/carbon))
|
|
M.Weaken(3)
|
|
else
|
|
shake_camera(M, 3, 1) // buckled, not a lot of shaking
|
|
|
|
//Gibs or moves mobs and stuff
|
|
/datum/shuttle/proc/collide(var/atom/movable/AM as mob|obj)
|
|
AM.shuttle_act(src)
|
|
|
|
//This is awful
|
|
/datum/shuttle/proc/supercharge()
|
|
cooldown = 0
|
|
pre_flight_delay = 0
|
|
transit_delay = 0
|
|
|
|
//Like (input() in shuttles), but better
|
|
/proc/select_shuttle_from_all(var/mob/user, var/message = "Select a shuttle", var/title = "Shuttle selection", var/list/omit_shuttles = null, var/show_lockdown = 0, var/show_cooldown = 0)
|
|
if(!user) return
|
|
|
|
var/list/shuttle_list = list()
|
|
for(var/datum/shuttle/S in shuttles)
|
|
if(omit_shuttles)
|
|
if(S.type in omit_shuttles) continue
|
|
if(S in omit_shuttles) continue
|
|
if(S.name in omit_shuttles) continue
|
|
var/name = S.name
|
|
if(show_lockdown && S.lockdown)
|
|
name = "[name] (LOCKDOWN)"
|
|
else
|
|
if(show_cooldown && !S.can_move())
|
|
name = "[name] (ON COOLDOWN)"
|
|
shuttle_list += name
|
|
shuttle_list[name]=S
|
|
|
|
var/my_shuttle = input(usr, message, title) in shuttle_list as text|null
|
|
|
|
if( my_shuttle && shuttle_list[my_shuttle] && istype(shuttle_list[my_shuttle], /datum/shuttle) )
|
|
return shuttle_list[my_shuttle]
|
|
|
|
/datum/shuttle/proc/move(var/mob/user) //a very simple proc which selects a random area and sends the shuttle there
|
|
var/list/possible_locations = list()
|
|
for(var/obj/structure/docking_port/destination/S in src.docking_ports)
|
|
if(S == current_port) continue
|
|
if(S.docked_with) continue
|
|
|
|
possible_locations += S
|
|
|
|
if(!possible_locations.len) return
|
|
var/obj/structure/docking_port/destination/target = pick(possible_locations)
|
|
|
|
travel_to(target,,user)
|
|
|
|
//The proc that does most of the work
|
|
//RETURNS: 1 if everything is good, 0 if everything is bad
|
|
/datum/shuttle/proc/move_area_to(var/turf/our_center, var/turf/new_center, var/rotate = 0)
|
|
if(!our_center) return
|
|
if(!new_center) return
|
|
if((rotate % 90) != 0) //If not divisible by 90, make it
|
|
rotate += (rotate % 90)
|
|
|
|
var/datum/coords/our_center_coords = new(our_center.x,our_center.y)
|
|
var/datum/coords/new_center_coords = new(new_center.x,new_center.y)
|
|
|
|
var/datum/coords/offset = new_center_coords.subtract(our_center_coords)
|
|
|
|
//For displacing
|
|
var/throwy = world.maxy
|
|
|
|
var/area/space
|
|
|
|
space = get_space_area
|
|
if(!space)
|
|
warning("There is no area at 1,1,2!")
|
|
|
|
//Make a list of coordinates of turfs to move, and associate the coordinates with the turfs they represent
|
|
var/list/turfs_to_move = list()
|
|
|
|
//Now here's the dumb part - since there's no fast way I know to check if a coord datum has a coord datum with the same values in a list,
|
|
//this coordinates list stores every coordinate of a moved turf as a string (example: "52;61").
|
|
var/list/our_own_turfs = list()
|
|
|
|
//Go through all turfs in our area
|
|
for(var/turf/T in linked_area.get_turfs())
|
|
var/datum/coords/C = new(T.x,T.y)
|
|
turfs_to_move += C
|
|
turfs_to_move[C] = T
|
|
|
|
our_own_turfs += "[T.x];[T.y];[T.z]"
|
|
|
|
var/cosine = cos(rotate)
|
|
var/sine = sin(rotate)
|
|
|
|
//Calculate new coordinates
|
|
var/list/new_turfs = list() //Coordinates of turfs that WILL be created
|
|
for(var/datum/coords/C in turfs_to_move)
|
|
var/datum/coords/new_coords = C.add(offset) //Get the coordinates of new turfs by adding offset
|
|
|
|
new_turfs += new_coords
|
|
new_turfs[new_coords] = C //Associate the old coordinates with the new ones for an easier time
|
|
|
|
if(rotate != 0)
|
|
//Oh god this works
|
|
|
|
var/newX = (cosine * (new_coords.x_pos - new_center.x)) + (sine * (new_coords.y_pos - new_center.y)) + new_center.x
|
|
var/newY = -(sine * (new_coords.x_pos - new_center.x)) + (cosine * (new_coords.y_pos - new_center.y)) + new_center.y
|
|
|
|
new_coords.x_pos = newX
|
|
new_coords.y_pos = newY
|
|
|
|
if(new_coords.y_pos < throwy)
|
|
throwy = new_coords.y_pos
|
|
|
|
var/area/A = get_area( locate(new_coords.x_pos, new_coords.y_pos, new_center.z) )
|
|
|
|
if(!A)
|
|
message_admins("<span class='notice'>WARNING: Unable to find an area at [new_coords.x_pos];[new_coords.y_pos];[new_center.z]. [src.name] ([src.type]) will not be moved.")
|
|
return
|
|
if(!destroy_everything && !(A.type in list(/area, /area/station/custom)) && !istype(A, /area/random_vault) && !istype(A, /area/vault)) //Breaking blueprint areas and space is fine, breaking the station is not. Breaking randomly generated vaults is fine, in case they spawn in a bad spot!
|
|
message_admins("<span class='notice'>WARNING: [src.name] ([src.type]) attempted to destroy [A] ([A.type]).</span> If you want [src.name] to be able to move freely and destroy areas, change its \"destroy_everything\" variable to 1.")
|
|
return
|
|
//If any of the new turfs are in the moved shuttle's current area, EMERGENCY ABORT (this leads to the shuttle destroying itself & potentially gibbing everybody inside)
|
|
if("[new_coords.x_pos];[new_coords.y_pos];[new_center.z]" in our_own_turfs)
|
|
warning("Shuttle ([src.name]; [src.type]) has attempted to move to a location which overlaps with its current position. Offending turf: [new_coords.x_pos];[new_coords.y_pos];[new_center.z]")
|
|
message_admins("WARNING: A shuttle ([src.name]; [src.type]) has attempted to move to a location which overlaps with its current position. The shuttle will not be moved.")
|
|
return
|
|
|
|
|
|
var/list/turfs_to_update = list()
|
|
|
|
//Move turfs
|
|
for(var/datum/coords/C in new_turfs)
|
|
//Get old turf type
|
|
var/datum/coords/old_C = new_turfs[C]
|
|
var/turf/old_turf = turfs_to_move[old_C]
|
|
var/turf/new_turf = locate(C.x_pos,C.y_pos,new_center.z)
|
|
var/add_underlay = 0
|
|
|
|
if(!old_turf)
|
|
message_admins("ERROR when moving [src.name] ([src.type]) - failed to get original turf at [old_C.x_pos];[old_C.y_pos];[our_center.z]")
|
|
continue
|
|
else if(old_turf.preserve_underlay == 0 && istype(old_turf,/turf/simulated/shuttle/wall)) //Varediting a turf's "preserve_underlay" to 1 will protect its underlay from being changed
|
|
if(old_turf.icon_state in transparent_icons)
|
|
add_underlay = 1
|
|
if(old_turf.underlays.len) //this list is in code/game/area/areas.dm
|
|
var/image/I = locate(/image) in old_turf.underlays //bandaid
|
|
if(I.icon == 'icons/turf/shuttle.dmi') //Don't change underlay to space if CURRENT underlay is a shuttle floor!
|
|
add_underlay = 0
|
|
|
|
if(!new_turf)
|
|
message_admins("ERROR when moving [src.name] ([src.type]) - failed to get new turf at [C.x_pos];[C.y_pos];[new_center.z]")
|
|
continue
|
|
|
|
var/turf/displace_to = locate(C.x_pos,throwy,new_center.z)
|
|
for(var/atom/movable/AM as mob|obj in new_turf.contents)
|
|
if(AM.anchored || src.collision_type == COLLISION_DESTROY)
|
|
src.collide(AM)
|
|
else
|
|
AM.forceMove(displace_to)
|
|
|
|
var/area/old_area = get_area(new_turf)
|
|
if(!old_area) old_area = space
|
|
|
|
//Get the turf's image before it's gone!
|
|
var/image/undlay
|
|
if(add_underlay)
|
|
undlay = image("icon"=new_turf.icon,"icon_state"=new_turf.icon_state,"dir"=new_turf.dir)
|
|
undlay.overlays = new_turf.overlays
|
|
|
|
//****Add the new turf to shuttle's area****
|
|
|
|
linked_area.contents.Add(new_turf)
|
|
new_turf.change_area(old_area,linked_area)
|
|
new_turf.ChangeTurf(old_turf.type, allow = 1)
|
|
new_turfs[C] = new_turf
|
|
|
|
//***Remove old turf from shuttle's area****
|
|
|
|
space.contents.Add(old_turf)
|
|
old_turf.change_area(linked_area,space)
|
|
|
|
//All objects which can't be moved by the shuttle have their area changed to space!
|
|
for(var/atom/movable/AM in old_turf.contents)
|
|
if(!AM.can_shuttle_move(src))
|
|
AM.change_area(linked_area,space)
|
|
|
|
//****Move all variables from the old turf over to the new turf****
|
|
|
|
for(var/key in old_turf.vars)
|
|
if(key in ignored_keys) continue
|
|
//ignored_keys: code/game/area/areas.dm, 526 (above the move_contents_to proc)
|
|
//as of 06/08/2015: list("loc", "locs", "parent_type", "vars", "verbs", "type", "x", "y", "z","group","contents","air","light","areaMaster","underlays","lighting_overlay")
|
|
if(istype(old_turf.vars[key],/list))
|
|
var/list/L = old_turf.vars[key]
|
|
new_turf.vars[key] = L.Copy()
|
|
else if(old_turf.vars)
|
|
new_turf.vars[key] = old_turf.vars[key]
|
|
if(old_turf.transform)
|
|
new_turf.transform = old_turf.transform
|
|
|
|
//****Prepare underlays**** (only do this if add_underlay is 1 -> see above)
|
|
if(add_underlay && undlay)
|
|
new_turf.underlays = list(undlay) //Remove all old underlays, add space
|
|
else
|
|
new_turf.underlays = old_turf.underlays
|
|
/*
|
|
if(ispath(replaced_turf_type,/turf/space))//including the transit hyperspace turfs
|
|
if(old_turf.underlays.len)
|
|
new_turf.underlays = old_turf.underlays
|
|
else
|
|
new_turf.underlays += undlay
|
|
else
|
|
new_turf.underlays += undlay*/
|
|
|
|
new_turf.dir = old_turf.dir
|
|
new_turf.icon_state = old_turf.icon_state
|
|
new_turf.icon = old_turf.icon
|
|
if(rotate)
|
|
new_turf.shuttle_rotate(rotate)
|
|
|
|
//*****Move air*****
|
|
|
|
var/turf/simulated/S_OLD = old_turf
|
|
|
|
if(istype(S_OLD) && S_OLD.zone)
|
|
var/turf/simulated/S_NEW = new_turf
|
|
|
|
if(!S_NEW.air)
|
|
S_NEW.make_air()
|
|
|
|
S_NEW.air.copy_from(S_OLD.zone.air)
|
|
S_OLD.zone.remove(S_OLD)
|
|
|
|
//*****Move objects and mobs*****
|
|
for(var/atom/movable/AM in old_turf)
|
|
if(!AM.can_shuttle_move(src))
|
|
continue
|
|
|
|
if(AM.bound_width > world.icon_size || AM.bound_height > world.icon_size) //If the moved object's bounding box is more than the default, move it after everything else (using spawn())
|
|
AM.loc = null //Without this, ALL neighbouring turfs attempt to move this object too, resulting in the object getting shifted to north/east
|
|
|
|
spawn()
|
|
AM.forceMove(new_turf)
|
|
|
|
//TODO: Make this compactible with bound_x and bound_y.
|
|
else
|
|
AM.forceMove(new_turf)
|
|
|
|
if(rotate)
|
|
AM.shuttle_rotate(rotate)
|
|
|
|
//Move landmarks - for moving the arrivals shuttle
|
|
for(var/list/L in moved_landmarks) //moved_landmarks: code/game/area/areas.dm, 527 (above the move_contents_to proc)
|
|
if(old_turf in L)
|
|
L -= old_turf
|
|
L += new_turf
|
|
|
|
//Add the new turf to the list of turfs to update
|
|
turfs_to_update += new_turf
|
|
|
|
//Delete the old turf
|
|
var/replacing_turf_type = get_base_turf(old_turf.z)
|
|
var/obj/structure/docking_port/destination/D = linked_port.docked_with
|
|
|
|
if(D && istype(D)) replacing_turf_type = D.base_turf_type
|
|
|
|
old_turf.ChangeTurf(replacing_turf_type, allow = 1)
|
|
|
|
if(D && istype(D))
|
|
if(D.base_turf_icon)
|
|
old_turf.icon = D.base_turf_icon
|
|
if(D.base_turf_icon_state)
|
|
old_turf.icon_state = D.base_turf_icon_state
|
|
|
|
if(istype(old_turf,/turf/space))
|
|
old_turf.lighting_clear_overlays() //A horrible band-aid fix for lighting overlays appearing over space
|
|
|
|
//Update doors
|
|
if(turfs_to_update.len)
|
|
for(var/turf/simulated/T1 in turfs_to_update)
|
|
for(var/obj/machinery/door/D2 in T1)
|
|
D2.update_nearby_tiles()
|
|
|
|
return 1
|
|
|
|
/proc/setup_shuttles()
|
|
world.log << "Setting up all shuttles..."
|
|
|
|
var/all_count = 0
|
|
var/count = 0
|
|
for(var/datum/shuttle/S in shuttles)
|
|
switch(S.initialize())
|
|
if(INIT_NO_AREA)
|
|
if(S.is_special())
|
|
var/msg = S.linked_area ? "- \"[S.linked_area]\" was given as a starting area." : ""
|
|
warning("Invalid or missing starting area for [S.name] ([S.type]) [msg]")
|
|
else
|
|
var/msg = S.linked_area ? "- \"[S.linked_area]\" was given as a starting area." : ""
|
|
world.log << "Invalid or missing starting area for [S.name] ([S.type]) [msg]"
|
|
if(INIT_NO_PORT)
|
|
if(S.is_special())
|
|
warning("Couldn't find a shuttle docking port for [S.name] ([S.type]).")
|
|
else
|
|
world.log << "Couldn't find a shuttle docking port for [S.name] ([S.type])."
|
|
if(INIT_NO_START)
|
|
if(S.is_special())
|
|
warning("[S.name] ([S.type]) couldn't connect to a destination port on init - unless this is intended, there might be problems.")
|
|
else
|
|
world.log << "[S.name] ([S.type]) couldn't connect to a destination port on init - unless this is intended, there might be problems."
|
|
else
|
|
count++
|
|
all_count++
|
|
|
|
world.log << "[all_count] shuttles initialized, of them [count] were initialized properly."
|
|
|
|
//THE MOST IMPORTANT PIECE OF CODE HERE
|
|
emergency_shuttle.shuttle = escape_shuttle
|
|
|
|
if(!emergency_shuttle || !emergency_shuttle.shuttle)
|
|
warning("Emergency shuttle is broken.")
|
|
else
|
|
world.log << "Emergency shuttle has been successfully set up."
|
|
|
|
//Custom shuttles
|
|
/datum/shuttle/custom
|
|
name = "custom shuttle"
|
|
|
|
/datum/shuttle/proc/show_outline(var/mob/user, var/turf/centered_at)
|
|
if(!user)
|
|
return
|
|
|
|
if(!centered_at)
|
|
var/turf/user_turf = get_turf(user)
|
|
if(!user_turf)
|
|
to_chat(user, "You must be standing on a turf!")
|
|
return
|
|
|
|
centered_at = get_step(user_turf,usr.dir)
|
|
|
|
var/turf/original_center = get_turf(linked_port)
|
|
|
|
if(!centered_at)
|
|
to_chat(user, "ERROR: Unable to find center turf!")
|
|
return
|
|
|
|
var/offsetX = centered_at.x - original_center.x
|
|
var/offsetY = centered_at.y - original_center.y
|
|
var/datum/coords/offset = new(offsetX,offsetY)
|
|
|
|
var/rotate = dir2angle(turn(user.dir,180)) - dir2angle(linked_port.dir)
|
|
|
|
var/list/original_coords = list()
|
|
for(var/turf/T in linked_area.get_turfs())
|
|
var/datum/coords/C = new(T.x,T.y)
|
|
original_coords += C
|
|
|
|
var/list/new_coords = list()
|
|
|
|
var/cosine = cos(rotate)
|
|
var/sine = sin(rotate)
|
|
|
|
for(var/datum/coords/C in original_coords)
|
|
var/datum/coords/NC = C.add(offset)
|
|
new_coords += NC
|
|
|
|
if(rotate)
|
|
var/newX = (cosine * (NC.x_pos - centered_at.x)) + (sine * (NC.y_pos - centered_at.y)) + centered_at.x
|
|
var/newY = -(sine * (NC.x_pos - centered_at.x)) + (cosine * (NC.y_pos - centered_at.y)) + centered_at.y
|
|
|
|
NC.x_pos = newX
|
|
NC.y_pos = newY
|
|
|
|
var/list/images = list()
|
|
for(var/datum/coords/C in new_coords)
|
|
var/turf/T = locate(C.x_pos,C.y_pos,centered_at.z)
|
|
if(!T) continue
|
|
|
|
var/image/I = image('icons/turf/areas.dmi', icon_state="bluenew")
|
|
I.loc = T
|
|
images += I
|
|
user << I
|
|
|
|
var/image/center_img = image('icons/turf/areas.dmi', icon_state="blue") //This is actually RED, honk
|
|
center_img.loc = centered_at
|
|
images += center_img
|
|
user << center_img
|
|
|
|
alert(usr,"Press \"Ok\" to remove the images","Magic","Ok")
|
|
|
|
if(usr.client)
|
|
for(var/image/I in images)
|
|
usr.client.images -= I
|
|
return
|
|
|
|
#undef INIT_SUCCESS
|
|
#undef INIT_NO_AREA
|
|
#undef INIT_NO_PORT
|
|
#undef INIT_NO_START
|