Files
vgstation13/code/datums/shuttle.dm
vgstation-snowmap-team b39bdde99c SNOW MAP, LET THE APOCALYPSE BEGIN
* SNOWPLANES?

* snow map #2

* it sort of works (not really)

* we'll call this a prototype

* committing so I can remove other changes later

* snowmap prototype 2/11/2016 - practically ready for an open beta edition

* more stuff, more sprites, more items, we're getting there

* before I uncheck the error handler

* AAAAAAAAAAAAAAAAA

* it works now

* Edits the map to be more terrestrial: Added paramedic stations/security stations/EVA stations to each map. Removed grilles from taxi. Still a bunch of shite to do eg belt hell but we're getting there
Also tweaked spawn chance because reasons

* snowboot

* Coats (#2)

* Take these, good luck

* oops

* According to all known laws
of aviation,
there is no way a bee
should be able to fly.
Its wings are too small to get
its fat little body off the ground.
The bee, of course, flies anyway
because bees don’t care
what humans think is impossible.
Yellow, black. Yellow, black.
Yellow, black. Yellow, black.
Ooh, black and yellow!
Let’s shake it up a little.
Barry! Breakfast is ready!
Coming!
Hang on a second.
Hello?
- Barry?
- Adam?
- Oan you believe this is happening?
- I can’t. I’ll pick you up.
Looking sharp.
Use the stairs. Your father
paid good money for those.
Sorry. I’m excited.
Here’s the graduate.
We’re very proud of you, son.
A perfect report card, all B’s.
Very proud.
Ma! I got a thing going here.
- You got lint on your fuzz.
- Ow! That’s me!
- Wave to us! We’ll be in row 118,000.
- Bye!
Barry, I told you,
stop flying in the house!
- Hey, Adam.
- Hey, Barry.
- Is that fuzz gel?
- A little. Special day, graduation.
Never thought I’d make it.
Three days grade school,
three days high school.
Those were awkward.

* define

* bugfixes

* fixes conflicts

* fixed bugs and made hoods work better

* do ah look lahk ah know what "ay-tomic" is?

* bugfixes shadowfixes added like seven different coats, ian now can wear scarves

* mapchanges - snaxi is now united

* wolves, and point handling (#3)

* wolves, and point handling

* wolf pointing, removes hitler

* Removes nonsense

* ice ice baby
procedural generation is the best buzzword
new snow map doors
map now has proper z level names
not working right now
ice smoothing is being a !!bitch!!

* glaciers now smooth
glaciers no longer eat up the pipes between stations (this will cause some fuck ups with smoothing but uh yeah)
you now slip on rivers
todo
- skis
- snowshoes
- spiked boots

* Moves ores to overlays, adds snow roid sprites (#5)

* Moves ores to overlays, adds snow roid sprites

* Fixes gibtonite, re-approaches some mine surprises

* Wendigos added, skifree yeti added, wendigo meat and transformation added (#4)

* DEER, and leather stuff

* Adds xeno spears, xenohide, fixes bugs

* alright dragonbro over to you for tonight I'm going to sleep

* Fixes wendigos, and wolves

* if it works it works who cares why

* snowmap bugfixes and optimisations

* zzz

* Revamp in working state
no work in progress
saving wip
Most issues fixed.  Fishing half way through overhaul to include minigame
Turned spaces into tabs.  fucking atom REEEEEEEEEE
Clownfish and clownburger added.
All fishing code done.  Carp and normal fish recipes updated and ready.  Carpmeat changed to subtype of fish_fillet.
WIP.  Rods mostly done.  Basic fish and bait added.

* removes bluespace ponds to be atomic

* fixes issues - bluespace pond back in the code but not able to be got anywhere

* does the easy things

* renames it taxi outpost
adds map cleaning things

* OK THIS WILL FIX IT FOR REAL

* fixes EVERYTHING but it's not ready to merge because I reckon we can squeeze some last minute features in

* whoops forgot to fix this

* underground mining stuff

* adds lobby music courtesy of aceedex

* bugfixes
mining underground optimisations (now it actually runs instead of grinding to a halt)
there are runtimes
aaaa oh well will fix tomorrow

* fixes so that JSG can host it
some missing features
2016-12-24 18:32:15 -08:00

855 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/docking_port/shuttle/linked_port
//The shuttle's current location
var/obj/docking_port/destination/current_port
//The shuttle's transit location
var/obj/docking_port/destination/transit_port
//The shuttle's destination
var/obj/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
var/disable_mesons = 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/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/docking_port/shuttle/shuttle_docking_port
for(var/obj/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/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/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/docking_port/destination/dock in all_docking_ports)
if(istype(dock,D))
dock.link_to_shuttle(src)
return dock
else if(istype(D,/obj/docking_port/destination))
var/obj/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/docking_port/destination/dock in all_docking_ports)
if(istype(dock,D))
transit_port = dock
return dock
else if(istype(D,/obj/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/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].")
destination_port = D
last_moved = world.time
moving = 1
log_game("[usr ? key_name(usr) : "Something"] sent [name] ([type]) to [D.areaname]")
if(get_pre_flight_delay())
spawn(max(1,get_pre_flight_delay()-5))
for(var/obj/structure/shuttle/engine/propulsion/P in linked_area)
spawn()
P.shoot_exhaust()
spawn(get_pre_flight_delay())
//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])
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.")
moving = 0
destination_port = null
return 0
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)
spawn(max(1,get_transit_delay()-5))
for(var/obj/structure/shuttle/engine/propulsion/P in linked_area)
spawn()
P.shoot_exhaust()
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/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/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/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/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(istype(AM,/mob/living/carbon/human) && disable_mesons)
var/mob/living/carbon/human/H = AM
if(istype(H.glasses,/obj/item/clothing/glasses/scanner/meson))
var/obj/item/clothing/glasses/scanner/meson/mesons = H.glasses
mesons.disable(H)
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.Knockdown(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/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/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("Unable to find space area for shuttle [src.type]")
//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.shuttle_can_crush) //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.forceMove(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 = old_turf.get_underlying_turf()
var/obj/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_overlay() //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