diff --git a/code/__DEFINES/shuttles.dm b/code/__DEFINES/shuttles.dm index a133816f2d..134a4ea496 100644 --- a/code/__DEFINES/shuttles.dm +++ b/code/__DEFINES/shuttles.dm @@ -45,4 +45,9 @@ #define HYPERSPACE_LAUNCH 2 #define HYPERSPACE_END 3 -#define CALL_SHUTTLE_REASON_LENGTH 12 \ No newline at end of file +#define CALL_SHUTTLE_REASON_LENGTH 12 + +//Engine related +#define ENGINE_COEFF_MIN 0.5 +#define ENGINE_COEFF_MAX 2 +#define ENGINE_DEFAULT_MAXSPEED_ENGINES 5 \ No newline at end of file diff --git a/code/controllers/subsystem/shuttle.dm b/code/controllers/subsystem/shuttle.dm index 441fe44740..9f28a78615 100644 --- a/code/controllers/subsystem/shuttle.dm +++ b/code/controllers/subsystem/shuttle.dm @@ -47,7 +47,7 @@ SUBSYSTEM_DEF(shuttle) var/lockdown = FALSE //disallow transit after nuke goes off - var/auto_call = 99000 //time before in deciseconds in which the shuttle is auto called. Default is 2½ hours plus 15 for the shuttle. So total is 3. + var/auto_call = 99000 //time before in deciseconds in which the shuttle is auto called. Default is 2½ hours plus 15 for the shuttle. So total is 3. /datum/controller/subsystem/shuttle/Initialize(timeofday) if(!arrivals) @@ -544,3 +544,8 @@ SUBSYSTEM_DEF(shuttle) for(var/obj/docking_port/mobile/M in mobile) if(M.is_in_shuttle_bounds(A)) return TRUE + +/datum/controller/subsystem/shuttle/proc/get_containing_shuttle(atom/A) + for(var/obj/docking_port/mobile/M in mobile) + if(M.is_in_shuttle_bounds(A)) + return M diff --git a/code/controllers/subsystem/shuttle.dm.rej b/code/controllers/subsystem/shuttle.dm.rej new file mode 100644 index 0000000000..0fc7b77b16 --- /dev/null +++ b/code/controllers/subsystem/shuttle.dm.rej @@ -0,0 +1,9 @@ +diff a/code/controllers/subsystem/shuttle.dm b/code/controllers/subsystem/shuttle.dm (rejected hunks) +@@ -536,3 +536,7 @@ SUBSYSTEM_DEF(shuttle) + if(M.is_in_shuttle_bounds(A)) + return TRUE + ++/datum/controller/subsystem/shuttle/proc/get_containing_shuttle(atom/A) ++ for(var/obj/docking_port/mobile/M in mobile) ++ if(M.is_in_shuttle_bounds(A)) ++ return M diff --git a/code/datums/shuttles.dm b/code/datums/shuttles.dm index 94226dc8ec..a86574e710 100644 --- a/code/datums/shuttles.dm +++ b/code/datums/shuttles.dm @@ -21,6 +21,10 @@ mappath = "[prefix][shuttle_id].dmm" . = ..() +//Whatever special stuff you want +/datum/map_template/shuttle/proc/on_bought() + return + /datum/map_template/shuttle/emergency port_id = "emergency" name = "Base Shuttle Template (Emergency)" @@ -49,6 +53,12 @@ // first 10 minutes only return world.time - SSticker.round_start_time < 6000 +/datum/map_template/shuttle/emergency/airless/on_bought() + //enable buying engines from cargo + var/datum/supply_pack/P = SSshuttle.supply_packs[/datum/supply_pack/engineering/shuttle_engine] + P.special_enabled = TRUE + + /datum/map_template/shuttle/emergency/asteroid suffix = "asteroid" name = "Asteroid Station Emergency Shuttle" diff --git a/code/game/shuttle_engines.dm b/code/game/shuttle_engines.dm index b364cba2b1..a72c2bf8f6 100644 --- a/code/game/shuttle_engines.dm +++ b/code/game/shuttle_engines.dm @@ -1,21 +1,95 @@ +#define ENGINE_UNWRENCHED 0 +#define ENGINE_WRENCHED 1 +#define ENGINE_WELDED 2 +#define ENGINE_WELDTIME 200 /obj/structure/shuttle name = "shuttle" icon = 'icons/turf/shuttle.dmi' - resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | ACID_PROOF + resistance_flags = LAVA_PROOF | FIRE_PROOF | ACID_PROOF + obj_integrity = 500 + max_integrity = 500 + armor = list(melee = 100, bullet = 10, laser = 10, energy = 0, bomb = 0, bio = 0, rad = 0, fire = 50, acid = 70) //default + ignores melee /obj/structure/shuttle/engine name = "engine" - density = 1 - anchored = 1 + density = TRUE + anchored = TRUE + var/engine_power = 1 + var/state = ENGINE_WELDED //welding shmelding + +//Ugh this is a lot of copypasta from emitters, welding need some boilerplate reduction +/obj/structure/shuttle/engine/can_be_unfasten_wrench(mob/user, silent) + if(state == ENGINE_WELDED) + if(!silent) + to_chat(user, "[src] is welded to the floor!") + return FAILED_UNFASTEN + return ..() + +/obj/structure/shuttle/engine/default_unfasten_wrench(mob/user, obj/item/weapon/wrench/W, time = 20) + . = ..() + if(. == SUCCESSFUL_UNFASTEN) + if(anchored) + state = ENGINE_WRENCHED + else + state = ENGINE_UNWRENCHED + +/obj/structure/shuttle/engine/attackby(obj/item/I, mob/user, params) + add_fingerprint(user) + if(default_unfasten_wrench(user, I)) + return + else if(istype(I, /obj/item/weapon/weldingtool)) + var/obj/item/weapon/weldingtool/WT = I + switch(state) + if(ENGINE_UNWRENCHED) + to_chat(user, "The [src.name] needs to be wrenched to the floor!") + if(EM_SECURED) + if(WT.remove_fuel(0,user)) + playsound(loc, WT.usesound, 50, 1) + user.visible_message("[user.name] starts to weld the [name] to the floor.", \ + "You start to weld \the [src] to the floor...", \ + "You hear welding.") + if(do_after(user,ENGINE_WELDTIME*WT.toolspeed, target = src) && WT.isOn()) + state = ENGINE_WELDED + to_chat(user, "You weld \the [src] to the floor.") + alter_engine_power(engine_power) + if(EM_WELDED) + if(WT.remove_fuel(0,user)) + playsound(loc, WT.usesound, 50, 1) + user.visible_message("[user.name] starts to cut the [name] free from the floor.", \ + "You start to cut \the [src] free from the floor...", \ + "You hear welding.") + if(do_after(user,ENGINE_WELDTIME*WT.toolspeed, target = src) && WT.isOn()) + state = ENGINE_WRENCHED + to_chat(user, "You cut \the [src] free from the floor.") + alter_engine_power(-engine_power) + return + else + return ..() + +/obj/structure/shuttle/engine/Destroy() + if(state == ENGINE_WELDED) + alter_engine_power(-engine_power) + . = ..() + +//Propagates the change to the shuttle. +/obj/structure/shuttle/engine/proc/alter_engine_power(mod) + if(mod == 0) + return + if(SSshuttle.is_in_shuttle_bounds(src)) + var/obj/docking_port/mobile/M = SSshuttle.get_containing_shuttle(src) + if(M) + M.alter_engines(mod) /obj/structure/shuttle/engine/heater name = "heater" icon_state = "heater" + engine_power = 0 // todo make these into 2x1 parts /obj/structure/shuttle/engine/platform name = "platform" icon_state = "platform" + engine_power = 0 /obj/structure/shuttle/engine/propulsion name = "propulsion" @@ -25,6 +99,10 @@ /obj/structure/shuttle/engine/propulsion/burst name = "burst" +/obj/structure/shuttle/engine/propulsion/burst/cargo + state = ENGINE_UNWRENCHED + anchored = FALSE + /obj/structure/shuttle/engine/propulsion/burst/left name = "left" icon_state = "burst_l" diff --git a/code/game/shuttle_engines.dm.rej b/code/game/shuttle_engines.dm.rej new file mode 100644 index 0000000000..d04dfc957e --- /dev/null +++ b/code/game/shuttle_engines.dm.rej @@ -0,0 +1,10 @@ +diff a/code/game/shuttle_engines.dm b/code/game/shuttle_engines.dm (rejected hunks) +@@ -46,7 +117,7 @@ + bound_height = 64 + appearance_flags = 0 + +-obj/structure/shuttle/engine/huge ++/obj/structure/shuttle/engine/huge + name = "engine" + opacity = 1 + icon = 'icons/obj/3x3.dmi' diff --git a/code/modules/cargo/packs.dm b/code/modules/cargo/packs.dm index 8a688d833b..d695e49bce 100644 --- a/code/modules/cargo/packs.dm +++ b/code/modules/cargo/packs.dm @@ -710,6 +710,15 @@ /obj/item/weapon/am_containment) crate_name = "antimatter jar crate" +/datum/supply_pack/engineering/shuttle_engine + name = "Shuttle Engine Crate" + cost = 5000 + access = GLOB.access_ce + contains = list(/obj/structure/shuttle/engine/propulsion/burst/cargo) + crate_name = "shuttle engine crate" + crate_type = /obj/structure/closet/crate/secure/engineering + special = TRUE + ////////////////////////////////////////////////////////////////////////////// //////////////////////////// Medical ///////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////// diff --git a/code/modules/shuttle/emergency.dm b/code/modules/shuttle/emergency.dm index e1ed63793d..5b3ac7f4d1 100644 --- a/code/modules/shuttle/emergency.dm +++ b/code/modules/shuttle/emergency.dm @@ -213,7 +213,7 @@ set_coefficient = 1 else set_coefficient = 0.5 - var/call_time = SSshuttle.emergencyCallTime * set_coefficient + var/call_time = SSshuttle.emergencyCallTime * set_coefficient * engine_coeff switch(mode) // The shuttle can not normally be called while "recalling", so // if this proc is called, it's via admin fiat @@ -359,7 +359,7 @@ enterTransit() mode = SHUTTLE_ESCAPE launch_status = ENDGAME_LAUNCHED - setTimer(SSshuttle.emergencyEscapeTime) + setTimer(SSshuttle.emergencyEscapeTime * engine_coeff) priority_announce("The Emergency Shuttle has left the station. Estimate [timeLeft(600)] minutes until the shuttle docks at Central Command.", null, null, "Priority") if(SHUTTLE_STRANDED) diff --git a/code/modules/shuttle/manipulator.dm b/code/modules/shuttle/manipulator.dm index c2feb1331a..6dcf366ba5 100644 --- a/code/modules/shuttle/manipulator.dm +++ b/code/modules/shuttle/manipulator.dm @@ -285,6 +285,9 @@ message_admins(msg) WARNING(msg) + return + //Everything fine + S.on_bought() /obj/machinery/shuttle_manipulator/proc/unload_preview() if(preview_shuttle) diff --git a/code/modules/shuttle/shuttle.dm b/code/modules/shuttle/shuttle.dm index 96db9d0ac3..b9457f9394 100644 --- a/code/modules/shuttle/shuttle.dm +++ b/code/modules/shuttle/shuttle.dm @@ -12,7 +12,7 @@ resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF anchored = 1 - +// var/id // this should point -away- from the dockingport door, ie towards the ship dir = NORTH @@ -224,11 +224,9 @@ var/timid = FALSE var/list/ripples = list() - -/obj/docking_port/mobile/Initialize() - . = ..() - if(!timid) - register() + var/engine_coeff = 1 //current engine coeff + var/current_engines = 0 //current engine power + var/initial_engines = 0 //initial engine power /obj/docking_port/mobile/proc/register() SSshuttle.mobile += src @@ -244,6 +242,8 @@ /obj/docking_port/mobile/Initialize(mapload) . = ..() + if(!timid) + register() var/area/A = get_area(src) if(istype(A, /area/shuttle)) @@ -259,6 +259,9 @@ areaInstance.name = name areaInstance.contents += return_ordered_turfs() + initial_engines = count_engines() + current_engines = initial_engines + #ifdef DOCKING_PORT_HIGHLIGHT highlight("#0f0") #endif @@ -325,17 +328,17 @@ switch(mode) if(SHUTTLE_CALL) if(S == destination) - if(timeLeft(1) < callTime) - setTimer(callTime) + if(timeLeft(1) < callTime * engine_coeff) + setTimer(callTime * engine_coeff) else destination = S - setTimer(callTime) + setTimer(callTime * engine_coeff) if(SHUTTLE_RECALL) if(S == destination) - setTimer(callTime - timeLeft(1)) + setTimer(callTime * engine_coeff - timeLeft(1)) else destination = S - setTimer(callTime) + setTimer(callTime * engine_coeff) mode = SHUTTLE_CALL if(SHUTTLE_IDLE, SHUTTLE_IGNITING) destination = S @@ -621,7 +624,7 @@ return else mode = SHUTTLE_CALL - setTimer(callTime) + setTimer(callTime * engine_coeff) enterTransit() return @@ -685,7 +688,7 @@ var/ds_remaining if(!timer) - ds_remaining = callTime + ds_remaining = callTime * engine_coeff else ds_remaining = max(0, timer - world.time) @@ -765,5 +768,62 @@ return TRUE return FALSE +// Losing all initial engines should get you 2 +// Adding another set of engines at 0.5 time +/obj/docking_port/mobile/proc/alter_engines(mod) + if(mod == 0) + return + var/old_coeff = engine_coeff + engine_coeff = get_engine_coeff(current_engines,mod) + current_engines = max(0,current_engines + mod) + if(in_flight()) + var/delta_coeff = engine_coeff / old_coeff + modTimer(delta_coeff) + +/obj/docking_port/mobile/proc/count_engines() + . = 0 + for(var/obj/structure/shuttle/engine/E in areaInstance.contents) + if(!QDELETED(E)) + . += E.engine_power + +// Double initial engines to get to 0.5 minimum +// Lose all initial engines to get to 2 +//For 0 engine shuttles like BYOS 5 engines to get to doublespeed +/obj/docking_port/mobile/proc/get_engine_coeff(current,engine_mod) + var/new_value = max(0,current + engine_mod) + if(new_value == initial_engines) + return 1 + if(new_value > initial_engines) + var/delta = new_value - initial_engines + var/change_per_engine = (1 - ENGINE_COEFF_MIN) / ENGINE_DEFAULT_MAXSPEED_ENGINES // 5 by default + if(initial_engines > 0) + change_per_engine = (1 - ENGINE_COEFF_MIN) / initial_engines // or however many it had + return Clamp(1 - delta * change_per_engine,ENGINE_COEFF_MIN,ENGINE_COEFF_MAX) + if(new_value < initial_engines) + var/delta = initial_engines - new_value + var/change_per_engine = 1 //doesn't really matter should not be happening for 0 engine shuttles + if(initial_engines > 0) + change_per_engine = (ENGINE_COEFF_MAX - 1) / initial_engines //just linear drop to max delay + return Clamp(1 + delta * change_per_engine,ENGINE_COEFF_MIN,ENGINE_COEFF_MAX) + + +/obj/docking_port/mobile/proc/in_flight() + switch(mode) + if(SHUTTLE_CALL,SHUTTLE_RECALL) + return TRUE + if(SHUTTLE_IDLE,SHUTTLE_IGNITING) + return FALSE + else + return FALSE // hmm + +/obj/docking_port/mobile/emergency/in_flight() + switch(mode) + if(SHUTTLE_ESCAPE) + return TRUE + if(SHUTTLE_STRANDED,SHUTTLE_ENDGAME) + return FALSE + else + return ..() + #undef DOCKING_PORT_HIGHLIGHT