diff --git a/code/__DEFINES/stat.dm b/code/__DEFINES/stat.dm index fe780c5d154..8c895013bf5 100644 --- a/code/__DEFINES/stat.dm +++ b/code/__DEFINES/stat.dm @@ -42,6 +42,9 @@ #define SHUTTLE_ESCAPE 5 #define SHUTTLE_ENDGAME 6 +// Shuttle return values +#define SHUTTLE_ALREADY_DOCKED 7 + /* Logic diff --git a/code/_globalvars/mapping.dm b/code/_globalvars/mapping.dm index 891dbc05b24..1bc335d827a 100644 --- a/code/_globalvars/mapping.dm +++ b/code/_globalvars/mapping.dm @@ -61,3 +61,5 @@ var/list/datum/map_template/map_templates = list() var/list/datum/map_template/ruins_templates = list() var/list/datum/map_template/space_ruins_templates = list() //var/list/datum/map_template/lava_ruins_templates = list() + +var/list/datum/map_template/shuttle_templates = list() diff --git a/code/controllers/Processes/shuttles.dm b/code/controllers/Processes/shuttles.dm index e92def92224..31782e10de0 100644 --- a/code/controllers/Processes/shuttles.dm +++ b/code/controllers/Processes/shuttles.dm @@ -9,6 +9,7 @@ var/const/CALL_SHUTTLE_REASON_LENGTH = 12 //emergency shuttle stuff var/obj/docking_port/mobile/emergency/emergency + var/obj/docking_port/mobile/emergency/backup/backup_shuttle var/emergencyCallTime = 6000 //time taken for emergency shuttle to reach the station when called (in deciseconds) var/emergencyDockTime = 1800 //time taken for emergency shuttle to leave again once it has docked (in deciseconds) var/emergencyEscapeTime = 1200 //time taken for emergency shuttle to reach a safe distance after leaving station (in deciseconds) @@ -49,6 +50,8 @@ var/const/CALL_SHUTTLE_REASON_LENGTH = 12 if(!emergency) WARNING("No /obj/docking_port/mobile/emergency placed on the map!") + if(!backup_shuttle) + WARNING("No /obj/docking_port/mobile/emergency/backup placed on the map!") if(!supply) WARNING("No /obj/docking_port/mobile/supply placed on the map!") @@ -88,8 +91,11 @@ var/const/CALL_SHUTTLE_REASON_LENGTH = 12 /datum/controller/process/shuttle/proc/requestEvac(mob/user, call_reason) if(!emergency) - throw EXCEPTION("requestEvac(): There is no emergency shuttle! The game will be unresolvable. This is likely due to a mapping error") - return + WARNING("requestEvac(): There is no emergency shuttle, but the shuttle was called. Using the backup shuttle instead.") + if(!backup_shuttle) + throw EXCEPTION("requestEvac(): There is no emergency shuttle, or backup shuttle! The game will be unresolvable. This is likely due to a mapping error") + return + emergency = backup_shuttle if(world.time - round_start_time < config.shuttle_refuel_delay) to_chat(user, "The emergency shuttle is refueling. Please wait another [abs(round(((world.time - round_start_time) - config.shuttle_refuel_delay)/600))] minutes before trying again.") @@ -130,6 +136,14 @@ var/const/CALL_SHUTTLE_REASON_LENGTH = 12 return + +// Called when an emergency shuttle mobile docking port is +// destroyed, which will only happen with admin intervention +/datum/controller/process/shuttle/proc/emergencyDeregister() + // When a new emergency shuttle is created, it will override the + // backup shuttle. + emergency = backup_shuttle + /datum/controller/process/shuttle/proc/cancelEvac(mob/user) if(canRecall()) emergency.cancel(get_area(user)) @@ -194,13 +208,14 @@ var/const/CALL_SHUTTLE_REASON_LENGTH = 12 /datum/controller/process/shuttle/proc/moveShuttle(shuttleId, dockId, timed) var/obj/docking_port/mobile/M = getShuttle(shuttleId) + var/obj/docking_port/stationary/D = getDock(dockId) if(!M) return 1 if(timed) - if(M.request(getDock(dockId))) + if(M.request(D)) return 2 else - if(M.dock(getDock(dockId))) + if(M.dock(D)) return 2 return 0 //dock successful diff --git a/code/datums/helper_datums/map_template.dm b/code/datums/helper_datums/map_template.dm index 03fe8602281..8b26807199e 100644 --- a/code/datums/helper_datums/map_template.dm +++ b/code/datums/helper_datums/map_template.dm @@ -147,7 +147,7 @@ if(istype(R, /datum/map_template/ruin/space)) space_ruins_templates[R.name] = R -/* + /proc/preloadShuttleTemplates() for(var/item in subtypesof(/datum/map_template/shuttle)) var/datum/map_template/shuttle/shuttle_type = item @@ -158,4 +158,3 @@ shuttle_templates[S.shuttle_id] = S map_templates[S.shuttle_id] = S -*/ diff --git a/code/datums/shuttles.dm b/code/datums/shuttles.dm new file mode 100644 index 00000000000..067f278ffca --- /dev/null +++ b/code/datums/shuttles.dm @@ -0,0 +1,152 @@ +/datum/map_template/shuttle + name = "Base Shuttle Template" + var/prefix = "_maps/shuttles/" + var/suffix + var/port_id + + var/description + var/admin_notes + +/datum/map_template/shuttle/New() + mappath = "[prefix][port_id]_[suffix].dmm" + . = ..() + +/datum/map_template/shuttle/emergency + port_id = "emergency" + name = "Base Shuttle Template (Emergency)" + +/datum/map_template/shuttle/cargo + port_id = "cargo" + name = "Base Shuttle Template (Cargo)" + +/datum/map_template/shuttle/ferry + port_id = "ferry" + name = "Base Shuttle Template (Ferry)" + +/datum/map_template/shuttle/whiteship + port_id = "whiteship" + +// Shuttles start here: + +/datum/map_template/shuttle/emergency/airless + suffix = "airless" + name = "(Shuttle Under Construction)" + description = "The documentation hasn't been finished yet for this \ + shuttle.\n\ + In case of emergency: Break glass." + +/datum/map_template/shuttle/emergency/bar + suffix = "bar" + name = "The Emergency Escape Bar" + description = "Features include a very tough Bardrone, with laws to be \ + a good bartender, bathroom, a quality lounge for the heads, and a \ + small gambling table." + admin_notes = "Bardrone should be controlled by a player, either admin \ + or ghost, has modified drone laws, can speak human and see normally." + +/datum/map_template/shuttle/emergency/box + suffix = "box" + name = "emergency shuttle (Box)" + +/datum/map_template/shuttle/emergency/clown + suffix = "clown" + name = "Snappop(tm)!" + description = "Hey kids and grownups! Are you bored of DULL and TEDIOUS \ + shuttle journeys after you're evacuating for probably BORING reasons. \ + Well then order the Snappop(tm) today! We've got fun activities for \ + everyone, an all access cockpit, and no boring security brig! Boo! \ + Play dress up with your friends! Collect all the bedsheets before \ + your neighbour does! Check if the AI is watching you with our patent \ + pending \"Peeping Tom AI Multitool Detector\" or PEEEEEETUR for \ + short. Have a fun ride!" + admin_notes = "Brig is replaced by anchored greentext book surrounded by \ + lavaland chasms, stationside door has been removed to prevent \ + accidental dropping." + +/datum/map_template/shuttle/emergency/cramped + suffix = "cramped" + name = "Secure Transport Vessel 5 (STV5)" + description = "Well, looks like Centcomm only had this ship in the area, \ + they probably weren't expecting you to need evac for a while. \ + Probably best if you don't rifle around in whatever equipment they \ + were transporting. I hope you're friendly with your coworkers, \ + because there is very little space in this thing.\n\ + \n\ + Contains contraband armory guns, maintenance loot, and abandoned \ + crates!" + admin_notes = "Due to origin as a solo piloted secure vessel, has an \ + active GPS onboard labeled STV5." + +/datum/map_template/shuttle/emergency/meta + suffix = "meta" + name = "emergency shuttle (Metastation)" + +/datum/map_template/shuttle/emergency/narnar + suffix = "narnar" + name = "Shuttle 667" + description = "Looks like this shuttle may have wandered into the \ + darkness between the stars on route to the station. Let's not think \ + too hard about where all the bodies came from." + admin_notes = "Contains real cult ruins, mob eyeballs, and inactive \ + constructs. Put players in constructs if you want them to move. \ + Cloning pods in 'medbay' area are showcases and nonfunctional." + +/datum/map_template/shuttle/emergency/supermatter + suffix = "supermatter" + name = "Hyperfractal Gigashuttle" + description = "\"I dunno, this seems kinda needlessly complicated.\"\n\ + \"This shuttle has very a very high safety record, according to \ + Centcom Officer Cadet Yins.\"\n\ + \"Are you sure?\"\n\ + \"Yes, it has a safety record of N-A-N, which is apparently \ + larger than 100%.\"" + admin_notes = "Supermatter that spawns on shuttle is special anchored \ + 'hugbox' supermatter that cannot take damage and does not take in \ + or emit gas. Outside of admin intervention, it cannot explode. \ + It does, however, still dust anything on contact, emits high levels \ + of radiation, and induce hallucinations in anyone looking at it \ + without protective goggles. Emitters spawn powered on, expect \ + admin notices, they are harmless." + +/datum/map_template/shuttle/ferry/base + suffix = "base" + name = "transport ferry" + description = "Standard issue Box/Metastation Centcom ferry." + +/datum/map_template/shuttle/ferry/meat + suffix = "meat" + name = "\"meat\" ferry" + description = "Ahoy! We got all kinds o' meat aft here. Meat from plant \ + people, people who be dark, not in a racist way, just they're dark \ + black. Oh and lizard meat too,mighty popular that is. Definitely \ + 100% fresh, just ask this guy here. *person on meatspike moans* See? \ + Definitely high quality meat, nothin' wrong with it, nothin' added, \ + definitely no zombifyin' reagents!" + admin_notes = "Meat currently contains no zombifying reagents, lizard on \ + meatspike must be spawned in." + +/datum/map_template/shuttle/ferry/lighthouse + suffix = "lighthouse" + name = "The Lighthouse(?)" + description = "*static*... part of a much larger vessel, possibly \ + military in origin. The weapon markings aren't anything we've seen \ + ... static ... by almost never the same person twice, possible use \ + of unknown storage ... static ... seeing ERT officers onboard, but \ + no missions are on file for ... static ... static ... annoying \ + jingle ... only at The LIGHTHOUSE! Fulfilling needs you didn't even \ + know you had. We've got EVERYTHING, and something else!" + admin_notes = "Currently larger than ferry docking port on Box, will not \ + hit anything, but must be force docked. Trader and ERT bodyguards are \ + not included." + +/datum/map_template/shuttle/whiteship/box + suffix = "box" + name = "NT Medical Ship" + +/datum/map_template/shuttle/whiteship/meta + suffix = "meta" + name = "NT Recovery White-ship" + +/datum/map_template/shuttle/cargo/box + suffix = "box" + name = "supply shuttle (Box)" diff --git a/code/game/gamemodes/game_mode.dm b/code/game/gamemodes/game_mode.dm index 7d2ae88fe2a..e91f7156208 100644 --- a/code/game/gamemodes/game_mode.dm +++ b/code/game/gamemodes/game_mode.dm @@ -135,7 +135,7 @@ break /datum/game_mode/proc/check_finished() //to be called by ticker - if(shuttle_master.emergency.mode >= SHUTTLE_ENDGAME || station_was_nuked) + if((shuttle_master.emergency && shuttle_master.emergency.mode >= SHUTTLE_ENDGAME)|| station_was_nuked) return 1 return 0 diff --git a/code/game/machinery/status_display.dm b/code/game/machinery/status_display.dm index e73dbaf5dbd..12404d0574e 100644 --- a/code/game/machinery/status_display.dm +++ b/code/game/machinery/status_display.dm @@ -89,7 +89,7 @@ return 1 if(STATUS_DISPLAY_TRANSFER_SHUTTLE_TIME) //emergency shuttle timer var/use_warn = 0 - if(shuttle_master.emergency.timer) + if(shuttle_master.emergency && shuttle_master.emergency.timer) use_warn = 1 message1 = "-[shuttle_master.emergency.getModeStr()]-" message2 = shuttle_master.emergency.getTimerStr() diff --git a/code/game/objects/effects/misc.dm b/code/game/objects/effects/misc.dm index a635d2fdad9..13d02c1a740 100644 --- a/code/game/objects/effects/misc.dm +++ b/code/game/objects/effects/misc.dm @@ -92,4 +92,11 @@ name = "mobl" var/master = null - var/list/container = list( ) \ No newline at end of file + var/list/container = list( ) + + +/obj/structure/showcase/horrific_experiment + name = "horrific experiment" + desc = "Some sort of pod filled with blood and vicerea. You swear you can see it moving..." + icon = 'icons/obj/cloning.dmi' + icon_state = "pod_g" \ No newline at end of file diff --git a/code/modules/admin/admin_verbs.dm b/code/modules/admin/admin_verbs.dm index 90ad26039db..894fc07bd60 100644 --- a/code/modules/admin/admin_verbs.dm +++ b/code/modules/admin/admin_verbs.dm @@ -37,6 +37,7 @@ var/list/admin_verbs_admin = list( /client/proc/jumptoturf, /*allows us to jump to a specific turf*/ /client/proc/admin_call_shuttle, /*allows us to call the emergency shuttle*/ /client/proc/admin_cancel_shuttle, /*allows us to cancel the emergency shuttle, sending it back to centcomm*/ + /client/proc/cmd_admin_destroy_shuttle, /* Destroys the emergency shuttle, allowing us to import a new shuttle template. Or just horribly fuck with the game. */ /client/proc/cmd_admin_import_shuttle, /* Imports a emergency shuttle from a template, and sends it to its round start location. Probably should destroy the old one first.*/ /client/proc/check_words, /*displays cult-words*/ /client/proc/check_ai_laws, /*shows AI and borg laws*/ /client/proc/manage_silicon_laws, /* Allows viewing and editing silicon laws. */ diff --git a/code/modules/shuttle/emergency.dm b/code/modules/shuttle/emergency.dm index 8516d3e1dec..a7498d99f0f 100644 --- a/code/modules/shuttle/emergency.dm +++ b/code/modules/shuttle/emergency.dm @@ -98,6 +98,13 @@ shuttle_master.emergency = src return 1 +/obj/docking_port/mobile/emergency/Destroy() + if(src.i_know_what_im_doing) + // This'll make the shuttle subsystem use the backup shuttle. + shuttle_master.emergencyDeregister() + + . = ..() + /obj/docking_port/mobile/emergency/timeLeft(divisor) if(divisor <= 0) divisor = 10 @@ -286,3 +293,22 @@ 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/New() + // We want to be a valid emergency shuttle + // but not be the main one, keep whatever's set + // valid. + var/current_emergency = SSshuttle.emergency + ..() + shuttle_master.emergency = current_emergency + shuttle_master.backup_shuttle = src diff --git a/code/modules/shuttle/shuttle.dm b/code/modules/shuttle/shuttle.dm index 5d35eff842e..050ac3d8a20 100644 --- a/code/modules/shuttle/shuttle.dm +++ b/code/modules/shuttle/shuttle.dm @@ -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 + var/i_know_what_im_doing = 0 + //these objects are indestructable /obj/docking_port/Destroy() - return QDEL_HINT_LETMELIVE + // unless you assert that you know what you're doing. Horrible things + // may result. + if(!i_know_what_im_doing) + return QDEL_HINT_LETMELIVE + else + // If not removed immediately, it can interfere with the docking + // detection code, which is annoying and inconvinient. + return QDEL_HINT_HARDDEL_NOW /obj/docking_port/singularity_pull() return @@ -121,7 +130,7 @@ //return first-found touching dockingport /obj/docking_port/proc/get_docked() - return locate(/obj/docking_port/stationary) in loc + . = locate(/obj/docking_port/mobile) in loc /obj/docking_port/proc/getDockedId() var/obj/docking_port/P = get_docked() @@ -226,6 +235,10 @@ return 1 +/obj/docking_port/mobile/Destroy() + if(i_know_what_im_doing) + shuttle_master.mobile -= src + . = ..() //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() @@ -247,16 +260,30 @@ if(height-dheight > S.height-S.dheight) return 5 //check the dock isn't occupied - if(S.get_docked()) - return 6 + var/currently_docked = S.get_docked() + // by someone other than us + if(currently_docked != src) + return 6 + 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 0 //0 means we can dock //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 + var/status = canDock(S) + if(status == SHUTTLE_ALREADY_DOCKED) + // We're already docked there, don't need to do anything. + return + else if(status) + . = status + spawn(0) + var/msg = "request(): shuttle [src] cannot dock at [S], \ + error: [status]" + message_admins(msg) + throw EXCEPTION(msg) + return status //we can't dock at S switch(mode) if(SHUTTLE_CALL) @@ -320,17 +347,66 @@ 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/open/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=1, i<=L0.len, ++i) + var/turf/T0 = L0[i] + if(!T0) + continue + + for(var/atom/AM in T0.GetAllContents()) + if(istype(AM, /mob/dead)) + continue + qdel(AM) + + T0.ChangeTurf(turf_type) + + T0.redraw_lighting() + air_master.remove_from_active(T0) + T0.CalculateAdjacentTurfs() + air_master.add_to_active(T0,1) + + src.i_know_what_im_doing = TRUE + qdel(src) //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) + var/status = canDock(S1) + if(status == 7) + return SHUTTLE_ALREADY_DOCKED + else if(status) + spawn(0) + var/msg = "dock(): shuttle [src] cannot dock at [S1], \ + error: [status]" + message_admins(msg) + throw EXCEPTION(msg) + return status - 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)) @@ -475,6 +551,24 @@ var/obj/docking_port/stationary/transit/T = shuttle_master.getDock("[id]_transit") if(T && !canDock(T)) return T + + +/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" /* commented out due to issues with rotation for(var/obj/docking_port/stationary/transit/S in shuttle_master.transit) if(S.id) diff --git a/code/modules/shuttle/shuttle_mainpulator.dm b/code/modules/shuttle/shuttle_mainpulator.dm new file mode 100644 index 00000000000..55913ab432f --- /dev/null +++ b/code/modules/shuttle/shuttle_mainpulator.dm @@ -0,0 +1,13 @@ +/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/dominator.dmi' + icon_state = "dominator-blue" + +/obj/machinery/shuttle_manipulator/process() + return diff --git a/paradise.dme b/paradise.dme index d79069d135d..b1e0b5979db 100644 --- a/paradise.dme +++ b/paradise.dme @@ -10,6 +10,7 @@ #define DEBUG // END_PREFERENCES // BEGIN_INCLUDE +#include "shuttles.dm" #include "_maps\cyberiad.dm" #include "code\_compile_options.dm" #include "code\hub.dm" @@ -202,6 +203,7 @@ #include "code\datums\progressbar.dm" #include "code\datums\recipe.dm" #include "code\datums\ruins.dm" +#include "code\datums\shuttles.dm" #include "code\datums\spell.dm" #include "code\datums\supplypacks.dm" #include "code\datums\uplink_item.dm" @@ -1994,6 +1996,7 @@ #include "code\modules\shuttle\assault_pod.dm" #include "code\modules\shuttle\emergency.dm" #include "code\modules\shuttle\shuttle.dm" +#include "code\modules\shuttle\shuttle_mainpulator.dm" #include "code\modules\shuttle\supply.dm" #include "code\modules\shuttle\syndicate.dm" #include "code\modules\space_transition\space_transition.dm" diff --git a/shuttles.dm b/shuttles.dm new file mode 100644 index 00000000000..18f078c519e --- /dev/null +++ b/shuttles.dm @@ -0,0 +1,117 @@ +/proc/emergency_sanity_check() + if(shuttle_master.emergency.mode != SHUTTLE_IDLE) + var/confirm = alert(src, "Modification of the emergency shuttle while it is not idle can be highly dangerous, and may result in WEIRD UNPREDICTABLE SHIT. Are you SURE you want to continue? Obviously if you're not touching the emergency shuttle, then you're probably fine.", "Confirm", "Yes", "No") + if(confirm == "Yes") + return TRUE + else + return FALSE + else + return TRUE + +/client/proc/cmd_admin_destroy_shuttle() + set category = "Admin" + set name = "Shuttle Destroy" + + if (!holder) + src << "Only administrators may use this command." + return + + if(!emergency_sanity_check()) + return + + var/list/names = list() + var/obj/docking_port/mobile/M + for (var/atom/AM in shuttle_master.mobile) + M = AM + names += M.name + + var/selected = input("Select shuttle to DESTROY", "Shuttles") as null|anything in names + + var/decide_against_msg = "You decide against destroying a shuttle." + + if(!selected) + src << decide_against_msg + return + + var/confirm = alert(src, "Are you sure you want to destroy [selected]?", "Confirm", "Yes", "No") + + if(confirm != "Yes") + src << decide_against_msg + return + + var/destroyed = FALSE + for (var/atom/AM in shuttle_master.mobile) + M = AM + if(M.name == selected) + M.jumpToNullSpace() + destroyed = TRUE + break + + if(!destroyed) + src << "Something went wrong, the selected shuttle doesn't exist anymore." + return + + log_admin("[key_name_admin(usr)] - ShuttleDestroy: [M]") + message_admins("[key_name_admin(usr)] has used ShuttleDestroy on [selected]
") + feedback_add_details("admin_verb","SHTDEL") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + +/client/proc/cmd_admin_import_shuttle() + set category = "Admin" + set name = "Shuttle Import" + + if (!holder) + to_chat(src, "Only administrators may use this command.") + return + + if(!emergency_sanity_check()) + return + + var/datum/map_template/template + var/map = input(usr, "Choose a Shuttle Template to import","Import Shuttle Template") as null|anything in shuttle_templates + if(!map) + return + template = shuttle_templates[map] + + if(alert(usr,"Confirm importing of [map]","Shuttle Import Confirm","Yes","No") != "Yes") + return + + var/turf/T = get_turf(locate("landmark*Shuttle Import")) + if(!T) + to_chat(usr, "Shuttle import landmark not found. Aborting.") + template.load(T, centered = TRUE) + + var/obj/docking_port/mobile/M + + for(var/S in template.get_affected_turfs(T,centered = TRUE)) + for (var/AM in S) + if(istype(AM, /obj/docking_port/mobile)) + if(!M) + M = AM + else + to_chat(usr,"More than one mobile docking port was detected ([AM]), this is a BAD THING, TELL A CODER.") + if(istype(AM, /obj/docking_port/stationary)) + to_chat(usr, "REEEEEEEEEEEE! THE LOADED TEMPLATE HAS [AM], A STATIONARY DOCKING PORT, THIS IS A BAD THING FIX IT. TELL A CODER. WE CAN DELETE IT BUT IT SHOULD NOT BE THERE.") + var/obj/docking_port/stationary/bad = AM + bad.i_know_what_im_doing = TRUE + qdel(bad) + + if(!M) + to_chat(usr, "The loaded template didn't have a mobile docking port! The template has been deleted.") + for(var/S in template.get_affected_turfs(T,centered = TRUE)) + var/turf/T0 = S + for(var/atom/AM in T0.GetAllContents()) + if(istype(AM, /mob/dead)) + continue + qdel(AM) + qdel(S) + return + + var/status = M.dockRoundstart() + if(status) + log_admin("The imported shuttle [map]/[M] failed to travel to its roundstart \ + location (error code [status]). Please fix or delete the imported shuttle \ + before continuing any more shuttle import hijinks.") + + log_admin("[key_name_admin(usr)] - ShuttleImport: [map] - [M]") + message_admins("[key_name_admin(usr)] has used ShuttleImport: [map] - [M]
") + feedback_add_details("admin_verb","SHTIMP") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! \ No newline at end of file