mirror of
https://github.com/SPLURT-Station/S.P.L.U.R.T-Station-13.git
synced 2025-12-11 10:22:13 +00:00
Shuttles
This commit is contained in:
@@ -7,6 +7,8 @@
|
||||
#define SHUTTLE_STRANDED "stranded"
|
||||
#define SHUTTLE_ESCAPE "escape"
|
||||
#define SHUTTLE_ENDGAME "endgame: game over"
|
||||
#define SHUTTLE_RECHARGING "recharging"
|
||||
#define SHUTTLE_PREARRIVAL "landing"
|
||||
|
||||
#define EMERGENCY_IDLE_OR_RECALLED (SSshuttle.emergency && ((SSshuttle.emergency.mode == SHUTTLE_IDLE) || (SSshuttle.emergency.mode == SHUTTLE_RECALL)))
|
||||
#define EMERGENCY_ESCAPED_OR_ENDGAMED (SSshuttle.emergency && ((SSshuttle.emergency.mode == SHUTTLE_ESCAPE) || (SSshuttle.emergency.mode == SHUTTLE_ENDGAME)))
|
||||
|
||||
@@ -521,3 +521,10 @@
|
||||
* Camera mobs, AIs, ghosts and some other are of course exempt from this. This also doesn't influence simplemob AI, for the best.
|
||||
*/
|
||||
/datum/config_entry/flag/use_field_of_vision
|
||||
|
||||
//Shuttle size limiter
|
||||
/datum/config_entry/number/max_shuttle_count
|
||||
config_entry_value = 6
|
||||
|
||||
/datum/config_entry/number/max_shuttle_size
|
||||
config_entry_value = 250
|
||||
|
||||
@@ -103,6 +103,10 @@
|
||||
/area/shuttle/custom
|
||||
name = "Custom player shuttle"
|
||||
|
||||
/area/shuttle/custom/powered
|
||||
name = "Custom Powered player shuttle"
|
||||
requires_power = FALSE
|
||||
|
||||
/area/shuttle/arrival
|
||||
name = "Arrival Shuttle"
|
||||
unique = TRUE // SSjob refers to this area for latejoiners
|
||||
|
||||
@@ -846,6 +846,9 @@
|
||||
/atom/proc/GenerateTag()
|
||||
return
|
||||
|
||||
/atom/proc/connect_to_shuttle(obj/docking_port/mobile/port, obj/docking_port/stationary/dock, idnum, override=FALSE)
|
||||
return
|
||||
|
||||
// Generic logging helper
|
||||
/atom/proc/log_message(message, message_type, color=null, log_globally=TRUE)
|
||||
if(!log_globally)
|
||||
|
||||
@@ -35,6 +35,11 @@
|
||||
M.unset_machine() //to properly reset the view of the users if the console is deleted.
|
||||
return ..()
|
||||
|
||||
/obj/machinery/computer/security/connect_to_shuttle(obj/docking_port/mobile/port, obj/docking_port/stationary/dock, idnum, override=FALSE)
|
||||
for(var/i in network)
|
||||
network -= i
|
||||
network += "[idnum][i]"
|
||||
|
||||
/obj/machinery/computer/security/can_interact(mob/user)
|
||||
if((!hasSiliconAccessInArea(user) && !Adjacent(user)) || is_blind(user) || !in_view_range(user, src))
|
||||
return FALSE
|
||||
|
||||
33
code/game/machinery/shuttle/custom_shuttle.dm
Normal file
33
code/game/machinery/shuttle/custom_shuttle.dm
Normal file
@@ -0,0 +1,33 @@
|
||||
/obj/machinery/shuttle
|
||||
name = "shuttle component"
|
||||
desc = "Something for shuttles."
|
||||
density = TRUE
|
||||
obj_integrity = 250
|
||||
max_integrity = 250
|
||||
icon = 'icons/turf/shuttle.dmi'
|
||||
icon_state = "burst_plasma"
|
||||
idle_power_usage = 150
|
||||
circuit = /obj/item/circuitboard/machine/shuttle/engine
|
||||
var/icon_state_closed = "burst_plasma"
|
||||
var/icon_state_open = "burst_plasma_open"
|
||||
var/icon_state_off = "burst_plasma_off"
|
||||
|
||||
/obj/machinery/shuttle/Initialize()
|
||||
. = ..()
|
||||
GLOB.custom_shuttle_machines += src
|
||||
|
||||
/obj/machinery/shuttle/Destroy()
|
||||
. = ..()
|
||||
GLOB.custom_shuttle_machines -= src
|
||||
|
||||
/obj/machinery/shuttle/attackby(obj/item/I, mob/living/user, params)
|
||||
if(default_deconstruction_screwdriver(user, icon_state_open, icon_state_closed, I))
|
||||
return
|
||||
if(default_pry_open(I))
|
||||
return
|
||||
if(panel_open)
|
||||
if(default_change_direction_wrench(user, I))
|
||||
return
|
||||
if(default_deconstruction_crowbar(I))
|
||||
return
|
||||
return ..()
|
||||
138
code/game/machinery/shuttle/shuttle_engine.dm
Normal file
138
code/game/machinery/shuttle/shuttle_engine.dm
Normal file
@@ -0,0 +1,138 @@
|
||||
//-----------------------------------------------
|
||||
//-------------Engine Thrusters------------------
|
||||
//-----------------------------------------------
|
||||
|
||||
#define ENGINE_HEAT_TARGET 600
|
||||
#define ENGINE_HEATING_POWER 5000000
|
||||
|
||||
/obj/machinery/shuttle/engine
|
||||
name = "shuttle thruster"
|
||||
desc = "A thruster for shuttles."
|
||||
density = TRUE
|
||||
obj_integrity = 250
|
||||
max_integrity = 250
|
||||
icon = 'icons/turf/shuttle.dmi'
|
||||
icon_state = "burst_plasma"
|
||||
idle_power_usage = 150
|
||||
circuit = /obj/item/circuitboard/machine/shuttle/engine
|
||||
var/thrust = 0
|
||||
var/fuel_use = 0
|
||||
var/bluespace_capable = TRUE
|
||||
var/cooldown = 0
|
||||
var/thruster_active = FALSE
|
||||
var/datum/weakref/attached_heater
|
||||
|
||||
/obj/machinery/shuttle/engine/plasma
|
||||
name = "plasma thruster"
|
||||
desc = "A thruster that burns plasma stored in an adjacent plasma thruster heater."
|
||||
icon_state = "burst_plasma"
|
||||
icon_state_off = "burst_plasma_off"
|
||||
|
||||
idle_power_usage = 0
|
||||
circuit = /obj/item/circuitboard/machine/shuttle/engine/plasma
|
||||
thrust = 25
|
||||
fuel_use = 0.24
|
||||
bluespace_capable = FALSE
|
||||
cooldown = 45
|
||||
|
||||
/obj/machinery/shuttle/engine/void
|
||||
name = "void thruster"
|
||||
desc = "A thruster using technology to breach voidspace for propulsion."
|
||||
icon_state = "burst_void"
|
||||
icon_state_off = "burst_void"
|
||||
icon_state_closed = "burst_void"
|
||||
icon_state_open = "burst_void_open"
|
||||
idle_power_usage = 0
|
||||
circuit = /obj/item/circuitboard/machine/shuttle/engine/void
|
||||
thrust = 400
|
||||
fuel_use = 0
|
||||
bluespace_capable = TRUE
|
||||
cooldown = 90
|
||||
|
||||
/obj/machinery/shuttle/engine/Initialize()
|
||||
. = ..()
|
||||
check_setup()
|
||||
|
||||
/obj/machinery/shuttle/engine/on_construction()
|
||||
. = ..()
|
||||
check_setup()
|
||||
|
||||
/obj/machinery/shuttle/engine/proc/check_setup()
|
||||
var/heater_turf
|
||||
switch(dir)
|
||||
if(NORTH)
|
||||
heater_turf = get_offset_target_turf(src, 0, 1)
|
||||
if(SOUTH)
|
||||
heater_turf = get_offset_target_turf(src, 0, -1)
|
||||
if(EAST)
|
||||
heater_turf = get_offset_target_turf(src, 1, 0)
|
||||
if(WEST)
|
||||
heater_turf = get_offset_target_turf(src, -1, 0)
|
||||
if(!heater_turf)
|
||||
attached_heater = null
|
||||
update_engine()
|
||||
return
|
||||
attached_heater = null
|
||||
for(var/obj/machinery/atmospherics/components/unary/shuttle/heater/as_heater in heater_turf)
|
||||
if(as_heater.dir != dir)
|
||||
continue
|
||||
if(as_heater.panel_open)
|
||||
continue
|
||||
if(!as_heater.anchored)
|
||||
continue
|
||||
attached_heater = WEAKREF(as_heater)
|
||||
break
|
||||
update_engine()
|
||||
return
|
||||
|
||||
/obj/machinery/shuttle/engine/proc/update_engine()
|
||||
if(!attached_heater)
|
||||
icon_state = icon_state_off
|
||||
thruster_active = FALSE
|
||||
return
|
||||
var/obj/machinery/atmospherics/components/unary/shuttle/heater/resolved_heater = attached_heater.resolve()
|
||||
if(panel_open)
|
||||
thruster_active = FALSE
|
||||
else if(resolved_heater?.hasFuel(1))
|
||||
icon_state = icon_state_closed
|
||||
thruster_active = TRUE
|
||||
else
|
||||
thruster_active = FALSE
|
||||
icon_state = icon_state_off
|
||||
return
|
||||
|
||||
/obj/machinery/shuttle/engine/void/update_engine()
|
||||
if(panel_open)
|
||||
thruster_active = FALSE
|
||||
return
|
||||
thruster_active = TRUE
|
||||
icon_state = icon_state_closed
|
||||
return
|
||||
|
||||
//Thanks to spaceheater.dm for inspiration :)
|
||||
/obj/machinery/shuttle/engine/proc/fireEngine()
|
||||
var/turf/heatTurf = loc
|
||||
if(!heatTurf)
|
||||
return
|
||||
var/datum/gas_mixture/env = heatTurf.return_air()
|
||||
var/heat_cap = env.heat_capacity()
|
||||
var/req_power = abs(env.return_temperature() - ENGINE_HEAT_TARGET) * heat_cap
|
||||
req_power = min(req_power, ENGINE_HEATING_POWER)
|
||||
var/deltaTemperature = req_power / heat_cap
|
||||
if(deltaTemperature < 0)
|
||||
return
|
||||
env.temperature += deltaTemperature
|
||||
air_update_turf()
|
||||
|
||||
/obj/machinery/shuttle/engine/attackby(obj/item/I, mob/living/user, params)
|
||||
check_setup()
|
||||
if(default_deconstruction_screwdriver(user, icon_state_open, icon_state_closed, I))
|
||||
return
|
||||
if(default_pry_open(I))
|
||||
return
|
||||
if(panel_open)
|
||||
if(default_change_direction_wrench(user, I))
|
||||
return
|
||||
if(default_deconstruction_crowbar(I))
|
||||
return
|
||||
return ..()
|
||||
132
code/game/machinery/shuttle/shuttle_heater.dm
Normal file
132
code/game/machinery/shuttle/shuttle_heater.dm
Normal file
@@ -0,0 +1,132 @@
|
||||
//-----------------------------------------------
|
||||
//--------------Engine Heaters-------------------
|
||||
//This uses atmospherics, much like a thermomachine,
|
||||
//but instead of changing temp, it stores plasma and uses
|
||||
//it for the engine.
|
||||
//-----------------------------------------------
|
||||
/obj/machinery/atmospherics/components/unary/shuttle
|
||||
name = "shuttle atmospherics device"
|
||||
desc = "This does something to do with shuttle atmospherics"
|
||||
icon_state = "heater"
|
||||
icon = 'icons/turf/shuttle.dmi'
|
||||
|
||||
/obj/machinery/atmospherics/components/unary/shuttle/heater
|
||||
name = "engine heater"
|
||||
desc = "Directs energy into compressed particles in order to power an attached thruster."
|
||||
icon_state = "heater_pipe"
|
||||
var/icon_state_closed = "heater_pipe"
|
||||
var/icon_state_open = "heater_pipe_open"
|
||||
var/icon_state_off = "heater_pipe"
|
||||
idle_power_usage = 50
|
||||
circuit = /obj/item/circuitboard/machine/shuttle/heater
|
||||
|
||||
density = TRUE
|
||||
max_integrity = 400
|
||||
armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 100, "bomb" = 0, "bio" = 100, "rad" = 100, "fire" = 100, "acid" = 30)
|
||||
layer = OBJ_LAYER
|
||||
showpipe = TRUE
|
||||
|
||||
pipe_flags = PIPING_ONE_PER_TURF | PIPING_DEFAULT_LAYER_ONLY
|
||||
|
||||
var/gas_type = /datum/gas/plasma
|
||||
var/efficiency_multiplier = 1
|
||||
var/gas_capacity = 0
|
||||
|
||||
/obj/machinery/atmospherics/components/unary/shuttle/heater/New()
|
||||
. = ..()
|
||||
GLOB.custom_shuttle_machines += src
|
||||
SetInitDirections()
|
||||
update_adjacent_engines()
|
||||
updateGasStats()
|
||||
|
||||
/obj/machinery/atmospherics/components/unary/shuttle/heater/Destroy()
|
||||
. = ..()
|
||||
update_adjacent_engines()
|
||||
GLOB.custom_shuttle_machines -= src
|
||||
|
||||
/obj/machinery/atmospherics/components/unary/shuttle/heater/on_construction()
|
||||
..(dir, dir)
|
||||
SetInitDirections()
|
||||
update_adjacent_engines()
|
||||
|
||||
/obj/machinery/atmospherics/components/unary/shuttle/heater/default_change_direction_wrench(mob/user, obj/item/I)
|
||||
if(!..())
|
||||
return FALSE
|
||||
SetInitDirections()
|
||||
var/obj/machinery/atmospherics/node = nodes[1]
|
||||
if(node)
|
||||
node.disconnect(src)
|
||||
nodes[1] = null
|
||||
if(!parents[1])
|
||||
return
|
||||
nullifyPipenet(parents[1])
|
||||
|
||||
atmosinit()
|
||||
node = nodes[1]
|
||||
if(node)
|
||||
node.atmosinit()
|
||||
node.addMember(src)
|
||||
build_network()
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/atmospherics/components/unary/shuttle/heater/RefreshParts()
|
||||
var/cap = 0
|
||||
var/eff = 0
|
||||
for(var/obj/item/stock_parts/matter_bin/M in component_parts)
|
||||
cap += M.rating
|
||||
for(var/obj/item/stock_parts/micro_laser/L in component_parts)
|
||||
eff += L.rating
|
||||
gas_capacity = 5000 * ((cap - 1) ** 2) + 1000
|
||||
efficiency_multiplier = round(((eff / 2) / 2.8) ** 2, 0.1)
|
||||
updateGasStats()
|
||||
|
||||
/obj/machinery/atmospherics/components/unary/shuttle/heater/examine(mob/user)
|
||||
. = ..()
|
||||
var/datum/gas_mixture/air_contents = airs[1]
|
||||
. += "The engine heater's gas dial reads [air_contents.return_volume()] liters in internal tank.<br>"
|
||||
|
||||
/obj/machinery/atmospherics/components/unary/shuttle/heater/proc/updateGasStats()
|
||||
var/datum/gas_mixture/air_contents = airs[1]
|
||||
if(!air_contents)
|
||||
return
|
||||
air_contents.volume = gas_capacity
|
||||
air_contents.temperature = T20C
|
||||
|
||||
/obj/machinery/atmospherics/components/unary/shuttle/heater/proc/hasFuel(var/required)
|
||||
var/datum/gas_mixture/air_contents = airs[1]
|
||||
var/moles = air_contents.total_moles()
|
||||
return moles >= required
|
||||
|
||||
/obj/machinery/atmospherics/components/unary/shuttle/heater/proc/consumeFuel(var/amount)
|
||||
var/datum/gas_mixture/air_contents = airs[1]
|
||||
air_contents.remove(amount)
|
||||
return
|
||||
|
||||
/obj/machinery/atmospherics/components/unary/shuttle/heater/attackby(obj/item/I, mob/living/user, params)
|
||||
update_adjacent_engines()
|
||||
if(default_deconstruction_screwdriver(user, icon_state_open, icon_state_closed, I))
|
||||
return
|
||||
if(default_pry_open(I))
|
||||
return
|
||||
if(panel_open)
|
||||
if(default_change_direction_wrench(user, I))
|
||||
return
|
||||
if(default_deconstruction_crowbar(I))
|
||||
return
|
||||
return ..()
|
||||
|
||||
/obj/machinery/atmospherics/components/unary/shuttle/heater/proc/update_adjacent_engines()
|
||||
var/engine_turf
|
||||
switch(dir)
|
||||
if(NORTH)
|
||||
engine_turf = get_offset_target_turf(src, 0, -1)
|
||||
if(SOUTH)
|
||||
engine_turf = get_offset_target_turf(src, 0, 1)
|
||||
if(EAST)
|
||||
engine_turf = get_offset_target_turf(src, -1, 0)
|
||||
if(WEST)
|
||||
engine_turf = get_offset_target_turf(src, 1, 0)
|
||||
if(!engine_turf)
|
||||
return
|
||||
for(var/obj/machinery/shuttle/engine/E in engine_turf)
|
||||
E.check_setup()
|
||||
@@ -290,7 +290,7 @@
|
||||
if("shuttle_id")
|
||||
update()
|
||||
|
||||
/obj/machinery/status_display/shuttle/proc/connect_to_shuttle(obj/docking_port/mobile/port, obj/docking_port/stationary/dock, idnum, override)
|
||||
/obj/machinery/status_display/shuttle/connect_to_shuttle(obj/docking_port/mobile/port, obj/docking_port/stationary/dock, idnum, override)
|
||||
if (port && (shuttle_id == initial(shuttle_id) || override))
|
||||
shuttle_id = port.id
|
||||
update()
|
||||
|
||||
@@ -379,3 +379,11 @@
|
||||
/obj/item/circuitboard/computer/nanite_cloud_controller
|
||||
name = "Nanite Cloud Control (Computer Board)"
|
||||
build_path = /obj/machinery/computer/nanite_cloud_controller
|
||||
|
||||
/obj/item/circuitboard/computer/shuttle/flight_control
|
||||
name = "Shuttle Flight Control (Computer Board)"
|
||||
build_path = /obj/machinery/computer/custom_shuttle
|
||||
|
||||
/obj/item/circuitboard/computer/shuttle/docker
|
||||
name = "Shuttle Navigation Computer (Computer Board)"
|
||||
build_path = /obj/machinery/computer/camera_advanced/shuttle_docker/custom
|
||||
|
||||
@@ -1102,3 +1102,28 @@
|
||||
/obj/item/stock_parts/micro_laser = 2,
|
||||
/obj/item/stock_parts/scanning_module = 2
|
||||
)
|
||||
|
||||
/obj/item/circuitboard/machine/shuttle/engine
|
||||
name = "Thruster (Machine Board)"
|
||||
build_path = /obj/machinery/shuttle/engine
|
||||
req_components = list()
|
||||
|
||||
/obj/item/circuitboard/machine/shuttle/engine/plasma
|
||||
name = "Plasma Thruster (Machine Board)"
|
||||
build_path = /obj/machinery/shuttle/engine/plasma
|
||||
req_components = list(/obj/item/stock_parts/capacitor = 2,
|
||||
/obj/item/stack/cable_coil = 5,
|
||||
/obj/item/stock_parts/micro_laser = 1)
|
||||
|
||||
/obj/item/circuitboard/machine/shuttle/engine/void
|
||||
name = "Void Thruster (Machine Board)"
|
||||
build_path = /obj/machinery/shuttle/engine/void
|
||||
req_components = list(/obj/item/stock_parts/capacitor/quadratic = 2,
|
||||
/obj/item/stack/cable_coil = 5,
|
||||
/obj/item/stock_parts/micro_laser/quadultra = 1)
|
||||
|
||||
/obj/item/circuitboard/machine/shuttle/heater
|
||||
name = "Electronic Engine Heater (Machine Board)"
|
||||
build_path = /obj/machinery/atmospherics/components/unary/shuttle/heater
|
||||
req_components = list(/obj/item/stock_parts/micro_laser = 2,
|
||||
/obj/item/stock_parts/matter_bin = 1)
|
||||
|
||||
@@ -167,4 +167,34 @@
|
||||
id = "xenobio_slimeadv"
|
||||
build_path = /obj/item/disk/xenobio_console_upgrade/slimeadv
|
||||
|
||||
/datum/design/board/shuttle/engine/plasma
|
||||
name = "Machine Design (Plasma Thruster Board)"
|
||||
desc = "The circuit board for a plasma thruster."
|
||||
id = "engine_plasma"
|
||||
build_path = /obj/item/circuitboard/machine/shuttle/engine/plasma
|
||||
category = list ("Shuttle Machinery")
|
||||
departmental_flags = DEPARTMENTAL_FLAG_ENGINEERING | DEPARTMENTAL_FLAG_SCIENCE
|
||||
|
||||
/datum/design/board/shuttle/engine/void
|
||||
name = "Machine Design (Void Thruster Board)"
|
||||
desc = "The circuit board for a void thruster."
|
||||
id = "engine_void"
|
||||
build_path = /obj/item/circuitboard/machine/shuttle/engine/void
|
||||
category = list ("Shuttle Machinery")
|
||||
departmental_flags = DEPARTMENTAL_FLAG_ENGINEERING | DEPARTMENTAL_FLAG_SCIENCE
|
||||
|
||||
/datum/design/board/shuttle/engine/heater
|
||||
name = "Machine Design (Engine Heater Board)"
|
||||
desc = "The circuit board for an engine heater."
|
||||
id = "engine_heater"
|
||||
build_path = /obj/item/circuitboard/machine/shuttle/heater
|
||||
category = list ("Shuttle Machinery")
|
||||
departmental_flags = DEPARTMENTAL_FLAG_ENGINEERING | DEPARTMENTAL_FLAG_SCIENCE
|
||||
|
||||
/obj/item/circuitboard/computer/shuttle/flight_control
|
||||
name = "Shuttle Flight Control (Computer Board)"
|
||||
build_path = /obj/machinery/computer/custom_shuttle
|
||||
|
||||
/obj/item/circuitboard/computer/shuttle/docker
|
||||
name = "Shuttle Navigation Computer (Computer Board)"
|
||||
build_path = /obj/machinery/computer/camera_advanced/shuttle_docker/custom
|
||||
|
||||
@@ -761,3 +761,33 @@
|
||||
build_path = /obj/item/tank/internals/emergency_oxygen/engi/empty
|
||||
category = list("Equipment")
|
||||
departmental_flags = DEPARTMENTAL_FLAG_ENGINEERING
|
||||
|
||||
/datum/design/shuttle_speed_upgrade
|
||||
name = "Shuttle Route Optimisation Upgrade"
|
||||
desc = "A disk that allows for calculating shorter routes when inserted into a flight control console."
|
||||
id = "disk_shuttle_route"
|
||||
build_type = PROTOLATHE
|
||||
materials = list(/datum/material/iron = 1000, /datum/material/glass = 1000)
|
||||
build_path = /obj/item/shuttle_route_optimisation
|
||||
category = list("Equipment")
|
||||
departmental_flags = DEPARTMENTAL_FLAG_SCIENCE | DEPARTMENTAL_FLAG_ENGINEERING
|
||||
|
||||
/datum/design/shuttle_speed_upgrade_hyper
|
||||
name = "Shuttle Bluespace Hyperlane Optimisation Upgrade"
|
||||
desc = "A disk that allows for calculating shorter routes when inserted into a flight control console. This one abuses bluespace hyperlanes for increased efficiency."
|
||||
id = "disk_shuttle_route_hyper"
|
||||
build_type = PROTOLATHE
|
||||
materials = list(/datum/material/iron = 1000, /datum/material/glass = 1000)
|
||||
build_path = /obj/item/shuttle_route_optimisation/hyperlane
|
||||
category = list("Equipment")
|
||||
departmental_flags = DEPARTMENTAL_FLAG_SCIENCE | DEPARTMENTAL_FLAG_ENGINEERING
|
||||
|
||||
/datum/design/shuttle_speed_upgrade_void
|
||||
name = "Shuttle Voidspace Optimisation Upgrade"
|
||||
desc = "A disk that allows for calculating shorter routes when inserted into a flight control console. This one access voidspace for increased efficiency."
|
||||
id = "disk_shuttle_route_void"
|
||||
build_type = PROTOLATHE
|
||||
materials = list(/datum/material/iron = 1000, /datum/material/glass = 1000)
|
||||
build_path = /obj/item/shuttle_route_optimisation/void
|
||||
category = list("Equipment")
|
||||
departmental_flags = DEPARTMENTAL_FLAG_SCIENCE | DEPARTMENTAL_FLAG_ENGINEERING
|
||||
@@ -42,6 +42,16 @@
|
||||
category = list("Tool Designs")
|
||||
departmental_flags = DEPARTMENTAL_FLAG_ENGINEERING
|
||||
|
||||
/datum/design/shuttlecreator
|
||||
name = "Rapid Shuttle Designator"
|
||||
desc = "An advanced device capable of defining areas for use in the creation of shuttles"
|
||||
id = "shuttle_creator"
|
||||
build_path = /obj/item/shuttle_creator
|
||||
build_type = PROTOLATHE
|
||||
materials = list(/datum/material/iron = 8000, /datum/material/titanium = 5000, /datum/material/bluespace = 5000)
|
||||
category = list("Tool Designs")
|
||||
departmental_flags = DEPARTMENTAL_FLAG_SCIENCE | DEPARTMENTAL_FLAG_ENGINEERING
|
||||
|
||||
/datum/design/handdrill
|
||||
name = "Hand Drill"
|
||||
desc = "A small electric hand drill with an interchangeable screwdriver and bolt bit"
|
||||
|
||||
@@ -63,3 +63,36 @@
|
||||
prereq_ids = list("bluespace_warping", "syndicate_basic")
|
||||
design_ids = list("desynchronizer")
|
||||
research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500)
|
||||
|
||||
/////////////////////////shuttle tech/////////////////////////
|
||||
/datum/techweb_node/basic_shuttle_tech
|
||||
id = "basic_shuttle"
|
||||
display_name = "Basic Shuttle Research"
|
||||
description = "Research the technology required to create and use basic shuttles."
|
||||
prereq_ids = list("bluespace_travel", "adv_engi")
|
||||
design_ids = list("shuttle_creator", "engine_plasma", "engine_heater", "shuttle_control", "shuttle_docker")
|
||||
research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 5000)
|
||||
|
||||
/datum/techweb_node/shuttle_route_upgrade
|
||||
id = "shuttle_route_upgrade"
|
||||
display_name = "Route Optimisation Upgrade"
|
||||
description = "Research into bluespace tunnelling, allowing us to reduce flight times by up to 20%!"
|
||||
prereq_ids = list("basic_shuttle")
|
||||
design_ids = list("disk_shuttle_route")
|
||||
research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500)
|
||||
|
||||
/datum/techweb_node/shuttle_route_upgrade_hyper
|
||||
id = "shuttle_route_upgrade_hyper"
|
||||
display_name = "Hyperlane Optimisation Upgrade"
|
||||
description = "Research into bluespace hyperlane, allowing us to reduce flight times by up to 40%!"
|
||||
prereq_ids = list("shuttle_route_upgrade", "micro_bluespace")
|
||||
design_ids = list("disk_shuttle_route_hyper")
|
||||
research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 5000)
|
||||
|
||||
/datum/techweb_node/shuttle_route_upgrade_void
|
||||
id = "shuttle_route_upgrade_void"
|
||||
display_name = "Nullspace Breaching Upgrade"
|
||||
description = "Research into voidspace tunnelling, allowing us to significantly reduce flight times."
|
||||
prereq_ids = list("shuttle_route_upgrade_hyper", "alientech")
|
||||
design_ids = list("disk_shuttle_route_void", "engine_void")
|
||||
research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 12500)
|
||||
|
||||
@@ -71,6 +71,6 @@
|
||||
to_chat(user, "<span class='notice'>You fried the consoles ID checking system.</span>")
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/computer/shuttle/proc/connect_to_shuttle(obj/docking_port/mobile/port, obj/docking_port/stationary/dock, idnum, override=FALSE)
|
||||
/obj/machinery/computer/shuttle/connect_to_shuttle(obj/docking_port/mobile/port, obj/docking_port/stationary/dock, idnum, override=FALSE)
|
||||
if(port && (shuttleId == initial(shuttleId) || override))
|
||||
shuttleId = port.id
|
||||
268
code/modules/shuttle/custom_shuttle.dm
Normal file
268
code/modules/shuttle/custom_shuttle.dm
Normal file
@@ -0,0 +1,268 @@
|
||||
#define Z_DIST 500
|
||||
#define CUSTOM_ENGINES_START_TIME 65
|
||||
#define CALCULATE_STATS_COOLDOWN 2
|
||||
|
||||
/obj/machinery/computer/custom_shuttle
|
||||
name = "nanotrasen shuttle flight controller"
|
||||
desc = "A terminal used to fly shuttles defined by the Shuttle Zoning Designator"
|
||||
circuit = /obj/item/circuitboard/computer/shuttle/flight_control
|
||||
icon_screen = "shuttle"
|
||||
icon_keyboard = "tech_key"
|
||||
light_color = LIGHT_COLOR_CYAN
|
||||
req_access = list( )
|
||||
var/shuttleId
|
||||
var/possible_destinations = "whiteship_home"
|
||||
var/admin_controlled
|
||||
var/no_destination_swap = 0
|
||||
var/calculated_mass = 0
|
||||
var/calculated_dforce = 0
|
||||
var/calculated_speed = 0
|
||||
var/calculated_engine_count = 0
|
||||
var/calculated_consumption = 0
|
||||
var/calculated_cooldown = 0
|
||||
var/calculated_non_operational_thrusters = 0
|
||||
var/calculated_fuel_less_thrusters = 0
|
||||
var/target_fuel_cost = 0
|
||||
var/targetLocation
|
||||
var/datum/browser/popup
|
||||
|
||||
var/stat_calc_cooldown = 0
|
||||
|
||||
//Upgrades
|
||||
var/distance_multiplier = 1
|
||||
|
||||
/obj/machinery/computer/custom_shuttle/examine(mob/user)
|
||||
. = ..()
|
||||
. += distance_multiplier < 1 ? "Bluespace shortcut module installed. Route is [distance_multiplier]x the original length." : ""
|
||||
|
||||
/obj/machinery/computer/custom_shuttle/ui_interact(mob/user)
|
||||
var/list/options = params2list(possible_destinations)
|
||||
var/obj/docking_port/mobile/M = SSshuttle.getShuttle(shuttleId)
|
||||
var/dat = "[M ? "Current Location : [M.getStatusText()]" : "Shuttle link required."]<br><br>"
|
||||
if(M)
|
||||
dat += "<A href='?src=[REF(src)];calculate=1'>Run Flight Calculations</A><br>"
|
||||
dat += "<b>Shuttle Data</b><hr>"
|
||||
dat += "Shuttle Mass: [calculated_mass/10]tons<br>"
|
||||
dat += "Engine Force: [calculated_dforce]kN ([calculated_engine_count] engines)<br>"
|
||||
dat += "Sublight Speed: [calculated_speed]ms<sup>-1</sup><br>"
|
||||
dat += calculated_speed < 1 ? "<b>INSUFFICIENT ENGINE POWER</b><br>" : ""
|
||||
dat += calculated_non_operational_thrusters > 0 ? "<b>Warning: [calculated_non_operational_thrusters] thrusters offline.</b><br>" : ""
|
||||
dat += "Fuel Consumption: [calculated_consumption]units per distance<br>"
|
||||
dat += "Engine Cooldown: [calculated_cooldown]s<hr>"
|
||||
var/destination_found
|
||||
for(var/obj/docking_port/stationary/S in SSshuttle.stationary)
|
||||
if(!options.Find(S.id))
|
||||
continue
|
||||
if(!M.check_dock(S, silent=TRUE))
|
||||
continue
|
||||
if(calculated_speed == 0)
|
||||
break
|
||||
destination_found = TRUE
|
||||
var/dist = round(calculateDistance(S))
|
||||
dat += "<A href='?src=[REF(src)];setloc=[S.id]'>Target [S.name] (Dist: [dist] | Fuel Cost: [round(dist * calculated_consumption)] | Time: [round(dist / calculated_speed)])</A><br>"
|
||||
if(!destination_found)
|
||||
dat += "<B>No valid destinations</B><br>"
|
||||
dat += "<hr>[targetLocation ? "Target Location : [targetLocation]" : "No Target Location"]"
|
||||
dat += "<hr><A href='?src=[REF(src)];fly=1'>Initate Flight</A><br>"
|
||||
dat += "<A href='?src=[REF(user)];mach_close=computer'>Close</a>"
|
||||
|
||||
popup = new(user, "computer", M ? M.name : "shuttle", 350, 450)
|
||||
popup.set_content("<center>[dat]</center>")
|
||||
popup.set_title_image(usr.browse_rsc_icon(src.icon, src.icon_state))
|
||||
popup.open()
|
||||
|
||||
/obj/machinery/computer/custom_shuttle/Topic(href, href_list)
|
||||
if(..())
|
||||
return
|
||||
usr.set_machine(src)
|
||||
src.add_fingerprint(usr)
|
||||
if(!allowed(usr))
|
||||
to_chat(usr, "<span class='danger'>Access denied.</span>")
|
||||
return
|
||||
|
||||
if(href_list["calculate"])
|
||||
calculateStats()
|
||||
ui_interact(usr)
|
||||
return
|
||||
var/obj/docking_port/mobile/M = SSshuttle.getShuttle(shuttleId)
|
||||
if(!M)
|
||||
return
|
||||
if(M.launch_status == ENDGAME_LAUNCHED)
|
||||
return
|
||||
if(href_list["setloc"])
|
||||
SetTargetLocation(href_list["setloc"])
|
||||
ui_interact(usr)
|
||||
return
|
||||
else if(href_list["fly"])
|
||||
Fly()
|
||||
ui_interact(usr)
|
||||
return
|
||||
|
||||
/obj/machinery/computer/custom_shuttle/proc/calculateDistance(var/obj/docking_port/stationary/port)
|
||||
var/deltaX = port.x - x
|
||||
var/deltaY = port.y - y
|
||||
var/deltaZ = (port.z - z) * Z_DIST
|
||||
return sqrt(deltaX * deltaX + deltaY * deltaY + deltaZ * deltaZ) * distance_multiplier
|
||||
|
||||
/obj/machinery/computer/custom_shuttle/proc/linkShuttle(var/new_id)
|
||||
shuttleId = new_id
|
||||
possible_destinations = "whiteship_home;shuttle[new_id]_custom"
|
||||
|
||||
/obj/machinery/computer/custom_shuttle/proc/calculateStats(var/useFuel = FALSE, var/dist = 0, var/ignore_cooldown = FALSE)
|
||||
if(!ignore_cooldown && stat_calc_cooldown >= world.time)
|
||||
to_chat(usr, "<span>You are using this too fast, please slow down</span>")
|
||||
return
|
||||
stat_calc_cooldown = world.time + CALCULATE_STATS_COOLDOWN
|
||||
var/obj/docking_port/mobile/M = SSshuttle.getShuttle(shuttleId)
|
||||
if(!M)
|
||||
return FALSE
|
||||
//Reset data
|
||||
calculated_mass = 0
|
||||
calculated_dforce = 0
|
||||
calculated_speed = 0
|
||||
calculated_engine_count = 0
|
||||
calculated_consumption = 0
|
||||
calculated_cooldown = 0
|
||||
calculated_fuel_less_thrusters = 0
|
||||
calculated_non_operational_thrusters = 0
|
||||
//Calculate all the data
|
||||
var/list/areas = M.shuttle_areas
|
||||
for(var/shuttleArea in areas)
|
||||
calculated_mass += length(get_area_turfs(shuttleArea))
|
||||
for(var/obj/machinery/shuttle/engine/E in shuttleArea)
|
||||
E.check_setup()
|
||||
if(!E.thruster_active) //Skipover thrusters with no valid heater
|
||||
calculated_non_operational_thrusters ++
|
||||
continue
|
||||
if(E.attached_heater)
|
||||
var/obj/machinery/atmospherics/components/unary/shuttle/heater/resolvedHeater = E.attached_heater.resolve()
|
||||
if(resolvedHeater && !resolvedHeater.hasFuel(dist * E.fuel_use) && useFuel)
|
||||
calculated_fuel_less_thrusters ++
|
||||
continue
|
||||
calculated_engine_count++
|
||||
calculated_dforce += E.thrust
|
||||
calculated_consumption += E.fuel_use
|
||||
calculated_cooldown = max(calculated_cooldown, E.cooldown)
|
||||
//This should really be accelleration, but its a 2d spessman game so who cares
|
||||
if(calculated_mass == 0)
|
||||
return FALSE
|
||||
calculated_speed = (calculated_dforce*1000) / (calculated_mass*100)
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/computer/custom_shuttle/proc/consumeFuel(var/dist)
|
||||
var/obj/docking_port/mobile/M = SSshuttle.getShuttle(shuttleId)
|
||||
if(!M)
|
||||
return FALSE
|
||||
//Calculate all the data
|
||||
for(var/obj/machinery/shuttle/engine/shuttle_machine in GLOB.custom_shuttle_machines)
|
||||
shuttle_machine.check_setup()
|
||||
if(!shuttle_machine.thruster_active)
|
||||
continue
|
||||
if(get_area(M) != get_area(shuttle_machine))
|
||||
continue
|
||||
if(shuttle_machine.attached_heater)
|
||||
var/obj/machinery/atmospherics/components/unary/shuttle/heater/resolvedHeater = shuttle_machine.attached_heater.resolve()
|
||||
if(resolvedHeater && !resolvedHeater.hasFuel(dist * shuttle_machine.fuel_use))
|
||||
continue
|
||||
resolvedHeater?.consumeFuel(dist * shuttle_machine.fuel_use)
|
||||
shuttle_machine.fireEngine()
|
||||
|
||||
/obj/machinery/computer/custom_shuttle/proc/SetTargetLocation(var/newTarget)
|
||||
if(!(newTarget in params2list(possible_destinations)))
|
||||
log_admin("[usr] attempted to href dock exploit on [src] with target location \"[newTarget]\"")
|
||||
message_admins("[usr] just attempted to href dock exploit on [src] with target location \"[newTarget]\"")
|
||||
return
|
||||
targetLocation = newTarget
|
||||
say("Shuttle route calculated.")
|
||||
return
|
||||
|
||||
/obj/machinery/computer/custom_shuttle/proc/Fly()
|
||||
if(!targetLocation)
|
||||
return
|
||||
var/obj/docking_port/mobile/linkedShuttle = SSshuttle.getShuttle(shuttleId)
|
||||
if(!linkedShuttle)
|
||||
return
|
||||
if(linkedShuttle.mode != SHUTTLE_IDLE)
|
||||
return
|
||||
if(!calculateStats(TRUE, 0, TRUE))
|
||||
return
|
||||
if(calculated_fuel_less_thrusters > 0)
|
||||
say("Warning, [calculated_fuel_less_thrusters] do not have enough fuel for this journey, engine output may be limitted.")
|
||||
if(calculated_speed < 1)
|
||||
say("Insufficient engine power, shuttle requires [calculated_mass / 10]kN of thrust.")
|
||||
return
|
||||
var/obj/docking_port/stationary/targetPort = SSshuttle.getDock(targetLocation)
|
||||
if(!targetPort)
|
||||
return
|
||||
var/dist = calculateDistance(targetPort)
|
||||
var/time = min(max(round(dist / calculated_speed), 10), 90)
|
||||
linkedShuttle.callTime = time * 10
|
||||
linkedShuttle.rechargeTime = calculated_cooldown
|
||||
//We need to find the direction of this console to the port
|
||||
linkedShuttle.port_direction = angle2dir(dir2angle(dir) - (dir2angle(linkedShuttle.dir)) + 180)
|
||||
linkedShuttle.preferred_direction = NORTH
|
||||
linkedShuttle.ignitionTime = CUSTOM_ENGINES_START_TIME
|
||||
linkedShuttle.count_engines()
|
||||
linkedShuttle.hyperspace_sound(HYPERSPACE_WARMUP)
|
||||
var/throwForce = clamp((calculated_speed / 2) - 5, 0, 10)
|
||||
linkedShuttle.movement_force = list("KNOCKDOWN" = calculated_speed > 5 ? 3 : 0, "THROW" = throwForce)
|
||||
if(!(targetLocation in params2list(possible_destinations)))
|
||||
log_admin("[usr] attempted to launch a shuttle that has been affected by href dock exploit on [src] with target location \"[targetLocation]\"")
|
||||
message_admins("[usr] attempted to launch a shuttle that has been affected by href dock exploit on [src] with target location \"[targetLocation]\"")
|
||||
return
|
||||
switch(SSshuttle.moveShuttle(shuttleId, targetLocation, 1))
|
||||
if(0)
|
||||
consumeFuel(dist)
|
||||
say("Shuttle departing. Please stand away from the doors.")
|
||||
if(1)
|
||||
to_chat(usr, "<span class='warning'>Invalid shuttle requested.</span>")
|
||||
else
|
||||
to_chat(usr, "<span class='notice'>Unable to comply.</span>")
|
||||
return
|
||||
|
||||
/obj/machinery/computer/custom_shuttle/connect_to_shuttle(obj/docking_port/mobile/port, obj/docking_port/stationary/dock, idnum, override=FALSE)
|
||||
if(port && (shuttleId == initial(shuttleId) || override))
|
||||
linkShuttle(port.id)
|
||||
|
||||
//Custom shuttle docker locations
|
||||
/obj/machinery/computer/camera_advanced/shuttle_docker/custom
|
||||
name = "Shuttle Navigation Computer"
|
||||
desc = "Used to designate a precise transit location for private ships."
|
||||
lock_override = NONE
|
||||
whitelist_turfs = list(/turf/open/space,
|
||||
/turf/open/lava,
|
||||
/turf/open/floor/plating/beach,
|
||||
/turf/open/floor/plating/ashplanet,
|
||||
/turf/open/floor/plating/asteroid,
|
||||
/turf/open/floor/plating/lavaland_baseturf)
|
||||
jumpto_ports = list("whiteship_home" = 1)
|
||||
view_range = 12
|
||||
designate_time = 100
|
||||
circuit = /obj/item/circuitboard/computer/shuttle/docker
|
||||
|
||||
/obj/machinery/computer/camera_advanced/shuttle_docker/custom/Initialize()
|
||||
. = ..()
|
||||
GLOB.jam_on_wardec += src
|
||||
|
||||
/obj/machinery/computer/camera_advanced/shuttle_docker/custom/Destroy()
|
||||
GLOB.jam_on_wardec -= src
|
||||
return ..()
|
||||
|
||||
/obj/machinery/computer/camera_advanced/shuttle_docker/custom/placeLandingSpot()
|
||||
if(!shuttleId)
|
||||
return //Only way this would happen is if someone else delinks the console while in use somehow
|
||||
var/obj/docking_port/mobile/M = SSshuttle.getShuttle(shuttleId)
|
||||
if(M?.mode != SHUTTLE_IDLE)
|
||||
to_chat(usr, "<span class='warning'>You cannot target locations while in transit.</span>")
|
||||
return
|
||||
..()
|
||||
|
||||
/obj/machinery/computer/camera_advanced/shuttle_docker/custom/attack_hand(mob/user)
|
||||
if(!shuttleId)
|
||||
to_chat(user, "<span class='warning'>You must link the console to a shuttle first.</span>")
|
||||
return
|
||||
return ..()
|
||||
|
||||
/obj/machinery/computer/camera_advanced/shuttle_docker/custom/proc/linkShuttle(var/new_id)
|
||||
shuttleId = new_id
|
||||
shuttlePortId = "shuttle[new_id]_custom"
|
||||
@@ -253,7 +253,7 @@
|
||||
current_user.client.images -= remove_images
|
||||
current_user.client.images += add_images
|
||||
|
||||
/obj/machinery/computer/camera_advanced/shuttle_docker/proc/connect_to_shuttle(obj/docking_port/mobile/port, obj/docking_port/stationary/dock, idnum, override=FALSE)
|
||||
/obj/machinery/computer/camera_advanced/shuttle_docker/connect_to_shuttle(obj/docking_port/mobile/port, obj/docking_port/stationary/dock, idnum, override=FALSE)
|
||||
if(port && (shuttleId == initial(shuttleId) || override))
|
||||
shuttleId = port.id
|
||||
shuttlePortId = "[port.id]_custom"
|
||||
|
||||
@@ -11,17 +11,31 @@
|
||||
|
||||
resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF
|
||||
anchored = TRUE
|
||||
//
|
||||
/// The identifier of the port or ship.
|
||||
/// This will be used in numerous other places like the console,
|
||||
/// stationary ports and whatnot to tell them your ship's mobile
|
||||
/// port can be used in these places, or the docking port is compatible, etc.
|
||||
var/id
|
||||
// this should point -away- from the dockingport door, ie towards the ship
|
||||
///Common standard is for this to point -away- from the dockingport door, ie towards the ship
|
||||
dir = NORTH
|
||||
var/width = 0 //size of covered area, perpendicular to dir
|
||||
var/height = 0 //size of covered area, parallel to dir
|
||||
var/dwidth = 0 //position relative to covered area, perpendicular to dir
|
||||
var/dheight = 0 //position relative to covered area, parallel to dir
|
||||
///size of covered area, perpendicular to dir. You shouldn't modify this for mobile dockingports, set automatically.
|
||||
var/width = 0
|
||||
///size of covered area, parallel to dir. You shouldn't modify this for mobile dockingports, set automatically.
|
||||
var/height = 0
|
||||
///position relative to covered area, perpendicular to dir. You shouldn't modify this for mobile dockingports, set automatically.
|
||||
var/dwidth = 0
|
||||
///position relative to covered area, parallel to dir. You shouldn't modify this for mobile dockingports, set automatically.
|
||||
var/dheight = 0
|
||||
|
||||
var/area_type
|
||||
var/hidden = FALSE //are we invisible to shuttle navigation computers?
|
||||
///are we invisible to shuttle navigation computers?
|
||||
var/hidden = FALSE
|
||||
|
||||
///Delete this port after ship fly off.
|
||||
var/delete_after = FALSE
|
||||
|
||||
/obj/docking_port/proc/get_save_vars()
|
||||
return list("pixel_x", "pixel_y", "dir", "name", "req_access", "req_access_txt", "piping_layer", "color", "icon_state", "pipe_color", "amount", "width", "height", "dwidth", "dheight")
|
||||
|
||||
//these objects are indestructible
|
||||
/obj/docking_port/Destroy(force)
|
||||
@@ -155,8 +169,6 @@
|
||||
/obj/docking_port/stationary
|
||||
name = "dock"
|
||||
|
||||
area_type = SHUTTLE_DEFAULT_UNDERLYING_AREA
|
||||
|
||||
var/last_dock_time
|
||||
|
||||
var/datum/map_template/shuttle/roundstart_template
|
||||
@@ -169,6 +181,9 @@
|
||||
id = "[SSshuttle.stationary.len]"
|
||||
if(name == "dock")
|
||||
name = "dock[SSshuttle.stationary.len]"
|
||||
if(!area_type)
|
||||
var/area/place = get_area(src)
|
||||
area_type = place?.type // We might be created in nullspace
|
||||
|
||||
if(mapload)
|
||||
for(var/turf/T in return_turfs())
|
||||
@@ -183,6 +198,13 @@
|
||||
SSshuttle.stationary -= src
|
||||
. = ..()
|
||||
|
||||
/obj/docking_port/stationary/Moved(atom/oldloc, dir, forced)
|
||||
. = ..()
|
||||
if(area_type) // We already have one
|
||||
return
|
||||
var/area/newarea = get_area(src)
|
||||
area_type = newarea?.type
|
||||
|
||||
/obj/docking_port/stationary/proc/load_roundstart()
|
||||
if(json_key)
|
||||
var/sid = SSmapping.config.shuttles[json_key]
|
||||
@@ -196,9 +218,6 @@
|
||||
if(!roundstart_template)
|
||||
CRASH("Invalid path ([roundstart_template]) passed to docking port.")
|
||||
|
||||
if(roundstart_template)
|
||||
SSshuttle.manipulator.action_load(roundstart_template, src)
|
||||
|
||||
//returns first-found touching shuttleport
|
||||
/obj/docking_port/stationary/get_docked()
|
||||
. = locate(/obj/docking_port/mobile) in loc
|
||||
@@ -235,16 +254,25 @@
|
||||
|
||||
var/list/shuttle_areas
|
||||
|
||||
var/timer //used as a timer (if you want time left to complete move, use timeLeft proc)
|
||||
///used as a timer (if you want time left to complete move, use timeLeft proc)
|
||||
var/timer
|
||||
var/last_timer_length
|
||||
///current shuttle mode
|
||||
var/mode = SHUTTLE_IDLE
|
||||
///time spent in transit (deciseconds). Should not be lower then 10 seconds without editing the animation of the hyperspace ripples.
|
||||
var/callTime = 100
|
||||
/// time spent "starting the engines". Also rate limits how often we try to reserve transit space if its ever full of transiting shuttles.
|
||||
var/ignitionTime = 55
|
||||
/// time spent after arrival before being able to begin ignition
|
||||
var/rechargeTime = 0
|
||||
/// time spent after transit 'landing' before actually arriving
|
||||
var/prearrivalTime = 0
|
||||
|
||||
var/mode = SHUTTLE_IDLE //current shuttle mode
|
||||
var/callTime = 100 //time spent in transit (deciseconds). Should not be lower then 10 seconds without editing the animation of the hyperspace ripples.
|
||||
var/ignitionTime = 55 // time spent "starting the engines". Also rate limits how often we try to reserve transit space if its ever full of transiting shuttles.
|
||||
|
||||
// The direction the shuttle prefers to travel in
|
||||
/// The direction the shuttle prefers to travel in, ie what direction
|
||||
/// the animation will cause it to appear to be traveling in
|
||||
var/preferred_direction = NORTH
|
||||
// And the angle from the front of the shuttle to the port
|
||||
/// relative direction of the docking port from the front of the shuttle
|
||||
/// NORTH is towards front, EAST would be starboard side, WEST port, etc.
|
||||
var/port_direction = NORTH
|
||||
|
||||
var/obj/docking_port/stationary/destination
|
||||
@@ -254,13 +282,16 @@
|
||||
|
||||
var/launch_status = NOLAUNCH
|
||||
|
||||
var/list/movement_force = list("KNOCKDOWN" = 3, "THROW" = 2)
|
||||
///Whether or not you want your ship to knock people down, and also whether it will throw them several tiles upon launching.
|
||||
var/list/movement_force = list("KNOCKDOWN" = 3, "THROW" = 0)
|
||||
|
||||
var/list/ripples = list()
|
||||
var/engine_coeff = 1 //current engine coeff
|
||||
var/current_engines = 0 //current engine power
|
||||
var/initial_engines = 0 //initial engine power
|
||||
var/can_move_docking_ports = FALSE //if this shuttle can move docking ports other than the one it is docked at
|
||||
var/engine_coeff = 1
|
||||
var/current_engines = 0
|
||||
var/initial_engines = 0
|
||||
var/list/engine_list = list()
|
||||
///if this shuttle can move docking ports other than the one it is docked at
|
||||
var/can_move_docking_ports = FALSE
|
||||
var/list/hidden_turfs = list()
|
||||
|
||||
/obj/docking_port/mobile/proc/register()
|
||||
@@ -308,14 +339,12 @@
|
||||
id = "[id][idnum]"
|
||||
if(name == initial(name))
|
||||
name = "[name] [idnum]"
|
||||
for(var/i in shuttle_areas)
|
||||
var/area/place = i
|
||||
for(var/obj/machinery/computer/shuttle/comp in place)
|
||||
comp.connect_to_shuttle(src, dock, idnum)
|
||||
for(var/obj/machinery/computer/camera_advanced/shuttle_docker/comp in place)
|
||||
comp.connect_to_shuttle(src, dock, idnum)
|
||||
for(var/obj/machinery/status_display/shuttle/sd in place)
|
||||
sd.connect_to_shuttle(src, dock, idnum)
|
||||
for(var/place in shuttle_areas)
|
||||
var/area/area = place
|
||||
area.connect_to_shuttle(src, dock, idnum, FALSE)
|
||||
for(var/each in place)
|
||||
var/atom/atom = each
|
||||
atom.connect_to_shuttle(src, dock, idnum, FALSE)
|
||||
|
||||
|
||||
//this is a hook for custom behaviour. Maybe at some point we could add checks to see if engines are intact
|
||||
@@ -422,6 +451,9 @@
|
||||
if(S1)
|
||||
if(initiate_docking(S1) != DOCKING_SUCCESS)
|
||||
WARNING("shuttle \"[id]\" could not enter transit space. Docked at [S0 ? S0.id : "null"]. Transit dock [S1 ? S1.id : "null"].")
|
||||
else
|
||||
if(S0.delete_after)
|
||||
qdel(S0, TRUE)
|
||||
else
|
||||
previous = S0
|
||||
else
|
||||
@@ -536,7 +568,11 @@
|
||||
// If we can't dock or we don't have a transit slot, wait for 20 ds,
|
||||
// then try again
|
||||
switch(mode)
|
||||
if(SHUTTLE_CALL)
|
||||
if(SHUTTLE_CALL, SHUTTLE_PREARRIVAL)
|
||||
if(prearrivalTime && mode != SHUTTLE_PREARRIVAL)
|
||||
mode = SHUTTLE_PREARRIVAL
|
||||
setTimer(prearrivalTime)
|
||||
return
|
||||
var/error = initiate_docking(destination, preferred_direction)
|
||||
if(error && error & (DOCKING_NULL_DESTINATION | DOCKING_NULL_SOURCE))
|
||||
var/msg = "A mobile dock in transit exited initiate_docking() with an error. This is most likely a mapping problem: Error: [error], ([src]) ([previous][ADMIN_JMP(previous)] -> [destination][ADMIN_JMP(destination)])"
|
||||
@@ -547,6 +583,10 @@
|
||||
else if(error)
|
||||
setTimer(20)
|
||||
return
|
||||
if(rechargeTime)
|
||||
mode = SHUTTLE_RECHARGING
|
||||
setTimer(rechargeTime)
|
||||
return
|
||||
if(SHUTTLE_RECALL)
|
||||
if(initiate_docking(previous) != DOCKING_SUCCESS)
|
||||
setTimer(20)
|
||||
@@ -649,6 +689,10 @@
|
||||
return "ESC"
|
||||
if(SHUTTLE_STRANDED)
|
||||
return "ERR"
|
||||
if(SHUTTLE_RECHARGING)
|
||||
return "RCH"
|
||||
if(SHUTTLE_PREARRIVAL)
|
||||
return "LDN"
|
||||
return ""
|
||||
|
||||
// returns 5-letter timer string, used by status screens and mob status panel
|
||||
@@ -660,14 +704,14 @@
|
||||
if(timeleft > 1 HOURS)
|
||||
return "--:--"
|
||||
else if(timeleft > 0)
|
||||
return "[add_leading(num2text((timeleft / 60) % 60), 2, "0")]:[add_leading(num2text(timeleft % 60), 2, "0")]"
|
||||
return "[add_leading(num2text((timeleft / 60) % 60), 2, "0")]:[add_leading(num2text(timeleft % 60), 2, " ")]"
|
||||
else
|
||||
return "00:00"
|
||||
|
||||
|
||||
/obj/docking_port/mobile/proc/getStatusText()
|
||||
var/obj/docking_port/stationary/dockedAt = get_docked()
|
||||
|
||||
var/docked_at = dockedAt?.name || "unknown"
|
||||
if(istype(dockedAt, /obj/docking_port/stationary/transit))
|
||||
if (timeLeft() > 1 HOURS)
|
||||
return "hyperspace"
|
||||
@@ -678,8 +722,10 @@
|
||||
else
|
||||
dst = destination
|
||||
. = "transit towards [dst?.name || "unknown location"] ([getTimerStr()])"
|
||||
else if(mode == SHUTTLE_RECHARGING)
|
||||
return "[docked_at], recharging [getTimerStr()]"
|
||||
else
|
||||
return dockedAt?.name || "unknown"
|
||||
return docked_at
|
||||
|
||||
|
||||
/obj/docking_port/mobile/proc/getDbgStatusText()
|
||||
@@ -711,19 +757,47 @@
|
||||
return null
|
||||
|
||||
/obj/docking_port/mobile/proc/hyperspace_sound(phase, list/areas)
|
||||
var/s
|
||||
var/selected_sound
|
||||
switch(phase)
|
||||
if(HYPERSPACE_WARMUP)
|
||||
s = 'sound/effects/hyperspace_begin.ogg'
|
||||
selected_sound = "hyperspace_begin"
|
||||
if(HYPERSPACE_LAUNCH)
|
||||
s = 'sound/effects/hyperspace_progress.ogg'
|
||||
selected_sound = "hyperspace_progress"
|
||||
if(HYPERSPACE_END)
|
||||
s = 'sound/effects/hyperspace_end.ogg'
|
||||
selected_sound = "hyperspace_end"
|
||||
else
|
||||
CRASH("Invalid hyperspace sound phase: [phase]")
|
||||
// This previously was played from each door at max volume, and was one of the worst things I had ever seen.
|
||||
// Now it's instead played from the nearest engine if close, or the first engine in the list if far since it doesn't really matter.
|
||||
// Or a door if for some reason the shuttle has no engine, fuck oh hi daniel fuck it
|
||||
var/range = (engine_coeff * max(width, height))
|
||||
var/long_range = range * 2.5
|
||||
var/atom/distant_source
|
||||
if(LAZYLEN(engine_list))
|
||||
distant_source = engine_list[1]
|
||||
else
|
||||
for(var/A in areas)
|
||||
for(var/obj/machinery/door/E in A) //dumb, I know, but playing it on the engines doesn't do it justice
|
||||
playsound(E, s, 100, FALSE, max(width, height) - world.view)
|
||||
distant_source = locate(/obj/machinery/door) in A
|
||||
if(distant_source)
|
||||
break
|
||||
|
||||
if(distant_source)
|
||||
for(var/mob/M in SSmobs.clients_by_zlevel[z])
|
||||
var/dist_far = get_dist(M, distant_source)
|
||||
if(dist_far <= long_range && dist_far > range)
|
||||
M.playsound_local(distant_source, "sound/effects/[selected_sound]_distance.ogg", 100, falloff = 20)
|
||||
else if(dist_far <= range)
|
||||
var/source
|
||||
if(engine_list.len == 0)
|
||||
source = distant_source
|
||||
else
|
||||
var/closest_dist = 10000
|
||||
for(var/obj/O in engine_list)
|
||||
var/dist_near = get_dist(M, O)
|
||||
if(dist_near < closest_dist)
|
||||
source = O
|
||||
closest_dist = dist_near
|
||||
M.playsound_local(source, "sound/effects/[selected_sound].ogg", 100, falloff = range / 2)
|
||||
|
||||
// Losing all initial engines should get you 2
|
||||
// Adding another set of engines at 0.5 time
|
||||
@@ -743,7 +817,12 @@
|
||||
var/area/shuttle/areaInstance = thing
|
||||
for(var/obj/structure/shuttle/engine/E in areaInstance.contents)
|
||||
if(!QDELETED(E))
|
||||
engine_list += E
|
||||
. += E.engine_power
|
||||
for(var/obj/machinery/shuttle/engine/E in areaInstance.contents)
|
||||
if(!QDELETED(E))
|
||||
engine_list += E
|
||||
. += E.thruster_active ? 1 : 0
|
||||
|
||||
// Double initial engines to get to 0.5 minimum
|
||||
// Lose all initial engines to get to 2
|
||||
@@ -768,7 +847,7 @@
|
||||
|
||||
/obj/docking_port/mobile/proc/in_flight()
|
||||
switch(mode)
|
||||
if(SHUTTLE_CALL,SHUTTLE_RECALL)
|
||||
if(SHUTTLE_CALL,SHUTTLE_RECALL,SHUTTLE_PREARRIVAL)
|
||||
return TRUE
|
||||
if(SHUTTLE_IDLE,SHUTTLE_IGNITING)
|
||||
return FALSE
|
||||
|
||||
370
code/modules/shuttle/shuttle_creation/shuttle_creator.dm
Normal file
370
code/modules/shuttle/shuttle_creation/shuttle_creator.dm
Normal file
@@ -0,0 +1,370 @@
|
||||
#define SHUTTLE_CREATOR_MAX_SIZE CONFIG_GET(number/max_shuttle_size)
|
||||
#define CUSTOM_SHUTTLE_LIMIT CONFIG_GET(number/max_shuttle_count)
|
||||
#define CARDINAL_DIRECTIONS_X list(1, 0, -1, 0)
|
||||
#define CARDINAL_DIRECTIONS_Y list(0, 1, 0, -1)
|
||||
|
||||
GLOBAL_VAR_INIT(custom_shuttle_count, 0) //The amount of custom shuttles created to prevent creating hundreds
|
||||
GLOBAL_LIST_EMPTY(custom_shuttle_machines) //Machines that require updating (Heaters, engines)
|
||||
|
||||
//============ Shuttle Creator Object ============
|
||||
/obj/item/shuttle_creator
|
||||
name = "Rapid Shuttle Designator"
|
||||
icon = 'icons/obj/tools.dmi'
|
||||
icon_state = "rsd"
|
||||
lefthand_file = 'icons/mob/inhands/equipment/tools_lefthand.dmi'
|
||||
righthand_file = 'icons/mob/inhands/equipment/tools_righthand.dmi'
|
||||
desc = "A device used to define the area required for custom ships. Uses bluespace crystals to create bluespace-capable ships."
|
||||
density = FALSE
|
||||
anchored = FALSE
|
||||
flags_1 = CONDUCT_1
|
||||
item_flags = NOBLUDGEON
|
||||
force = 0
|
||||
throwforce = 8
|
||||
throw_speed = 3
|
||||
throw_range = 5
|
||||
w_class = WEIGHT_CLASS_NORMAL
|
||||
req_access_txt = "11"
|
||||
armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 100, "acid" = 50)
|
||||
resistance_flags = FIRE_PROOF
|
||||
var/ready = TRUE
|
||||
//pre-designation
|
||||
var/override_max_shuttles = FALSE
|
||||
var/obj/machinery/computer/camera_advanced/shuttle_creator/internal_shuttle_creator
|
||||
//During designation
|
||||
var/overwritten_area = /area/space
|
||||
var/list/loggedTurfs = list()
|
||||
var/loggedOldArea
|
||||
var/recorded_shuttle_area
|
||||
var/datum/shuttle_creator_overlay_holder/overlay_holder
|
||||
//After designation
|
||||
var/linkedShuttleId
|
||||
|
||||
/obj/item/shuttle_creator/Initialize()
|
||||
. = ..()
|
||||
internal_shuttle_creator = new()
|
||||
internal_shuttle_creator.owner_rsd = src
|
||||
overlay_holder = new()
|
||||
|
||||
/obj/item/shuttle_creator/Destroy()
|
||||
. = ..()
|
||||
if(internal_shuttle_creator)
|
||||
internal_shuttle_creator.owner_rsd = null
|
||||
QDEL_NULL(internal_shuttle_creator)
|
||||
if(overlay_holder)
|
||||
QDEL_NULL(overlay_holder)
|
||||
|
||||
/obj/item/shuttle_creator/attack_self(mob/user)
|
||||
..()
|
||||
if(linkedShuttleId)
|
||||
return
|
||||
if(GLOB.custom_shuttle_count > CUSTOM_SHUTTLE_LIMIT && !override_max_shuttles)
|
||||
to_chat(user, "<span class='warning'>Too many shuttles have been created.</span>")
|
||||
message_admins("[ADMIN_FLW(user)] attempted to create a shuttle, however [CUSTOM_SHUTTLE_LIMIT] have already been created.")
|
||||
return
|
||||
if(!internal_shuttle_creator)
|
||||
return
|
||||
overlay_holder.add_client(user.client)
|
||||
internal_shuttle_creator.attack_hand(user)
|
||||
|
||||
/obj/item/shuttle_creator/afterattack(atom/target, mob/user, proximity_flag)
|
||||
. = ..()
|
||||
if(!ready)
|
||||
to_chat(user, "<span class='warning'>You need to define a shuttle area first.</span>")
|
||||
return
|
||||
if(!proximity_flag)
|
||||
return
|
||||
if(istype(target, /obj/machinery/computer/custom_shuttle))
|
||||
if(!linkedShuttleId)
|
||||
to_chat(user, "<span class='warning'>Error, no defined shuttle linked to device</span>")
|
||||
return
|
||||
var/obj/machinery/computer/custom_shuttle/console = target
|
||||
console.linkShuttle(linkedShuttleId)
|
||||
to_chat(user, "<span class='notice'>Console linked successfully!</span>")
|
||||
return
|
||||
else if(istype(target, /obj/machinery/computer/camera_advanced/shuttle_docker/custom))
|
||||
if(!linkedShuttleId)
|
||||
to_chat(user, "<span class='warning'>Error, no defined shuttle linked to device</span>")
|
||||
return
|
||||
var/obj/machinery/computer/camera_advanced/shuttle_docker/custom/console = target
|
||||
console.linkShuttle(linkedShuttleId)
|
||||
to_chat(user, "<span class='notice'>Console linked successfully!</span>")
|
||||
return
|
||||
to_chat(user, "<span class='warning'>The [src] bleeps. Select an airlock to create a docking port, or a valid machine to link.</span>")
|
||||
return
|
||||
|
||||
//=========== shuttle designation actions ============
|
||||
/obj/item/shuttle_creator/proc/calculate_bounds(obj/docking_port/mobile/port)
|
||||
if(!port || !istype(port, /obj/docking_port/mobile))
|
||||
return FALSE
|
||||
//Heights is the distance away from the port
|
||||
//width is the distance perpendicular to the port
|
||||
var/minX = INFINITY
|
||||
var/maxX = 0
|
||||
var/minY = INFINITY
|
||||
var/maxY = 0
|
||||
for(var/turf/T in loggedTurfs)
|
||||
minX = min(T.x, minX)
|
||||
maxX = max(T.x, maxX)
|
||||
minY = min(T.y, minY)
|
||||
maxY = max(T.y, maxY)
|
||||
//Make sure shuttle was actually found.
|
||||
if(maxX == INFINITY || maxY == INFINITY)
|
||||
return FALSE
|
||||
minX--
|
||||
minY--
|
||||
var/width = maxX - minX
|
||||
var/height = maxY - minY
|
||||
var/offset_x = port.x - minX
|
||||
var/offset_y = port.y - minY
|
||||
switch(port.dir) //Source: code/datums/shuttles.dm line 77 (14/03/2020) :)
|
||||
if(NORTH)
|
||||
port.width = width
|
||||
port.height = height
|
||||
port.dwidth = offset_x - 1
|
||||
port.dheight = offset_y - 1
|
||||
if(EAST)
|
||||
port.width = height
|
||||
port.height = width
|
||||
port.dwidth = height - offset_y
|
||||
port.dheight = offset_x - 1
|
||||
if(SOUTH)
|
||||
port.width = width
|
||||
port.height = height
|
||||
port.dwidth = width - offset_x
|
||||
port.dheight = height - offset_y
|
||||
if(WEST)
|
||||
port.width = height
|
||||
port.height = width
|
||||
port.dwidth = offset_y - 1
|
||||
port.dheight = width - offset_x
|
||||
return TRUE
|
||||
|
||||
//Go through all the all_turfs and check which direction doesn't have the shuttle
|
||||
/obj/item/shuttle_creator/proc/getNonShuttleDirection(turf/targetTurf)
|
||||
var/position = null
|
||||
if(!(get_offset_target_turf(targetTurf, 0, 1) in loggedTurfs))
|
||||
if(position != null)
|
||||
return null
|
||||
position = NORTH
|
||||
if(!(get_offset_target_turf(targetTurf, 0, -1) in loggedTurfs))
|
||||
if(position != null)
|
||||
return null
|
||||
position = SOUTH
|
||||
if(!(get_offset_target_turf(targetTurf, 1, 0) in loggedTurfs))
|
||||
if(position != null)
|
||||
return null
|
||||
position = EAST
|
||||
if(!(get_offset_target_turf(targetTurf, -1, 0) in loggedTurfs))
|
||||
if(position != null)
|
||||
return null
|
||||
position = WEST
|
||||
return position
|
||||
|
||||
/obj/item/shuttle_creator/proc/invertDir(var/input_dir)
|
||||
if(input_dir == NORTH)
|
||||
return SOUTH
|
||||
else if(input_dir == SOUTH)
|
||||
return NORTH
|
||||
else if(input_dir == EAST)
|
||||
return WEST
|
||||
else if(input_dir == WEST)
|
||||
return EAST
|
||||
return null
|
||||
|
||||
/obj/item/shuttle_creator/proc/shuttle_create_docking_port(atom/target, mob/user)
|
||||
|
||||
if(loggedTurfs.len == 0 || !recorded_shuttle_area)
|
||||
to_chat(user, "<span class='warning'>Invalid shuttle, restarting bluespace systems...</span>")
|
||||
return FALSE
|
||||
|
||||
var/datum/map_template/shuttle/new_shuttle = new /datum/map_template/shuttle()
|
||||
|
||||
var/obj/docking_port/mobile/port = new /obj/docking_port/mobile(get_turf(target))
|
||||
var/obj/docking_port/stationary/stationary_port = new /obj/docking_port/stationary(get_turf(target))
|
||||
port.callTime = 50
|
||||
port.dir = 1 //Point away from space.
|
||||
port.id = "custom_[GLOB.custom_shuttle_count]"
|
||||
linkedShuttleId = port.id
|
||||
port.ignitionTime = 25
|
||||
port.name = "Custom Shuttle"
|
||||
port.port_direction = 2
|
||||
port.preferred_direction = 4
|
||||
port.area_type = recorded_shuttle_area
|
||||
|
||||
stationary_port.area_type = overwritten_area
|
||||
|
||||
var/portDirection = getNonShuttleDirection(get_turf(port))
|
||||
var/invertedDir = invertDir(portDirection)
|
||||
if(!portDirection || !invertedDir)
|
||||
to_chat(usr, "<span class='warning'>Shuttle creation aborted, docking airlock must be on an external wall. Please select a new airlock.</span>")
|
||||
port.Destroy()
|
||||
stationary_port.Destroy()
|
||||
linkedShuttleId = null
|
||||
return FALSE
|
||||
port.dir = invertedDir
|
||||
port.port_direction = portDirection
|
||||
|
||||
if(!calculate_bounds(port))
|
||||
to_chat(usr, "<span class='warning'>Bluespace calculations failed, please select a new airlock.</span>")
|
||||
port.Destroy()
|
||||
stationary_port.Destroy()
|
||||
linkedShuttleId = null
|
||||
return FALSE
|
||||
|
||||
port.shuttle_areas = list()
|
||||
//var/list/all_turfs = port.return_ordered_turfs(port.x, port.y, port.z, port.dir)
|
||||
var/list/all_turfs = loggedTurfs
|
||||
for(var/i in 1 to all_turfs.len)
|
||||
var/turf/curT = all_turfs[i]
|
||||
var/area/cur_area = curT.loc
|
||||
//Add the area to the shuttle <3
|
||||
if(istype(cur_area, recorded_shuttle_area))
|
||||
if(istype(curT, /turf/open/space))
|
||||
continue
|
||||
if(length(curT.baseturfs) < 2)
|
||||
continue
|
||||
//Add the shuttle base shit to the shuttle
|
||||
curT.baseturfs.Insert(3, /turf/baseturf_skipover/shuttle)
|
||||
port.shuttle_areas[cur_area] = TRUE
|
||||
|
||||
port.linkup(new_shuttle, stationary_port)
|
||||
|
||||
port.movement_force = list("KNOCKDOWN" = 0, "THROW" = 0)
|
||||
port.initiate_docking(stationary_port)
|
||||
|
||||
port.mode = SHUTTLE_IDLE
|
||||
port.timer = 0
|
||||
|
||||
port.register()
|
||||
|
||||
icon_state = "rsd_used"
|
||||
|
||||
//Clear highlights
|
||||
overlay_holder.clear_highlights()
|
||||
GLOB.custom_shuttle_count ++
|
||||
message_admins("[ADMIN_LOOKUPFLW(user)] created a new shuttle with a [src] at [ADMIN_VERBOSEJMP(user)] ([GLOB.custom_shuttle_count] custom shuttles, limit is [CUSTOM_SHUTTLE_LIMIT])")
|
||||
log_game("[key_name(user)] created a new shuttle with a [src] at [AREACOORD(user)] ([GLOB.custom_shuttle_count] custom shuttles, limit is [CUSTOM_SHUTTLE_LIMIT])")
|
||||
return TRUE
|
||||
|
||||
/obj/item/shuttle_creator/proc/create_shuttle_area(mob/user)
|
||||
//Check to see if the user can make a new area to prevent spamming
|
||||
if(user)
|
||||
if(user.create_area_cooldown >= world.time)
|
||||
to_chat(user, "<span class='warning'>Smoke vents from the [src], maybe you should let it cooldown before using it again.</span>")
|
||||
return FALSE
|
||||
user.create_area_cooldown = world.time + 10
|
||||
if(!loggedTurfs)
|
||||
return FALSE
|
||||
if(!check_area(loggedTurfs, FALSE)) //Makes sure nothing (Shuttles) has moved into the area during creation
|
||||
return FALSE
|
||||
//Create the new area
|
||||
var/area/shuttle/custom/powered/newS
|
||||
var/area/oldA = loggedOldArea
|
||||
var/str = stripped_input(user, "Shuttle Name:", "Blueprint Editing", "", MAX_NAME_LEN)
|
||||
if(!str || !length(str))
|
||||
return FALSE
|
||||
if(length(str) > 50)
|
||||
to_chat(user, "<span class='warning'>The provided ship name is too long, blares the [src]</span>")
|
||||
return FALSE
|
||||
newS = new /area/shuttle/custom/powered()
|
||||
newS.setup(str)
|
||||
newS.set_dynamic_lighting()
|
||||
//Shuttles always have gravity
|
||||
newS.has_gravity = TRUE
|
||||
newS.requires_power = TRUE
|
||||
//Record the area for use when creating the docking port
|
||||
recorded_shuttle_area = newS
|
||||
|
||||
for(var/i in 1 to loggedTurfs.len)
|
||||
var/turf/turf_holder = loggedTurfs[i]
|
||||
var/area/old_area = turf_holder.loc
|
||||
newS.contents += turf_holder
|
||||
turf_holder.change_area(old_area, newS)
|
||||
|
||||
newS.reg_in_areas_in_z()
|
||||
|
||||
var/list/firedoors = oldA.firedoors
|
||||
for(var/door in firedoors)
|
||||
var/obj/machinery/door/firedoor/FD = door
|
||||
FD.CalculateAffectingAreas()
|
||||
return TRUE
|
||||
|
||||
//Checks an area to ensure that the turfs provided are valid to be made into a shuttle
|
||||
/obj/item/shuttle_creator/proc/check_area(list/turfs, addingTurfs = TRUE)
|
||||
if(!turfs)
|
||||
to_chat(usr, "<span class='warning'>Shuttles must be created in an airtight space, ensure that the shuttle is airtight, including corners.</span>")
|
||||
return FALSE
|
||||
if(turfs.len + (addingTurfs ? loggedTurfs.len : 0) > SHUTTLE_CREATOR_MAX_SIZE)
|
||||
to_chat(usr, "<span class='warning'>The [src]'s internal cooling system wizzes violently and a message appears on the screen, \"Caution, this device can only handle the creation of shuttles up to [SHUTTLE_CREATOR_MAX_SIZE] units in size. Please reduce your shuttle by [turfs.len-SHUTTLE_CREATOR_MAX_SIZE]. Sorry for the inconvinience\"</span>")
|
||||
return FALSE
|
||||
//Check to see if it's a valid shuttle
|
||||
for(var/i in 1 to turfs.len)
|
||||
var/area/place = get_area(turfs[i])
|
||||
//If any of the turfs are on station / not in space, a shuttle cannot be forced there
|
||||
if(!place)
|
||||
to_chat(usr, "<span class='warning'>You can't seem to overpower the bluespace harmonics in this location, try somewhere else.</span>")
|
||||
return FALSE
|
||||
if(istype(place, /area/space))
|
||||
overwritten_area = /area/space
|
||||
else if(istype(place, /area/lavaland/surface/outdoors))
|
||||
overwritten_area = /area/lavaland/surface/outdoors
|
||||
else
|
||||
to_chat(usr, "<span class='warning'>Caution, shuttle must not use any material connected to the station. Your shuttle is currenly overlapping with [place.name]</span>")
|
||||
return FALSE
|
||||
//Finally, check to see if the area is actually attached
|
||||
if(!LAZYLEN(loggedTurfs))
|
||||
return TRUE
|
||||
for(var/turf/T in turfs)
|
||||
if(turf_connected_to_saved_turfs(T))
|
||||
return TRUE
|
||||
CHECK_TICK
|
||||
to_chat(usr, "<span class='warning'>Caution, new areas of the shuttle must be connected to the other areas of the shuttle.</span>")
|
||||
return FALSE
|
||||
|
||||
/obj/item/shuttle_creator/proc/turf_connected_to_saved_turfs(turf/T)
|
||||
for(var/i in 1 to 4)
|
||||
var/turf/adjacentT = get_offset_target_turf(T, CARDINAL_DIRECTIONS_X[i], CARDINAL_DIRECTIONS_Y[i])
|
||||
if(adjacentT in loggedTurfs)
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
/obj/item/shuttle_creator/proc/turf_in_list(turf/T)
|
||||
return loggedTurfs.Find(T)
|
||||
|
||||
/obj/item/shuttle_creator/proc/add_single_turf(turf/T)
|
||||
if(!check_area(list(T)))
|
||||
return FALSE
|
||||
loggedTurfs |= T
|
||||
loggedOldArea = get_area(T)
|
||||
overlay_holder.highlight_turf(T)
|
||||
|
||||
/obj/item/shuttle_creator/proc/add_saved_area(mob/user)
|
||||
var/static/area_or_turf_fail_types = typecacheof(list(
|
||||
/turf/open/space,
|
||||
/area/shuttle
|
||||
))
|
||||
//Detect the turfs connected in the curerrent enclosed area
|
||||
var/list/turfs = detect_room(get_turf(user), area_or_turf_fail_types)
|
||||
if(!check_area(turfs))
|
||||
return FALSE
|
||||
loggedOldArea = get_area(get_turf(user))
|
||||
loggedTurfs |= turfs
|
||||
overlay_holder.highlight_area(turfs)
|
||||
//TODO READD THIS SHIT: icon_state = "rsd_used"
|
||||
to_chat(user, "<span class='notice'>You add the area into the buffer of the [src], you made add more areas or select an airlock to act as a docking port to complete the shuttle.</span>")
|
||||
return turfs
|
||||
|
||||
/obj/item/shuttle_creator/proc/remove_single_turf(turf/T)
|
||||
if(!turf_in_list(T))
|
||||
return
|
||||
loggedTurfs -= T
|
||||
loggedOldArea = get_area(T)
|
||||
overlay_holder.unhighlight_turf(T)
|
||||
|
||||
/obj/item/shuttle_creator/proc/reset_saved_area()
|
||||
overlay_holder.clear_highlights()
|
||||
loggedTurfs.Cut()
|
||||
to_chat(usr, "<span class='notice'>You reset the area buffer on the [src].</span>")
|
||||
|
||||
#undef CARDINAL_DIRECTIONS_X
|
||||
#undef CARDINAL_DIRECTIONS_Y
|
||||
101
code/modules/shuttle/shuttle_creation/shuttle_creator_actions.dm
Normal file
101
code/modules/shuttle/shuttle_creation/shuttle_creator_actions.dm
Normal file
@@ -0,0 +1,101 @@
|
||||
//============ Actions ============
|
||||
/datum/action/innate/shuttle_creator
|
||||
icon_icon = 'icons/mob/actions/actions_shuttle.dmi'
|
||||
var/mob/living/C
|
||||
var/mob/camera/aiEye/remote/shuttle_creation/remote_eye
|
||||
var/obj/item/shuttle_creator/shuttle_creator
|
||||
|
||||
/datum/action/innate/shuttle_creator/Activate()
|
||||
if(!target)
|
||||
return TRUE
|
||||
C = owner
|
||||
remote_eye = C.remote_control
|
||||
var/obj/machinery/computer/camera_advanced/shuttle_creator/internal_console = target
|
||||
shuttle_creator = internal_console.owner_rsd
|
||||
|
||||
//Add an area
|
||||
/datum/action/innate/shuttle_creator/designate_area
|
||||
name = "Designate Room"
|
||||
button_icon_state = "designate_area"
|
||||
|
||||
/datum/action/innate/shuttle_creator/designate_area/Activate()
|
||||
if(..())
|
||||
return
|
||||
shuttle_creator.add_saved_area(remote_eye)
|
||||
|
||||
//Add a single turf
|
||||
/datum/action/innate/shuttle_creator/designate_turf
|
||||
name = "Designate Turf"
|
||||
button_icon_state = "designate_turf"
|
||||
|
||||
/datum/action/innate/shuttle_creator/designate_turf/Activate()
|
||||
if(..())
|
||||
return
|
||||
var/turf/T = get_turf(remote_eye)
|
||||
if(istype(T, /turf/open/space))
|
||||
var/connectors_exist = FALSE
|
||||
for(var/obj/structure/lattice/lattice in T)
|
||||
connectors_exist = TRUE
|
||||
break
|
||||
if(!connectors_exist)
|
||||
to_chat(usr, "<span class='warning'>This turf requires support, build some catwalks or lattices.</span>")
|
||||
return
|
||||
if(!shuttle_creator.check_area(list(T)))
|
||||
return
|
||||
if(shuttle_creator.turf_in_list(T))
|
||||
return
|
||||
shuttle_creator.add_single_turf(T)
|
||||
|
||||
//Clear a single entire area
|
||||
/datum/action/innate/shuttle_creator/clear_turf
|
||||
name = "Clear Turf"
|
||||
button_icon_state = "clear_turf"
|
||||
|
||||
/datum/action/innate/shuttle_creator/clear_turf/Activate()
|
||||
if(..())
|
||||
return
|
||||
shuttle_creator.remove_single_turf(get_turf(remote_eye))
|
||||
|
||||
//Clear the entire area
|
||||
/datum/action/innate/shuttle_creator/reset
|
||||
name = "Reset Buffer"
|
||||
button_icon_state = "clear_area"
|
||||
|
||||
/datum/action/innate/shuttle_creator/reset/Activate()
|
||||
if(..())
|
||||
return
|
||||
shuttle_creator.reset_saved_area()
|
||||
|
||||
//Finish the shuttle
|
||||
/datum/action/innate/shuttle_creator/airlock
|
||||
name = "Select Docking Airlock"
|
||||
button_icon_state = "select_airlock"
|
||||
|
||||
/datum/action/innate/shuttle_creator/airlock/Activate()
|
||||
if(..())
|
||||
return
|
||||
var/turf/T = get_turf(remote_eye)
|
||||
for(var/obj/machinery/door/airlock/A in T)
|
||||
if(get_area(A) != shuttle_creator.loggedOldArea)
|
||||
to_chat(C, "<span class='warning'>Caution, airlock must be on the shuttle to function as a dock.</span>")
|
||||
return
|
||||
if(shuttle_creator.linkedShuttleId)
|
||||
return
|
||||
if(GLOB.custom_shuttle_count > CUSTOM_SHUTTLE_LIMIT)
|
||||
to_chat(C, "<span class='warning'>Shuttle limit reached, sorry.</span>")
|
||||
return
|
||||
if(shuttle_creator.loggedTurfs.len > SHUTTLE_CREATOR_MAX_SIZE)
|
||||
to_chat(C, "<span class='warning'>This shuttle is too large!</span>")
|
||||
return
|
||||
if(!shuttle_creator.getNonShuttleDirection(T))
|
||||
to_chat(C, "<span class='warning'>Docking port must be on an external wall, with only 1 side exposed to space.</span>")
|
||||
return
|
||||
if(!shuttle_creator.create_shuttle_area(C))
|
||||
return
|
||||
if(shuttle_creator.shuttle_create_docking_port(A, C))
|
||||
to_chat(C, "<span class='notice'>Shuttle created!</span>")
|
||||
//Remove eye control
|
||||
var/obj/machinery/computer/camera_advanced/shuttle_creator/internal_console = target
|
||||
internal_console.remove_eye_control()
|
||||
qdel(internal_console)
|
||||
return
|
||||
@@ -0,0 +1,93 @@
|
||||
//============The internal camera console used for designating the area=============
|
||||
/obj/machinery/computer/camera_advanced/shuttle_creator
|
||||
name = "internal shuttle creator console"
|
||||
desc = "You should not have access to this, please report this as a bug"
|
||||
networks = list()
|
||||
var/obj/item/shuttle_creator/owner_rsd
|
||||
var/datum/action/innate/shuttle_creator/designate_area/area_action = new
|
||||
var/datum/action/innate/shuttle_creator/designate_turf/turf_action = new
|
||||
var/datum/action/innate/shuttle_creator/clear_turf/clear_turf_action = new
|
||||
var/datum/action/innate/shuttle_creator/reset/reset_action = new
|
||||
var/datum/action/innate/shuttle_creator/airlock/airlock_action = new
|
||||
|
||||
/obj/machinery/computer/camera_advanced/shuttle_creator/check_eye(mob/user)
|
||||
if(user.eye_blind || user.incapacitated())
|
||||
user.unset_machine()
|
||||
|
||||
/obj/machinery/computer/camera_advanced/shuttle_creator/CreateEye()
|
||||
eyeobj = new /mob/camera/aiEye/remote/shuttle_creation(get_turf(owner_rsd))
|
||||
eyeobj.origin = src
|
||||
eyeobj.use_static = USE_STATIC_NONE
|
||||
|
||||
/obj/machinery/computer/camera_advanced/shuttle_creator/is_operational()
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/computer/camera_advanced/shuttle_creator/can_interact(mob/user)
|
||||
if(!isliving(user))
|
||||
return FALSE
|
||||
var/mob/living/L = user
|
||||
if(L.incapacitated())
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/computer/camera_advanced/shuttle_creator/GrantActions(mob/living/user)
|
||||
..(user)
|
||||
eyeobj.invisibility = SEE_INVISIBLE_LIVING
|
||||
if(area_action)
|
||||
area_action.target = src
|
||||
area_action.Grant(user)
|
||||
actions += area_action
|
||||
if(turf_action)
|
||||
turf_action.target = src
|
||||
turf_action.Grant(user)
|
||||
actions += turf_action
|
||||
if(clear_turf_action)
|
||||
clear_turf_action.target = src
|
||||
clear_turf_action.Grant(user)
|
||||
actions += clear_turf_action
|
||||
if(reset_action)
|
||||
reset_action.target = src
|
||||
reset_action.Grant(user)
|
||||
actions += reset_action
|
||||
if(airlock_action)
|
||||
airlock_action.target = src
|
||||
airlock_action.Grant(user)
|
||||
actions += airlock_action
|
||||
|
||||
/obj/machinery/computer/camera_advanced/shuttle_creator/remove_eye_control(mob/living/user)
|
||||
. = ..()
|
||||
owner_rsd.overlay_holder.remove_client()
|
||||
eyeobj.invisibility = INVISIBILITY_MAXIMUM
|
||||
if(user.client)
|
||||
user.client.images -= eyeobj.user_image
|
||||
|
||||
/obj/machinery/computer/camera_advanced/shuttle_creator/attack_hand(mob/user)
|
||||
if(!is_operational()) //you cant use broken machine you chumbis
|
||||
return
|
||||
if(current_user)
|
||||
to_chat(user, "The console is already in use!")
|
||||
return
|
||||
var/mob/living/L = user
|
||||
if(!can_use(user))
|
||||
return
|
||||
if(!eyeobj)
|
||||
CreateEye()
|
||||
if(!eyeobj.eye_initialized)
|
||||
var/camera_location = get_turf(owner_rsd)
|
||||
if(camera_location)
|
||||
eyeobj.eye_initialized = TRUE
|
||||
give_eye_control(L)
|
||||
eyeobj.setLoc(camera_location)
|
||||
var/mob/camera/aiEye/remote/shuttle_creation/shuttle_eye = eyeobj
|
||||
shuttle_eye.source_turf = get_turf(user)
|
||||
else
|
||||
user.unset_machine()
|
||||
else
|
||||
var/camera_location = get_turf(owner_rsd)
|
||||
var/mob/camera/aiEye/remote/shuttle_creation/eye = eyeobj
|
||||
give_eye_control(L)
|
||||
if(camera_location)
|
||||
eye.source_turf = camera_location
|
||||
eyeobj.setLoc(camera_location)
|
||||
else
|
||||
eyeobj.setLoc(eyeobj.loc)
|
||||
54
code/modules/shuttle/shuttle_creation/shuttle_creator_eye.dm
Normal file
54
code/modules/shuttle/shuttle_creation/shuttle_creator_eye.dm
Normal file
@@ -0,0 +1,54 @@
|
||||
//===============Camera Eye================
|
||||
/mob/camera/aiEye/remote/shuttle_creation
|
||||
name = "shuttle holo-drone"
|
||||
icon = 'icons/obj/mining.dmi'
|
||||
icon_state = "construction_drone"
|
||||
visible_icon = FALSE
|
||||
acceleration = 0
|
||||
var/turf/source_turf
|
||||
var/max_range = 12
|
||||
|
||||
/mob/camera/aiEye/remote/shuttle_creation/Initialize()
|
||||
. = ..()
|
||||
setLoc(get_turf(source_turf))
|
||||
|
||||
/mob/camera/aiEye/remote/shuttle_creation/update_remote_sight(mob/living/user)
|
||||
user.sight = BLIND|SEE_TURFS
|
||||
user.lighting_alpha = LIGHTING_PLANE_ALPHA_INVISIBLE
|
||||
user.sync_lighting_plane_alpha()
|
||||
return TRUE
|
||||
|
||||
/mob/camera/aiEye/remote/shuttle_creation/relaymove(mob/user, direct)
|
||||
dir = direct //This camera eye is visible as a drone, and needs to keep the dir updated
|
||||
var/initial = initial(sprint)
|
||||
var/max_sprint = 50
|
||||
|
||||
if(cooldown && cooldown < world.timeofday) // 3 seconds
|
||||
sprint = initial
|
||||
|
||||
for(var/i = 0; i < max(sprint, initial); i += 20)
|
||||
var/turf/step = get_turf(get_step(src, direct))
|
||||
if(step && can_move_to(step))
|
||||
setLoc(step)
|
||||
|
||||
cooldown = world.timeofday + 5
|
||||
if(acceleration)
|
||||
sprint = min(sprint + 0.5, max_sprint)
|
||||
else
|
||||
sprint = initial
|
||||
|
||||
/mob/camera/aiEye/remote/shuttle_creation/proc/can_move_to(var/turf/T)
|
||||
var/origin_x = source_turf.x
|
||||
var/origin_y = source_turf.y
|
||||
var/change_X = abs(origin_x - T.x)
|
||||
var/change_Y = abs(origin_y - T.y)
|
||||
return (change_X < max_range && change_Y < max_range)
|
||||
|
||||
/mob/camera/aiEye/remote/shuttle_creation/setLoc(T)
|
||||
..()
|
||||
if(eye_user?.client)
|
||||
eye_user.client.images -= user_image
|
||||
var/image/I = image(icon, loc, icon_state, FLY_LAYER, dir)
|
||||
I.plane = MASSIVE_OBJ_LAYER
|
||||
user_image = I
|
||||
eye_user.client.images += user_image
|
||||
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Manages the overlays for the shuttle creator drone.
|
||||
*/
|
||||
|
||||
/datum/shuttle_creator_overlay_holder
|
||||
var/client/holder
|
||||
var/list/images = list()
|
||||
var/list/turfs = list()
|
||||
|
||||
/datum/shuttle_creator_overlay_holder/proc/add_client(client/C)
|
||||
holder = C
|
||||
holder.images += images
|
||||
|
||||
/datum/shuttle_creator_overlay_holder/proc/remove_client()
|
||||
holder.images -= images
|
||||
holder = null
|
||||
|
||||
/datum/shuttle_creator_overlay_holder/proc/clear_highlights()
|
||||
if(holder)
|
||||
holder.images -= images
|
||||
images.Cut()
|
||||
turfs.Cut()
|
||||
|
||||
/datum/shuttle_creator_overlay_holder/proc/create_hightlight(turf/T)
|
||||
if(T in turfs)
|
||||
return
|
||||
var/image/I = image('icons/turf/overlays.dmi', T, "greenOverlay")
|
||||
I.plane = ABOVE_LIGHTING_PLANE
|
||||
images += I
|
||||
holder.images += I
|
||||
turfs += T
|
||||
|
||||
/datum/shuttle_creator_overlay_holder/proc/remove_hightlight(turf/T)
|
||||
if(!(T in turfs))
|
||||
return
|
||||
turfs -= T
|
||||
holder.images -= images
|
||||
for(var/image/I in images)
|
||||
if(get_turf(I) != T)
|
||||
continue
|
||||
images -= I
|
||||
holder.images += images
|
||||
|
||||
/datum/shuttle_creator_overlay_holder/proc/highlight_area(list/turfs)
|
||||
for(var/turf/T in turfs)
|
||||
highlight_turf(T)
|
||||
|
||||
/datum/shuttle_creator_overlay_holder/proc/highlight_turf(turf/T)
|
||||
create_hightlight(T)
|
||||
|
||||
/datum/shuttle_creator_overlay_holder/proc/unhighlight_turf(turf/T)
|
||||
remove_hightlight(T)
|
||||
39
code/modules/shuttle/shuttle_creation/shuttle_upgrades.dm
Normal file
39
code/modules/shuttle/shuttle_creation/shuttle_upgrades.dm
Normal file
@@ -0,0 +1,39 @@
|
||||
/obj/item/shuttle_route_optimisation
|
||||
name = "Route Optimisation Upgrade"
|
||||
desc = "Used on a custom shuttle control console to calculate more efficient routes."
|
||||
icon = 'icons/obj/module.dmi'
|
||||
icon_state = "shuttledisk"
|
||||
force = 0
|
||||
throwforce = 8
|
||||
throw_speed = 3
|
||||
throw_range = 5
|
||||
density = FALSE
|
||||
anchored = FALSE
|
||||
item_flags = NOBLUDGEON
|
||||
var/upgrade_amount = 0.8
|
||||
|
||||
/obj/item/shuttle_route_optimisation/hyperlane
|
||||
name = "Bluespace Hyperlane Calculator"
|
||||
desc = "Used on a custom shuttle control console to allow for the following of bluespace hyperlanes, increasing the efficiency of the shuttle."
|
||||
icon_state = "shuttledisk_better"
|
||||
upgrade_amount = 0.6
|
||||
|
||||
/obj/item/shuttle_route_optimisation/void
|
||||
name = "Voidspace Route Calculator"
|
||||
desc = "Used on a custom shuttle control console to allow it to navigate into voidspace, making the routes almost instant."
|
||||
icon_state = "shuttledisk_void"
|
||||
upgrade_amount = 0.2
|
||||
|
||||
/obj/item/shuttle_route_optimisation/attack_obj(obj/O, mob/living/user)
|
||||
. = ..()
|
||||
if(!istype(O, /obj/machinery/computer))
|
||||
return
|
||||
if(!istype(O, /obj/machinery/computer/custom_shuttle))
|
||||
to_chat(user, "<span class='warning'>This upgrade only works on a custom shuttle flight console.</span>")
|
||||
return
|
||||
if (!user.transferItemToLoc(src, get_turf(O)))
|
||||
return
|
||||
var/obj/machinery/computer/custom_shuttle/link_comp = O
|
||||
link_comp.distance_multiplier = clamp(link_comp.distance_multiplier, 0, upgrade_amount)
|
||||
playsound(src, 'sound/machines/terminal_insert_disc.ogg', 50, 0)
|
||||
to_chat(usr, "<span class='notice'>You insert the disk into the flight computer, allowing for routes to be [upgrade_amount]x the original distance.</span>")
|
||||
BIN
icons/mob/actions/actions_shuttle.dmi
Normal file
BIN
icons/mob/actions/actions_shuttle.dmi
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 3.0 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 28 KiB After Width: | Height: | Size: 28 KiB |
@@ -828,6 +828,9 @@
|
||||
#include "code\game\machinery\porta_turret\portable_turret.dm"
|
||||
#include "code\game\machinery\porta_turret\portable_turret_construct.dm"
|
||||
#include "code\game\machinery\porta_turret\portable_turret_cover.dm"
|
||||
#include "code\game\machinery\shuttle\custom_shuttle.dm"
|
||||
#include "code\game\machinery\shuttle\shuttle_engine.dm"
|
||||
#include "code\game\machinery\shuttle\shuttle_heater.dm"
|
||||
#include "code\game\machinery\telecomms\broadcasting.dm"
|
||||
#include "code\game\machinery\telecomms\machine_interactions.dm"
|
||||
#include "code\game\machinery\telecomms\telecomunications.dm"
|
||||
@@ -3139,6 +3142,7 @@
|
||||
#include "code\modules\shuttle\arrivals.dm"
|
||||
#include "code\modules\shuttle\assault_pod.dm"
|
||||
#include "code\modules\shuttle\computer.dm"
|
||||
#include "code\modules\shuttle\custom_shuttle.dm"
|
||||
#include "code\modules\shuttle\docking.dm"
|
||||
#include "code\modules\shuttle\elevator.dm"
|
||||
#include "code\modules\shuttle\emergency.dm"
|
||||
@@ -3155,6 +3159,12 @@
|
||||
#include "code\modules\shuttle\supply.dm"
|
||||
#include "code\modules\shuttle\syndicate.dm"
|
||||
#include "code\modules\shuttle\white_ship.dm"
|
||||
#include "code\modules\shuttle\shuttle_creation\shuttle_creator.dm"
|
||||
#include "code\modules\shuttle\shuttle_creation\shuttle_creator_actions.dm"
|
||||
#include "code\modules\shuttle\shuttle_creation\shuttle_creator_console.dm"
|
||||
#include "code\modules\shuttle\shuttle_creation\shuttle_creator_eye.dm"
|
||||
#include "code\modules\shuttle\shuttle_creation\shuttle_creator_overlay.dm"
|
||||
#include "code\modules\shuttle\shuttle_creation\shuttle_upgrades.dm"
|
||||
#include "code\modules\spells\spell.dm"
|
||||
#include "code\modules\spells\spell_types\aimed.dm"
|
||||
#include "code\modules\spells\spell_types\area_teleport.dm"
|
||||
|
||||
Reference in New Issue
Block a user