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_STRANDED "stranded"
|
||||||
#define SHUTTLE_ESCAPE "escape"
|
#define SHUTTLE_ESCAPE "escape"
|
||||||
#define SHUTTLE_ENDGAME "endgame: game over"
|
#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_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)))
|
#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.
|
* 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
|
/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
|
/area/shuttle/custom
|
||||||
name = "Custom player shuttle"
|
name = "Custom player shuttle"
|
||||||
|
|
||||||
|
/area/shuttle/custom/powered
|
||||||
|
name = "Custom Powered player shuttle"
|
||||||
|
requires_power = FALSE
|
||||||
|
|
||||||
/area/shuttle/arrival
|
/area/shuttle/arrival
|
||||||
name = "Arrival Shuttle"
|
name = "Arrival Shuttle"
|
||||||
unique = TRUE // SSjob refers to this area for latejoiners
|
unique = TRUE // SSjob refers to this area for latejoiners
|
||||||
|
|||||||
@@ -846,6 +846,9 @@
|
|||||||
/atom/proc/GenerateTag()
|
/atom/proc/GenerateTag()
|
||||||
return
|
return
|
||||||
|
|
||||||
|
/atom/proc/connect_to_shuttle(obj/docking_port/mobile/port, obj/docking_port/stationary/dock, idnum, override=FALSE)
|
||||||
|
return
|
||||||
|
|
||||||
// Generic logging helper
|
// Generic logging helper
|
||||||
/atom/proc/log_message(message, message_type, color=null, log_globally=TRUE)
|
/atom/proc/log_message(message, message_type, color=null, log_globally=TRUE)
|
||||||
if(!log_globally)
|
if(!log_globally)
|
||||||
|
|||||||
@@ -35,6 +35,11 @@
|
|||||||
M.unset_machine() //to properly reset the view of the users if the console is deleted.
|
M.unset_machine() //to properly reset the view of the users if the console is deleted.
|
||||||
return ..()
|
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)
|
/obj/machinery/computer/security/can_interact(mob/user)
|
||||||
if((!hasSiliconAccessInArea(user) && !Adjacent(user)) || is_blind(user) || !in_view_range(user, src))
|
if((!hasSiliconAccessInArea(user) && !Adjacent(user)) || is_blind(user) || !in_view_range(user, src))
|
||||||
return FALSE
|
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")
|
if("shuttle_id")
|
||||||
update()
|
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))
|
if (port && (shuttle_id == initial(shuttle_id) || override))
|
||||||
shuttle_id = port.id
|
shuttle_id = port.id
|
||||||
update()
|
update()
|
||||||
|
|||||||
@@ -379,3 +379,11 @@
|
|||||||
/obj/item/circuitboard/computer/nanite_cloud_controller
|
/obj/item/circuitboard/computer/nanite_cloud_controller
|
||||||
name = "Nanite Cloud Control (Computer Board)"
|
name = "Nanite Cloud Control (Computer Board)"
|
||||||
build_path = /obj/machinery/computer/nanite_cloud_controller
|
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/micro_laser = 2,
|
||||||
/obj/item/stock_parts/scanning_module = 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"
|
id = "xenobio_slimeadv"
|
||||||
build_path = /obj/item/disk/xenobio_console_upgrade/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
|
||||||
|
|||||||
@@ -760,4 +760,34 @@
|
|||||||
materials = list(/datum/material/iron = 1000)
|
materials = list(/datum/material/iron = 1000)
|
||||||
build_path = /obj/item/tank/internals/emergency_oxygen/engi/empty
|
build_path = /obj/item/tank/internals/emergency_oxygen/engi/empty
|
||||||
category = list("Equipment")
|
category = list("Equipment")
|
||||||
departmental_flags = DEPARTMENTAL_FLAG_ENGINEERING
|
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")
|
category = list("Tool Designs")
|
||||||
departmental_flags = DEPARTMENTAL_FLAG_ENGINEERING
|
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
|
/datum/design/handdrill
|
||||||
name = "Hand Drill"
|
name = "Hand Drill"
|
||||||
desc = "A small electric hand drill with an interchangeable screwdriver and bolt bit"
|
desc = "A small electric hand drill with an interchangeable screwdriver and bolt bit"
|
||||||
|
|||||||
@@ -63,3 +63,36 @@
|
|||||||
prereq_ids = list("bluespace_warping", "syndicate_basic")
|
prereq_ids = list("bluespace_warping", "syndicate_basic")
|
||||||
design_ids = list("desynchronizer")
|
design_ids = list("desynchronizer")
|
||||||
research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500)
|
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>")
|
to_chat(user, "<span class='notice'>You fried the consoles ID checking system.</span>")
|
||||||
return TRUE
|
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))
|
if(port && (shuttleId == initial(shuttleId) || override))
|
||||||
shuttleId = port.id
|
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 -= remove_images
|
||||||
current_user.client.images += add_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))
|
if(port && (shuttleId == initial(shuttleId) || override))
|
||||||
shuttleId = port.id
|
shuttleId = port.id
|
||||||
shuttlePortId = "[port.id]_custom"
|
shuttlePortId = "[port.id]_custom"
|
||||||
|
|||||||
@@ -11,17 +11,31 @@
|
|||||||
|
|
||||||
resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF
|
resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF
|
||||||
anchored = TRUE
|
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
|
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
|
dir = NORTH
|
||||||
var/width = 0 //size of covered area, perpendicular to dir
|
///size of covered area, perpendicular to dir. You shouldn't modify this for mobile dockingports, set automatically.
|
||||||
var/height = 0 //size of covered area, parallel to dir
|
var/width = 0
|
||||||
var/dwidth = 0 //position relative to covered area, perpendicular to dir
|
///size of covered area, parallel to dir. You shouldn't modify this for mobile dockingports, set automatically.
|
||||||
var/dheight = 0 //position relative to covered area, parallel to dir
|
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/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
|
//these objects are indestructible
|
||||||
/obj/docking_port/Destroy(force)
|
/obj/docking_port/Destroy(force)
|
||||||
@@ -155,8 +169,6 @@
|
|||||||
/obj/docking_port/stationary
|
/obj/docking_port/stationary
|
||||||
name = "dock"
|
name = "dock"
|
||||||
|
|
||||||
area_type = SHUTTLE_DEFAULT_UNDERLYING_AREA
|
|
||||||
|
|
||||||
var/last_dock_time
|
var/last_dock_time
|
||||||
|
|
||||||
var/datum/map_template/shuttle/roundstart_template
|
var/datum/map_template/shuttle/roundstart_template
|
||||||
@@ -169,6 +181,9 @@
|
|||||||
id = "[SSshuttle.stationary.len]"
|
id = "[SSshuttle.stationary.len]"
|
||||||
if(name == "dock")
|
if(name == "dock")
|
||||||
name = "dock[SSshuttle.stationary.len]"
|
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)
|
if(mapload)
|
||||||
for(var/turf/T in return_turfs())
|
for(var/turf/T in return_turfs())
|
||||||
@@ -183,6 +198,13 @@
|
|||||||
SSshuttle.stationary -= src
|
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()
|
/obj/docking_port/stationary/proc/load_roundstart()
|
||||||
if(json_key)
|
if(json_key)
|
||||||
var/sid = SSmapping.config.shuttles[json_key]
|
var/sid = SSmapping.config.shuttles[json_key]
|
||||||
@@ -196,9 +218,6 @@
|
|||||||
if(!roundstart_template)
|
if(!roundstart_template)
|
||||||
CRASH("Invalid path ([roundstart_template]) passed to docking port.")
|
CRASH("Invalid path ([roundstart_template]) passed to docking port.")
|
||||||
|
|
||||||
if(roundstart_template)
|
|
||||||
SSshuttle.manipulator.action_load(roundstart_template, src)
|
|
||||||
|
|
||||||
//returns first-found touching shuttleport
|
//returns first-found touching shuttleport
|
||||||
/obj/docking_port/stationary/get_docked()
|
/obj/docking_port/stationary/get_docked()
|
||||||
. = locate(/obj/docking_port/mobile) in loc
|
. = locate(/obj/docking_port/mobile) in loc
|
||||||
@@ -235,16 +254,25 @@
|
|||||||
|
|
||||||
var/list/shuttle_areas
|
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
|
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
|
/// The direction the shuttle prefers to travel in, ie what direction
|
||||||
var/callTime = 100 //time spent in transit (deciseconds). Should not be lower then 10 seconds without editing the animation of the hyperspace ripples.
|
/// the animation will cause it to appear to be traveling in
|
||||||
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
|
|
||||||
var/preferred_direction = NORTH
|
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/port_direction = NORTH
|
||||||
|
|
||||||
var/obj/docking_port/stationary/destination
|
var/obj/docking_port/stationary/destination
|
||||||
@@ -254,13 +282,16 @@
|
|||||||
|
|
||||||
var/launch_status = NOLAUNCH
|
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/list/ripples = list()
|
||||||
var/engine_coeff = 1 //current engine coeff
|
var/engine_coeff = 1
|
||||||
var/current_engines = 0 //current engine power
|
var/current_engines = 0
|
||||||
var/initial_engines = 0 //initial engine power
|
var/initial_engines = 0
|
||||||
var/can_move_docking_ports = FALSE //if this shuttle can move docking ports other than the one it is docked at
|
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()
|
var/list/hidden_turfs = list()
|
||||||
|
|
||||||
/obj/docking_port/mobile/proc/register()
|
/obj/docking_port/mobile/proc/register()
|
||||||
@@ -308,14 +339,12 @@
|
|||||||
id = "[id][idnum]"
|
id = "[id][idnum]"
|
||||||
if(name == initial(name))
|
if(name == initial(name))
|
||||||
name = "[name] [idnum]"
|
name = "[name] [idnum]"
|
||||||
for(var/i in shuttle_areas)
|
for(var/place in shuttle_areas)
|
||||||
var/area/place = i
|
var/area/area = place
|
||||||
for(var/obj/machinery/computer/shuttle/comp in place)
|
area.connect_to_shuttle(src, dock, idnum, FALSE)
|
||||||
comp.connect_to_shuttle(src, dock, idnum)
|
for(var/each in place)
|
||||||
for(var/obj/machinery/computer/camera_advanced/shuttle_docker/comp in place)
|
var/atom/atom = each
|
||||||
comp.connect_to_shuttle(src, dock, idnum)
|
atom.connect_to_shuttle(src, dock, idnum, FALSE)
|
||||||
for(var/obj/machinery/status_display/shuttle/sd in place)
|
|
||||||
sd.connect_to_shuttle(src, dock, idnum)
|
|
||||||
|
|
||||||
|
|
||||||
//this is a hook for custom behaviour. Maybe at some point we could add checks to see if engines are intact
|
//this is a hook for custom behaviour. Maybe at some point we could add checks to see if engines are intact
|
||||||
@@ -423,7 +452,10 @@
|
|||||||
if(initiate_docking(S1) != DOCKING_SUCCESS)
|
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"].")
|
WARNING("shuttle \"[id]\" could not enter transit space. Docked at [S0 ? S0.id : "null"]. Transit dock [S1 ? S1.id : "null"].")
|
||||||
else
|
else
|
||||||
previous = S0
|
if(S0.delete_after)
|
||||||
|
qdel(S0, TRUE)
|
||||||
|
else
|
||||||
|
previous = S0
|
||||||
else
|
else
|
||||||
WARNING("shuttle \"[id]\" could not enter transit space. S0=[S0 ? S0.id : "null"] S1=[S1 ? S1.id : "null"]")
|
WARNING("shuttle \"[id]\" could not enter transit space. S0=[S0 ? S0.id : "null"] S1=[S1 ? S1.id : "null"]")
|
||||||
|
|
||||||
@@ -536,7 +568,11 @@
|
|||||||
// If we can't dock or we don't have a transit slot, wait for 20 ds,
|
// If we can't dock or we don't have a transit slot, wait for 20 ds,
|
||||||
// then try again
|
// then try again
|
||||||
switch(mode)
|
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)
|
var/error = initiate_docking(destination, preferred_direction)
|
||||||
if(error && error & (DOCKING_NULL_DESTINATION | DOCKING_NULL_SOURCE))
|
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)])"
|
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)
|
else if(error)
|
||||||
setTimer(20)
|
setTimer(20)
|
||||||
return
|
return
|
||||||
|
if(rechargeTime)
|
||||||
|
mode = SHUTTLE_RECHARGING
|
||||||
|
setTimer(rechargeTime)
|
||||||
|
return
|
||||||
if(SHUTTLE_RECALL)
|
if(SHUTTLE_RECALL)
|
||||||
if(initiate_docking(previous) != DOCKING_SUCCESS)
|
if(initiate_docking(previous) != DOCKING_SUCCESS)
|
||||||
setTimer(20)
|
setTimer(20)
|
||||||
@@ -649,6 +689,10 @@
|
|||||||
return "ESC"
|
return "ESC"
|
||||||
if(SHUTTLE_STRANDED)
|
if(SHUTTLE_STRANDED)
|
||||||
return "ERR"
|
return "ERR"
|
||||||
|
if(SHUTTLE_RECHARGING)
|
||||||
|
return "RCH"
|
||||||
|
if(SHUTTLE_PREARRIVAL)
|
||||||
|
return "LDN"
|
||||||
return ""
|
return ""
|
||||||
|
|
||||||
// returns 5-letter timer string, used by status screens and mob status panel
|
// returns 5-letter timer string, used by status screens and mob status panel
|
||||||
@@ -660,14 +704,14 @@
|
|||||||
if(timeleft > 1 HOURS)
|
if(timeleft > 1 HOURS)
|
||||||
return "--:--"
|
return "--:--"
|
||||||
else if(timeleft > 0)
|
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
|
else
|
||||||
return "00:00"
|
return "00:00"
|
||||||
|
|
||||||
|
|
||||||
/obj/docking_port/mobile/proc/getStatusText()
|
/obj/docking_port/mobile/proc/getStatusText()
|
||||||
var/obj/docking_port/stationary/dockedAt = get_docked()
|
var/obj/docking_port/stationary/dockedAt = get_docked()
|
||||||
|
var/docked_at = dockedAt?.name || "unknown"
|
||||||
if(istype(dockedAt, /obj/docking_port/stationary/transit))
|
if(istype(dockedAt, /obj/docking_port/stationary/transit))
|
||||||
if (timeLeft() > 1 HOURS)
|
if (timeLeft() > 1 HOURS)
|
||||||
return "hyperspace"
|
return "hyperspace"
|
||||||
@@ -678,8 +722,10 @@
|
|||||||
else
|
else
|
||||||
dst = destination
|
dst = destination
|
||||||
. = "transit towards [dst?.name || "unknown location"] ([getTimerStr()])"
|
. = "transit towards [dst?.name || "unknown location"] ([getTimerStr()])"
|
||||||
|
else if(mode == SHUTTLE_RECHARGING)
|
||||||
|
return "[docked_at], recharging [getTimerStr()]"
|
||||||
else
|
else
|
||||||
return dockedAt?.name || "unknown"
|
return docked_at
|
||||||
|
|
||||||
|
|
||||||
/obj/docking_port/mobile/proc/getDbgStatusText()
|
/obj/docking_port/mobile/proc/getDbgStatusText()
|
||||||
@@ -711,19 +757,47 @@
|
|||||||
return null
|
return null
|
||||||
|
|
||||||
/obj/docking_port/mobile/proc/hyperspace_sound(phase, list/areas)
|
/obj/docking_port/mobile/proc/hyperspace_sound(phase, list/areas)
|
||||||
var/s
|
var/selected_sound
|
||||||
switch(phase)
|
switch(phase)
|
||||||
if(HYPERSPACE_WARMUP)
|
if(HYPERSPACE_WARMUP)
|
||||||
s = 'sound/effects/hyperspace_begin.ogg'
|
selected_sound = "hyperspace_begin"
|
||||||
if(HYPERSPACE_LAUNCH)
|
if(HYPERSPACE_LAUNCH)
|
||||||
s = 'sound/effects/hyperspace_progress.ogg'
|
selected_sound = "hyperspace_progress"
|
||||||
if(HYPERSPACE_END)
|
if(HYPERSPACE_END)
|
||||||
s = 'sound/effects/hyperspace_end.ogg'
|
selected_sound = "hyperspace_end"
|
||||||
else
|
else
|
||||||
CRASH("Invalid hyperspace sound phase: [phase]")
|
CRASH("Invalid hyperspace sound phase: [phase]")
|
||||||
for(var/A in areas)
|
// This previously was played from each door at max volume, and was one of the worst things I had ever seen.
|
||||||
for(var/obj/machinery/door/E in A) //dumb, I know, but playing it on the engines doesn't do it justice
|
// 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.
|
||||||
playsound(E, s, 100, FALSE, max(width, height) - world.view)
|
// 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)
|
||||||
|
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
|
// Losing all initial engines should get you 2
|
||||||
// Adding another set of engines at 0.5 time
|
// Adding another set of engines at 0.5 time
|
||||||
@@ -743,7 +817,12 @@
|
|||||||
var/area/shuttle/areaInstance = thing
|
var/area/shuttle/areaInstance = thing
|
||||||
for(var/obj/structure/shuttle/engine/E in areaInstance.contents)
|
for(var/obj/structure/shuttle/engine/E in areaInstance.contents)
|
||||||
if(!QDELETED(E))
|
if(!QDELETED(E))
|
||||||
|
engine_list += E
|
||||||
. += E.engine_power
|
. += 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
|
// Double initial engines to get to 0.5 minimum
|
||||||
// Lose all initial engines to get to 2
|
// Lose all initial engines to get to 2
|
||||||
@@ -768,7 +847,7 @@
|
|||||||
|
|
||||||
/obj/docking_port/mobile/proc/in_flight()
|
/obj/docking_port/mobile/proc/in_flight()
|
||||||
switch(mode)
|
switch(mode)
|
||||||
if(SHUTTLE_CALL,SHUTTLE_RECALL)
|
if(SHUTTLE_CALL,SHUTTLE_RECALL,SHUTTLE_PREARRIVAL)
|
||||||
return TRUE
|
return TRUE
|
||||||
if(SHUTTLE_IDLE,SHUTTLE_IGNITING)
|
if(SHUTTLE_IDLE,SHUTTLE_IGNITING)
|
||||||
return FALSE
|
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.dm"
|
||||||
#include "code\game\machinery\porta_turret\portable_turret_construct.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\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\broadcasting.dm"
|
||||||
#include "code\game\machinery\telecomms\machine_interactions.dm"
|
#include "code\game\machinery\telecomms\machine_interactions.dm"
|
||||||
#include "code\game\machinery\telecomms\telecomunications.dm"
|
#include "code\game\machinery\telecomms\telecomunications.dm"
|
||||||
@@ -3139,6 +3142,7 @@
|
|||||||
#include "code\modules\shuttle\arrivals.dm"
|
#include "code\modules\shuttle\arrivals.dm"
|
||||||
#include "code\modules\shuttle\assault_pod.dm"
|
#include "code\modules\shuttle\assault_pod.dm"
|
||||||
#include "code\modules\shuttle\computer.dm"
|
#include "code\modules\shuttle\computer.dm"
|
||||||
|
#include "code\modules\shuttle\custom_shuttle.dm"
|
||||||
#include "code\modules\shuttle\docking.dm"
|
#include "code\modules\shuttle\docking.dm"
|
||||||
#include "code\modules\shuttle\elevator.dm"
|
#include "code\modules\shuttle\elevator.dm"
|
||||||
#include "code\modules\shuttle\emergency.dm"
|
#include "code\modules\shuttle\emergency.dm"
|
||||||
@@ -3155,6 +3159,12 @@
|
|||||||
#include "code\modules\shuttle\supply.dm"
|
#include "code\modules\shuttle\supply.dm"
|
||||||
#include "code\modules\shuttle\syndicate.dm"
|
#include "code\modules\shuttle\syndicate.dm"
|
||||||
#include "code\modules\shuttle\white_ship.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.dm"
|
||||||
#include "code\modules\spells\spell_types\aimed.dm"
|
#include "code\modules\spells\spell_types\aimed.dm"
|
||||||
#include "code\modules\spells\spell_types\area_teleport.dm"
|
#include "code\modules\spells\spell_types\area_teleport.dm"
|
||||||
|
|||||||
Reference in New Issue
Block a user