diff --git a/code/__DEFINES/nsv13.dm b/code/__DEFINES/nsv13.dm
index c6fe54ceadb..3af5050427b 100644
--- a/code/__DEFINES/nsv13.dm
+++ b/code/__DEFINES/nsv13.dm
@@ -74,7 +74,8 @@ GLOBAL_DATUM_INIT(conquest_role_handler, /datum/conquest_role_handler, new)
#define COMSIG_SHIP_BOARDED "ship_boarded"
#define COMSIG_GLOB_CHECK_INTERDICT "check_interdict" //from interdiction component
-#define BEING_INTERDICTED (1<<0) //returned on successful interdict
+#define WEAK_INTERDICT (1<<0) //! Not a "true" interdiction in that it disrupts the drive field, relies on scrambling calculations and rendering a jump too dangerous to execute.
+#define STRONG_INTERDICT (1<<1) //! The "true" interdiction, disrupts drive fields to the point any shift is impossible.
//Gaming
#define shares_overmap(A, B) (A.get_overmap() == B.get_overmap())
diff --git a/code/modules/security_levels/keycard_authentication.dm b/code/modules/security_levels/keycard_authentication.dm
index fffc79fdbbe..a3f8402be7f 100644
--- a/code/modules/security_levels/keycard_authentication.dm
+++ b/code/modules/security_levels/keycard_authentication.dm
@@ -3,6 +3,9 @@ GLOBAL_DATUM_INIT(keycard_events, /datum/events, new)
#define KEYCARD_RED_ALERT "Red Alert"
#define KEYCARD_EMERGENCY_MAINTENANCE_ACCESS "Emergency Maintenance Access"
#define KEYCARD_BSA_UNLOCK "Bluespace Artillery Unlock"
+//NSV13
+#define KEYCARD_FTL_SAFETY_OVERRIDE "FTL Safety Override"
+//NSV13 end.
/obj/machinery/keycard_auth
name = "Keycard Authentication Device"
@@ -52,6 +55,13 @@ GLOBAL_DATUM_INIT(keycard_events, /datum/events, new)
data["red_alert"] = (seclevel2num(get_security_level()) >= SEC_LEVEL_RED) ? 1 : 0
data["emergency_maint"] = GLOB.emergency_access
data["bsa_unlock"] = GLOB.bsa_unlock
+ //NSV13 - emergency FTL
+ var/ftl_state = -1 // -1 = not overmap; 0 = Safe; 1 = Unsafe.
+ var/obj/structure/overmap/current_overmap = get_overmap()
+ if(current_overmap)
+ ftl_state = current_overmap.ftl_safety_override
+ data["ftl_safety_override"] = ftl_state
+ //NSV13 end
return data
/obj/machinery/keycard_auth/ui_status(mob/user)
@@ -76,6 +86,12 @@ GLOBAL_DATUM_INIT(keycard_events, /datum/events, new)
. = TRUE
if("auth_swipe")
if(event_source)
+ //NSV13 - cross overmap safety even if the other things don't have it (we can have a subtype for syndi vessels that doesn't have the other options?).
+ var/overmap1 = event_source.get_overmap()
+ var/overmap2 = get_overmap()
+ if(overmap1 != overmap2)
+ return TRUE
+ //NSV13 end.
event_source.trigger_event(usr)
event_source = null
. = TRUE
@@ -83,6 +99,11 @@ GLOBAL_DATUM_INIT(keycard_events, /datum/events, new)
if(!event_source)
sendEvent(KEYCARD_BSA_UNLOCK)
. = TRUE
+ if("ftl_safety_override")
+ if(!event_source)
+ sendEvent(KEYCARD_FTL_SAFETY_OVERRIDE)
+ . = TRUE
+
/obj/machinery/keycard_auth/proc/sendEvent(event_type)
triggerer = usr
@@ -121,6 +142,8 @@ GLOBAL_DATUM_INIT(keycard_events, /datum/events, new)
make_maint_all_access()
if(KEYCARD_BSA_UNLOCK)
toggle_bluespace_artillery()
+ if(KEYCARD_FTL_SAFETY_OVERRIDE)
+ toggle_ftl_drive_safety(get_overmap())
GLOBAL_VAR_INIT(emergency_access, FALSE)
/proc/make_maint_all_access()
@@ -148,6 +171,18 @@ GLOBAL_VAR_INIT(emergency_access, FALSE)
minor_announce("Bluespace Artillery firing protocols have been [GLOB.bsa_unlock? "unlocked" : "locked"]", "Weapons Systems Update:")
SSblackbox.record_feedback("nested tally", "keycard_auths", 1, list("bluespace artillery", GLOB.bsa_unlock? "unlocked" : "locked"))
+///NSV13 - toggles FTL safety mode of a passed vessel.
+/proc/toggle_ftl_drive_safety(obj/structure/overmap/target)
+ if(QDELETED(target))
+ return
+ target.ftl_safety_override = !target.ftl_safety_override
+ if(target.ftl_safety_override) //Safety disengaged.
+ target.relay('nsv13/sound/misc/triple_boop_alert.ogg',"
FTL Drive System Notice
FTL Drive Safeties disengaged. Drive reverting to manual control.
")
+ else //Safety reengaged.
+ target.relay('sound/misc/notice2.ogg', "FTL Drive System Notice
FTL Drive Safeties restored.
")
+//NSV13 end.
+
#undef KEYCARD_RED_ALERT
#undef KEYCARD_EMERGENCY_MAINTENANCE_ACCESS
#undef KEYCARD_BSA_UNLOCK
+#undef KEYCARD_FTL_SAFETY_OVERRIDE
diff --git a/nsv13.dme b/nsv13.dme
index 2abd39ff698..5796f2e456d 100644
--- a/nsv13.dme
+++ b/nsv13.dme
@@ -4045,6 +4045,8 @@
#include "nsv13\code\modules\overmap\FTL\ftl_legacy.dm"
#include "nsv13\code\modules\overmap\FTL\components\drive.dm"
#include "nsv13\code\modules\overmap\FTL\components\drive_pylon.dm"
+#include "nsv13\code\modules\overmap\FTL\ftl_jump_mishaps\jump_mishap_helpers.dm"
+#include "nsv13\code\modules\overmap\FTL\ftl_jump_mishaps\phase_ghost.dm"
#include "nsv13\code\modules\overmap\ship_areas\badmiral.dm"
#include "nsv13\code\modules\overmap\types\miningships.dm"
#include "nsv13\code\modules\overmap\types\nanotrasen.dm"
diff --git a/nsv13/code/__DEFINES/overmap.dm b/nsv13/code/__DEFINES/overmap.dm
index b76e8577e0f..5ef24bbf45e 100644
--- a/nsv13/code/__DEFINES/overmap.dm
+++ b/nsv13/code/__DEFINES/overmap.dm
@@ -120,5 +120,10 @@ GLOBAL_LIST_INIT(overmap_impact_sounds, list('nsv13/sound/effects/ship/freespace
#define SHIELD_FORCE_DEFLECT 2 //!Shield absorbed hit and is redirecting projectile with slightly turned vector.
#define SHIELD_FORCE_REFLECT 3 //!Shield absorbed hit and is redirecting projectile in reverse direction.
+//Emergency FTL stuff.
+
+#define EMERGENCY_FTL_RANGE 120 //! Range of Emergency FTL jump (uncontrolled)
+#define EMERGENCY_FTL_COOLDOWN 35 MINUTES //!Cooldown of FTL drives between emergency jumps.
+
//Interior instancing comsig, aka cursed things.
#define COMSIG_INTERIOR_DONE_LOADING "interior_done_loading"
diff --git a/nsv13/code/modules/overmap/FTL/components/drive.dm b/nsv13/code/modules/overmap/FTL/components/drive.dm
index 513ffa698f0..f2cefcc6403 100644
--- a/nsv13/code/modules/overmap/FTL/components/drive.dm
+++ b/nsv13/code/modules/overmap/FTL/components/drive.dm
@@ -48,6 +48,9 @@
var/ftl_state = FTL_STATE_IDLE
+ ///world.time until which an user can confirm the emergency jump triggered by Nav.
+ var/await_emergency_ftl_confirm = 0
+
/obj/machinery/computer/ship/ftl_core/Initialize(mapload)
. = ..()
add_overlay("screen")
@@ -202,6 +205,16 @@
jump_speed_factor = 5
max_range = initial(max_range) * 3
+///Requests emergency FTL, needs manual confirm at the machine itself.
+/obj/machinery/computer/ship/ftl_core/proc/request_emergency_ftl_confirm()
+ if(await_emergency_ftl_confirm - world.time > 0)
+ return
+ if(!linked.ftl_safety_override)
+ return
+ await_emergency_ftl_confirm = world.time + 15 SECONDS
+ say("Emergency FTL request signal received from Navigation system. Manual confirmation required.")
+ radio.talk_into(src, "Emergency FTL request signal received from Navigation system. Manual confirmation required.", radio_channel)
+
/*
Preset classes of FTL drive with pre-programmed behaviours
*/
@@ -292,6 +305,22 @@ Preset classes of FTL drive with pre-programmed behaviours
return
auto_spool_enabled = !auto_spool_enabled
. = TRUE
+ if("emergency_jump")
+ . = TRUE
+ if(!linked.ftl_safety_override)
+ return
+ if(world.time < linked.next_emergency_jump)
+ say("Failsafe Capacitor still recharging. Emergency transition unavailable.")
+ await_emergency_ftl_confirm = 0
+ return
+ if(world.time > await_emergency_ftl_confirm)
+ return
+ if(progress / req_charge < 0.25)
+ say("FTL not sufficiently spooled for emergency transition. 25% of full charge required.")
+ await_emergency_ftl_confirm = 0
+ return
+ await_emergency_ftl_confirm = 0
+ linked.emergency_jump()
/obj/machinery/computer/ship/ftl_core/ui_data(mob/user)
var/list/data = list()
@@ -317,14 +346,15 @@ Preset classes of FTL drive with pre-programmed behaviours
data["pylons"] = all_pylon_info
data["can_auto_spool"] = auto_spool_capable
data["auto_spool_enabled"] = auto_spool_enabled
+ data["await_emergency_ftl_confirm"] = (await_emergency_ftl_confirm > world.time && linked.ftl_safety_override)
return data
-/obj/machinery/computer/ship/ftl_core/proc/jump(datum/star_system/target_system, force=FALSE)
+/obj/machinery/computer/ship/ftl_core/proc/jump(datum/star_system/target_system, force=FALSE, misjump = FALSE)
ftl_state = FTL_STATE_JUMPING
if(!target_system)
radio.talk_into(src, "ERROR. Specified star_system no longer exists.", radio_channel)
return
- linked.begin_jump(target_system, force)
+ linked.begin_jump(target_system, force, misjump)
playsound(src, 'nsv13/sound/voice/ftl_start.wav', 100, FALSE)
radio.talk_into(src, "Initiating FTL translation.", radio_channel)
playsound(src, 'nsv13/sound/effects/ship/freespace2/computer/escape.wav', 100, 1)
diff --git a/nsv13/code/modules/overmap/FTL/ftl_jump.dm b/nsv13/code/modules/overmap/FTL/ftl_jump.dm
index bcdfc6b9120..2db3738de46 100644
--- a/nsv13/code/modules/overmap/FTL/ftl_jump.dm
+++ b/nsv13/code/modules/overmap/FTL/ftl_jump.dm
@@ -161,10 +161,10 @@
system_contents -= OM
-/obj/structure/overmap/proc/begin_jump(datum/star_system/target_system, force=FALSE)
+/obj/structure/overmap/proc/begin_jump(datum/star_system/target_system, force=FALSE, misjump = FALSE)
relay(ftl_drive.ftl_start, channel = CHANNEL_IMPORTANT_SHIP_ALERT)
desired_angle = 90 //90 degrees AKA face EAST to match the FTL parallax.
- addtimer(CALLBACK(src, PROC_REF(jump_start), target_system, force), ftl_drive.ftl_startup_time)
+ addtimer(CALLBACK(src, PROC_REF(jump_start), target_system, force, misjump), ftl_drive.ftl_startup_time)
/obj/structure/overmap/proc/force_return_jump()
SIGNAL_HANDLER
@@ -214,14 +214,16 @@
if(M && M.client && M.hud_used && length(M.client.parallax_layers))
M.hud_used.update_parallax(force=TRUE)
-/obj/structure/overmap/proc/jump_start(datum/star_system/target_system, force=FALSE)
+/obj/structure/overmap/proc/jump_start(datum/star_system/target_system, force=FALSE, misjump = FALSE)
if(ftl_drive?.ftl_state != FTL_STATE_JUMPING)
- if(force && ftl_drive)
+ if((force || misjump) && ftl_drive)
ftl_drive.ftl_state = FTL_STATE_JUMPING
else
log_runtime("DEBUG: jump_start: aborted jump to [target_system], drive state = [ftl_drive?.ftl_state]")
return
- if((SEND_GLOBAL_SIGNAL(COMSIG_GLOB_CHECK_INTERDICT, src) & BEING_INTERDICTED) && !force) // Override interdiction if the game is over
+
+ var/interdict_return = SEND_GLOBAL_SIGNAL(COMSIG_GLOB_CHECK_INTERDICT, src)
+ if(!force && ((interdict_return & STRONG_INTERDICT) || ((interdict_return & WEAK_INTERDICT) && !misjump))) // Override interdiction if the game is over, flying unsafe also bypasses non-fielddisruptive interdiction.
ftl_drive.radio.talk_into(ftl_drive, "Warning. Local energy anomaly detected - calculated jump parameters invalid. Performing emergency reboot.", ftl_drive.radio_channel)
relay('sound/magic/lightning_chargeup.ogg', channel=CHANNEL_IMPORTANT_SHIP_ALERT)
ftl_drive.depower()
@@ -242,6 +244,8 @@
if(drive_speed <= 0) //Assumption: If we got into this proc with speed 0, we want it to jump anyways, as it should be caught before otherwise. Using very slow speed in this case.
drive_speed = 1 //Div-by-0s are not fun.
var/speed = (curr.dist(target_system) / (drive_speed * 10)) //TODO: FTL drive speed upgrades.
+ if(misjump)
+ speed = max(speed, 3)
SSstar_system.ships[src]["to_time"] = world.time + speed MINUTES
SEND_SIGNAL(src, COMSIG_FTL_STATE_CHANGE)
if(role == MAIN_OVERMAP) //Scuffed please fix
@@ -255,9 +259,11 @@
SSstar_system.ships[src]["target_system"] = target_system
SSstar_system.ships[src]["from_time"] = world.time
SSstar_system.ships[src]["current_system"] = null
- addtimer(CALLBACK(src, PROC_REF(jump_end), target_system), speed MINUTES)
+ addtimer(CALLBACK(src, PROC_REF(jump_end), target_system, misjump), speed MINUTES)
ftl_drive.depower(ftl_drive.auto_spool_enabled)
jump_handle_shake()
+ if(misjump)
+ on_misjump_start(target_system, (speed MINUTES))
force_parallax_update(TRUE)
/obj/structure/overmap/proc/jump_handle_shake(ftl_start)
@@ -286,7 +292,7 @@
shake_with_inertia(M, 4, 1, list(distance=nearestDistance, machine=nearestMachine))
-/obj/structure/overmap/proc/jump_end(datum/star_system/target_system)
+/obj/structure/overmap/proc/jump_end(datum/star_system/target_system, misjump = FALSE)
if(reserved_z) //Actual overmap parallax behaviour
var/datum/space_level/SL = SSmapping.z_list[reserved_z]
SL.set_parallax( (current_system != null) ? current_system.parallax_property : target_system.parallax_property, null)
@@ -300,7 +306,15 @@
SSstar_system.ships[src]["from_time"] = 0
SSstar_system.ships[src]["to_time"] = 0
SEND_SIGNAL(src, COMSIG_FTL_STATE_CHANGE)
- relay(ftl_drive.ftl_exit, "You feel the ship lurch to a halt", loop=FALSE, channel = CHANNEL_SHIP_ALERT)
+ if(!misjump)
+ relay(ftl_drive.ftl_exit, "You feel the ship lurch to a halt", loop=FALSE, channel = CHANNEL_SHIP_ALERT)
+ else
+ var/exit_sound = pick(list('nsv13/sound/effects/ship/misjump/misjump_exit_01.ogg', 'nsv13/sound/effects/ship/misjump/misjump_exit_02.ogg'))
+ relay(message = "You feel the ship violently leave drive space!")
+ for(var/mob/mob in mobs_in_ship)
+ if(!mob.client)
+ continue
+ mob.playsound_local(soundin = exit_sound, vol = 100, vary = FALSE) //Going for direct sound over relay because people should hear this, while system related sounds sometimes override relay.
var/list/pulled = list()
for(var/obj/structure/overmap/SOM as() in GLOB.overmap_objects) //Needs to go through global objects due to being in jumpspace not a system.
@@ -317,9 +331,10 @@
SEND_SIGNAL(src, COMSIG_SHIP_ARRIVED) // Let missions know we have arrived in the system
jump_handle_shake()
+ if(misjump)
+ on_misjump_end(target_system)
force_parallax_update(FALSE)
-
/obj/item/ftl_slipstream_chip
name = "Quantum slipstream field generation matrix (tier II)"
desc = "An upgrade to the ship's FTL computer, allowing it to benefit from cutting edge calculation technologies to result in faster jump times by changing the way in which it allows the ship to incurse into bluespace."
diff --git a/nsv13/code/modules/overmap/FTL/ftl_jump_mishaps/jump_mishap_helpers.dm b/nsv13/code/modules/overmap/FTL/ftl_jump_mishaps/jump_mishap_helpers.dm
new file mode 100644
index 00000000000..4b2c1b837e2
--- /dev/null
+++ b/nsv13/code/modules/overmap/FTL/ftl_jump_mishaps/jump_mishap_helpers.dm
@@ -0,0 +1,326 @@
+///Has the ship begin an emergency jump. Very hazardous.
+/obj/structure/overmap/proc/emergency_jump()
+ var/datum/star_system/target_system = current_system
+ var/list/viable_systems = SSstar_system.systems.Copy()
+ shuffle_inplace(viable_systems)
+ for(var/datum/star_system/potential_target as() in viable_systems)
+ if(current_system.dist(potential_target) > EMERGENCY_FTL_RANGE)
+ continue
+ if(potential_target.hidden)
+ continue
+ if(potential_target.sector != current_system.sector)
+ continue
+ target_system = potential_target
+ break
+ next_emergency_jump = world.time + EMERGENCY_FTL_COOLDOWN
+ ftl_drive.jump(target_system, misjump = TRUE) //Buckle up, here we go.
+
+///Called on jump start if the jump is a misjump.
+/obj/structure/overmap/proc/on_misjump_start(datum/star_system/target_system, jump_length)
+ if(!occupying_levels || !linked_areas)
+ take_damage(0.4 * max_integrity, BRUTE, bypasses_shields = TRUE, sound_effect = FALSE)
+ return
+ else
+ take_damage((rand(5, 10) / 100) * max_integrity, BRUTE, bypasses_shields = TRUE, sound_effect = FALSE)
+ handle_concerning_noises(jump_length)
+ addtimer(CALLBACK(src, PROC_REF(fry_phasestate)), rand(35, 180) SECONDS)
+ disjoint_phasestate()
+
+///Called on jump end if the jump is a misjump.
+/obj/structure/overmap/proc/on_misjump_end(datum/star_system/target_system)
+ if(!occupying_levels || !linked_areas)
+ take_damage(0.5 * max_integrity, BRUTE, bypasses_shields = TRUE, sound_effect = FALSE, nsv_damagesound = FALSE)
+ return
+ else
+ var/structure_stress = prob(25) ? 10 : rand(15,75)
+ var/structure_damage = (structure_stress / 100) * max_integrity
+ take_damage(structure_damage, BRUTE, bypasses_shields = TRUE, sound_effect = FALSE, nsv_damagesound = FALSE)
+
+ var/fun_meteors = pick(0,0,0,0,1,2,2,3,4)
+ var/oops_asteroid_collision = 25
+ for(var/obj/structure/overmap/asteroid/asteroid in target_system.system_contents)
+ oops_asteroid_collision += 5
+ oops_asteroid_collision = CLAMP(oops_asteroid_collision, 25, 90)
+ fry_phasestate()
+ if(prob(oops_asteroid_collision))
+ handle_asteroid_phase_collision()
+ if(fun_meteors > 0)
+ handle_meteor_launches(fun_meteors)
+
+///Provides occassional concerning noises while emergency jumping, also occasionally distorts the drive bubble, creating anomalies.
+/obj/structure/overmap/proc/handle_concerning_noises(jump_length)
+ new /datum/misjump_noise_handler(src, jump_length)
+
+//Creates fun and engaging noises, self deletes shortly before jump end, or on end, or if the owner deletes. Also does some other stuff.
+/datum/misjump_noise_handler
+ ///Linked overmap
+ var/obj/structure/overmap/linked
+ ///Next world.time or above to do things at
+ var/next_noise = 0
+ ///Sounds to choose from
+ var/static/list/yowie_sounds = list('nsv13/sound/ambience/ship_damage/creak5.ogg' = 10, 'nsv13/sound/ambience/ship_damage/creak6.ogg' = 10, 'nsv13/sound/ambience/ship_damage/creak7.ogg' = 2)
+ ///The timer that tracks our time-based deletion
+ var/deletetimer
+
+/datum/misjump_noise_handler/New(obj/structure/overmap/linked_ship, jump_length)
+ . = ..()
+ if(!linked_ship)
+ log_runtime("A misjump noise handler was created without a linked ship :(")
+ linked = linked_ship
+ deletetimer = addtimer(CALLBACK(src, PROC_REF(on_timer_expire)), jump_length - (20 SECONDS), TIMER_STOPPABLE)
+ RegisterSignal(linked, COMSIG_PARENT_QDELETING, PROC_REF(cease_noise)) //If we are somehow faster than we expected.
+ RegisterSignal(linked, COMSIG_SHIP_ARRIVED, PROC_REF(cease_noise))
+ START_PROCESSING(SSprocessing, src)
+
+///Handles deletion if our timer runs out.
+/datum/misjump_noise_handler/proc/on_timer_expire()
+ deletetimer = null
+ qdel(src)
+
+///Handles deletion if one of our two signals gets triggered.
+/datum/misjump_noise_handler/proc/cease_noise()
+ SIGNAL_HANDLER
+ qdel(src)
+
+/datum/misjump_noise_handler/Destroy(force, ...)
+ if(deletetimer)
+ deltimer(deletetimer)
+ deletetimer = null
+ UnregisterSignal(linked, COMSIG_PARENT_QDELETING)
+ UnregisterSignal(linked, COMSIG_SHIP_ARRIVED)
+ linked = null
+ STOP_PROCESSING(SSprocessing, src)
+ return ..()
+
+/datum/misjump_noise_handler/process(delta_time)
+ if(next_noise > world.time)
+ return
+ var/yowie_sound = pickweight(yowie_sounds)
+ linked.relay(yowie_sound)
+ if(prob(1))
+ var/oops_reality_distortion = pick(/obj/effect/anomaly/stormdrive, /obj/effect/anomaly/stormdrive/sheer, /obj/effect/anomaly/bluespace)
+ var/list/possible_areas = linked.linked_areas.Copy() //we really should have a different space area for the NSV huh (and we even already have nearstation)
+ shuffle_inplace(possible_areas)
+ var/area/target_area
+ for(var/area/possible_area in possible_areas)
+ if(istype(possible_area, /area/space))
+ continue
+ target_area = possible_area
+ break
+ var/turf/target_turf
+ for(var/turf/possible_target in target_area.contents)
+ target_turf = possible_target
+ break
+ if(target_turf)
+ new oops_reality_distortion(target_turf)
+ if(linked.reserved_z)
+ var/turf/hmmm = locate(rand(TRANSITIONEDGE, world.maxx - TRANSITIONEDGE), rand(TRANSITIONEDGE, world.maxy - TRANSITIONEDGE), linked.reserved_z)
+ if(hmmm)
+ new /obj/structure/overmap/ref_0x000000(hmmm, linked)
+ if(linked.structure_crit && prob(20)) //Bad times.
+ var/datum/space_level/picked_z = pick(linked.occupying_levels)
+ var/turf/explode_turf = locate(rand(TRANSITIONEDGE, world.maxx - TRANSITIONEDGE), rand(TRANSITIONEDGE, world.maxy - TRANSITIONEDGE), picked_z.z_value)
+ if(isturf(explode_turf) && !isspaceturf(explode_turf)) //If we roll space, you got lucky.
+ new /obj/effect/temp_visual/explosion_telegraph(explode_turf, 100 * round(((world.time - linked.structure_crit_init) / (1 MINUTES)) + 1))
+ next_noise = world.time + 8 SECONDS
+
+///Launches a meteor from the front side somewhere towards the vessel.
+/obj/structure/overmap/proc/handle_meteor_launches(fun_meteors = 0)
+ var/list/possible_areas = linked_areas.Copy()
+ for(var/i = 1; i <= fun_meteors; i++)
+ shuffle_inplace(possible_areas)
+ var/area/main_target_area
+ for(var/area/possible_area in possible_areas)
+ if(istype(possible_area, /area/space))
+ continue
+ main_target_area = possible_area
+ break
+ var/turf/main_target_turf
+ for(var/turf/possible_target_turf in main_target_area.contents)
+ main_target_turf = possible_target_turf
+ break
+ if(!main_target_turf) //huh?
+ continue
+ var/turf/spawn_turf = locate(world.maxx - (TRANSITIONEDGE+1), main_target_turf.y, main_target_turf.z)
+ var/turf/real_target = locate((TRANSITIONEDGE+1), main_target_turf.y, main_target_turf.z)
+ if(!spawn_turf || !real_target)
+ continue
+ var/meteor_type = pickweight(GLOB.meteors_threatening)
+ new meteor_type(spawn_turf, real_target)
+
+// ~
+/obj/structure/overmap/ref_0x000000
+ name = "??????"
+ max_integrity = 10000
+ obj_integrity = 10000
+ desc = null
+ alpha = 0
+ layer = EFFECTS_LAYER
+ opacity = MOUSE_OPACITY_TRANSPARENT
+ invisibility = INVISIBILITY_MAXIMUM
+ resistance_flags = INDESTRUCTIBLE
+ destruction_effects = FALSE
+ ///Linked overmap
+ var/obj/structure/overmap/linked
+ brakes = FALSE
+ inertial_dampeners = FALSE
+ sensor_profile = 255
+
+/obj/structure/overmap/ref_0x000000/handle_cloak(state)
+ return
+
+/obj/structure/overmap/ref_0x000000/take_damage(damage_amount, damage_type, damage_flag, sound_effect, bypasses_shields, nsv_damagesound)
+ return
+
+/obj/structure/overmap/ref_0x000000/bullet_act(obj/item/projectile/P)
+ return BULLET_ACT_FORCE_PIERCE
+
+/obj/structure/overmap/ref_0x000000/ex_act()
+ return
+
+/obj/structure/overmap/ref_0x000000/singularity_act()
+ return
+
+/obj/structure/overmap/ref_0x000000/apply_weapons()
+ return
+
+/obj/structure/overmap/ref_0x000000/is_sensor_visible(obj/structure/overmap/observer)
+ return SENSOR_VISIBILITY_VERYFAINT
+
+/obj/structure/overmap/ref_0x000000/Initialize(mapload, obj/structure/overmap/linked_ship)
+ . = ..()
+ linked = linked_ship
+ RegisterSignal(linked, COMSIG_SHIP_ARRIVED, PROC_REF(self_delete))
+ velocity.a += (rand() - 0.5) * 2
+ velocity.e += (rand() - 0.5) * 2
+ QDEL_IN(src, rand(2,4) MINUTES)
+
+///Handles self deletion if signal is triggered
+/obj/structure/overmap/ref_0x000000/proc/self_delete()
+ SIGNAL_HANDLER
+ qdel(src)
+
+/obj/structure/overmap/ref_0x000000/Destroy(force)
+ UnregisterSignal(linked, COMSIG_SHIP_ARRIVED)
+ linked = null
+ return ..()
+
+///Called if the ship decides to leave drive space in a very bad spot.
+/obj/structure/overmap/proc/handle_asteroid_phase_collision()
+ if(!occupying_levels)
+ return
+ var/datum/space_level/target_z_level = pick(occupying_levels)
+ var/target_z = target_z_level.z_value
+ var/target_x = rand(40, world.maxx -40)
+ var/target_y = rand(40, world.maxy -40)
+ var/core_turf = locate(target_x, target_y, target_z)
+ var/list/potential_asteroids = flist("_maps/map_files/Mining/nsv13/asteroids/")
+ var/datum/map_template/asteroid_template = new /datum/map_template/asteroid("_maps/map_files/Mining/nsv13/asteroids/[pick(potential_asteroids)]", null, FALSE, list(/turf/closed/mineral/iron, /turf/closed/mineral/titanium, /turf/closed/mineral/plasma, /turf/closed/mineral/bscrystal))
+ var/list/asteroidbounds = asteroid_template.load(core_turf, TRUE, TRUE)
+ var/turf/bound1 = locate(asteroidbounds[MAP_MINX], asteroidbounds[MAP_MINY], asteroidbounds[MAP_MINZ])
+ var/turf/bound2 = locate(asteroidbounds[MAP_MAXX], asteroidbounds[MAP_MAXY], asteroidbounds[MAP_MAXZ])
+ if(!bound1 || !bound2)
+ return
+ for(var/y_iter = bound1.y, y_iter <= bound2.y, y_iter++)
+ for(var/x_iter = bound1.x, x_iter <= bound2.x, x_iter++)
+ var/turf/squish = locate(x_iter, y_iter, target_z)
+ if(!isclosedturf(squish))
+ continue
+ for(var/mob/living/squished in squish)
+ if(squished.client)
+ to_chat(squished, "You are suddenly crushed by something solid materializing in your own space!")
+ squished.gib()
+
+///Messes with turf spacetime in a certain area.
+/obj/structure/overmap/proc/disjoint_phasestate()
+ for(var/mob/living/cloned in mobs_in_ship)
+ var/turf/target_turf = get_turf(cloned)
+ if(!target_turf)
+ continue
+ var/obj/effect/abstract/phase_ghost/ghost = new(target_turf)
+ ghost.set_up(cloned)
+ var/list/possible_areas = linked_areas.Copy()
+ shuffle_inplace(possible_areas)
+ var/area/target_area
+ for(var/area/possible_area in possible_areas)
+ if(istype(possible_area, /area/space))
+ continue
+ target_area = possible_area
+ break
+ var/turf/target_turf
+ for(var/turf/possible_turf in target_area.contents)
+ target_turf = possible_turf //Why in the name of Ratvar is there no turf area list.
+ break
+ if(!target_turf)
+ return
+ var/list/turfs = spiral_range_turfs(12, target_turf)
+ if(!turfs.len)
+ return
+ var/list/turf_steps = list()
+ var/length = round(turfs.len * 0.5)
+ for(var/i in 1 to length)
+ turf_steps[pick_n_take(turfs)] = pick_n_take(turfs)
+ if(turfs.len > 0)
+ var/turf/loner = pick(turfs)
+ turf_steps[loner] = get_turf(pick(target_area.contents))
+
+ var/list/effects = list()
+ for(var/V in turf_steps)
+ var/turf/T0 = V
+ var/turf/T1 = turf_steps[V]
+ var/obj/effect/cross_action/spacetime_dist/STD0 = new /obj/effect/cross_action/spacetime_dist(T0)
+ var/obj/effect/cross_action/spacetime_dist/STD1 = new /obj/effect/cross_action/spacetime_dist(T1)
+ STD0.linked_dist = STD1
+ STD0.add_overlay(T1.photograph())
+ STD1.linked_dist = STD0
+ STD1.add_overlay(T0.photograph())
+ STD1.set_light(4, 30, "#c9fff5")
+ effects += STD0
+ effects += STD1
+ addtimer(CALLBACK(src, PROC_REF(clear_distortion), effects), rand(4,6) MINUTES)
+
+///Resets things after the timer expires
+/obj/structure/overmap/proc/clear_distortion(list/effects)
+ for(var/effect in effects)
+ qdel(effect)
+
+///Causes permanent spatial displacement.
+/obj/structure/overmap/proc/fry_phasestate()
+ var/num = rand(1,3)
+ var/list/possible_area_picks = linked_areas.Copy() //we really should have a different space area for the NSV huh (and we even already have nearstation)
+ shuffle_inplace(possible_area_picks)
+ for(var/area/possible_area in possible_area_picks)
+ if(istype(possible_area, /area/space))
+ possible_area_picks -= possible_area
+ num = min(num, length(possible_area_picks))
+ for(var/frycount = 1; frycount <= num; frycount++)
+ var/area/target_area = pick_n_take(possible_area_picks)
+ var/turf/target_turf = get_turf(pick(target_area.contents))
+ if(!target_turf)
+ continue
+ var/list/to_scrungle = RANGE_TURFS(3, target_turf)
+ shuffle_inplace(to_scrungle)
+ for(var/i = 1; i <= length(to_scrungle)-1; i += 2)
+ ///Turf doing the swapping
+ var/turf/turf1 = to_scrungle[i]
+ ///Turf being swapped with.
+ var/turf/turf2 = to_scrungle[i+1]
+ ///Type of second turf.
+ var/turf2_type = turf2.type
+ ///Baseturfs of second turf.
+ var/list/turf2_originals
+ if(islist(turf2.baseturfs)) //Why can baseturfs both be a single non-list path or a list of them..
+ turf2_originals = turf2.baseturfs.Copy()
+ else
+ turf2_originals = turf2.baseturfs
+ ///Contents of the second turf.
+ var/list/turf2_contents = turf2.contents.Copy()
+ if(islist(turf1.baseturfs))
+ turf2.ChangeTurf(turf1.type, turf1.baseturfs.Copy(), CHANGETURF_INHERIT_AIR)
+ else
+ turf2.ChangeTurf(turf1.type, turf1.baseturfs, CHANGETURF_INHERIT_AIR)
+ for(var/atom/movable/thing in turf1)
+ thing.forceMove(turf2)
+ turf1.ChangeTurf(turf2_type, turf2_originals, CHANGETURF_INHERIT_AIR)
+ for(var/atom/movable/thing in turf2_contents)
+ thing.forceMove(turf1)
diff --git a/nsv13/code/modules/overmap/FTL/ftl_jump_mishaps/phase_ghost.dm b/nsv13/code/modules/overmap/FTL/ftl_jump_mishaps/phase_ghost.dm
new file mode 100644
index 00000000000..06f04a2fdad
--- /dev/null
+++ b/nsv13/code/modules/overmap/FTL/ftl_jump_mishaps/phase_ghost.dm
@@ -0,0 +1,24 @@
+/obj/effect/abstract/phase_ghost
+ name = "?????"
+ alpha = 0
+ invisibility = INVISIBILITY_MAXIMUM
+ resistance_flags = INDESTRUCTIBLE
+
+///Links the echo to a existing thing.
+/obj/effect/abstract/phase_ghost/proc/set_up(mob/living/clone)
+ icon = clone.icon
+ icon_state = clone.icon_state
+ copy_overlays(clone, TRUE)
+ addtimer(CALLBACK(src, PROC_REF(appear)), rand(3, 6) MINUTES)
+
+///Makes the echo visible, and sets it to disappear later.
+/obj/effect/abstract/phase_ghost/proc/appear()
+ invisibility = 0
+ alpha = 100
+ add_atom_colour("#77abff", FIXED_COLOUR_PRIORITY)
+ QDEL_IN(src, rand(13, 20) MINUTES)
+
+/obj/effect/abstract/phase_ghost/Destroy(force)
+ icon = null
+ icon_state = null
+ return ..()
diff --git a/nsv13/code/modules/overmap/FTL/ftl_legacy.dm b/nsv13/code/modules/overmap/FTL/ftl_legacy.dm
index 0d48a618bbb..4e9fc054947 100644
--- a/nsv13/code/modules/overmap/FTL/ftl_legacy.dm
+++ b/nsv13/code/modules/overmap/FTL/ftl_legacy.dm
@@ -35,6 +35,9 @@
var/auto_spool_enabled = FALSE //For lazy admins
var/lockout = FALSE //Used for our end round shenanigains
+ ///world.time until which an user can confirm the emergency jump triggered by Nav.
+ var/await_emergency_ftl_confirm = 0
+
/obj/machinery/computer/ship/ftl_computer/attackby(obj/item/I, mob/user) //Allows you to upgrade dradis consoles to show asteroids, as well as revealing more valuable ones.
. = ..()
if(istype(I, /obj/item/ftl_slipstream_chip))
@@ -212,6 +215,22 @@ A way for syndies to track where the player ship is going in advance, so they ca
jump(S)
check_active(FALSE)
break
+ if("emergency_jump")
+ . = TRUE
+ if(!linked.ftl_safety_override)
+ return
+ if(world.time > await_emergency_ftl_confirm)
+ return
+ if(world.time < linked.next_emergency_jump)
+ say("Failsafe Capacitor still recharging. Emergency transition unavailable.")
+ await_emergency_ftl_confirm = 0
+ return
+ if(progress / spoolup_time < 0.25)
+ say("FTL not sufficiently spooled for emergency transition. 25% of full charge required.")
+ await_emergency_ftl_confirm = 0
+ return
+ await_emergency_ftl_confirm = 0
+ linked.emergency_jump()
/obj/machinery/computer/ship/ftl_computer/ui_data(mob/user)
var/list/data = list()
@@ -232,6 +251,7 @@ A way for syndies to track where the player ship is going in advance, so they ca
for(var/datum/star_system/S in SSstar_system.systems)
if(S.visitable && S != linked.current_system)
data["systems"] += list(list("name" = S.name, "distance" = "2 minutes"))
+ data["await_emergency_ftl_confirm"] = (await_emergency_ftl_confirm > world.time && linked.ftl_safety_override)
return data
/obj/machinery/computer/ship/ftl_computer/proc/check_active(state)
@@ -242,11 +262,11 @@ A way for syndies to track where the player ship is going in advance, so they ca
depower()
STOP_PROCESSING(SSmachines, src)
-/obj/machinery/computer/ship/ftl_computer/proc/jump(datum/star_system/target_system, force=FALSE)
+/obj/machinery/computer/ship/ftl_computer/proc/jump(datum/star_system/target_system, force=FALSE, misjump = FALSE)
if(!target_system)
radio.talk_into(src, "ERROR. Specified star_system no longer exists.", radio_channel)
return
- linked?.begin_jump(target_system, force)
+ linked?.begin_jump(target_system, force, misjump)
playsound(src, 'nsv13/sound/voice/ftl_start.wav', 100, FALSE)
radio.talk_into(src, "Initiating FTL translation.", radio_channel)
playsound(src, 'nsv13/sound/effects/ship/freespace2/computer/escape.wav', 100, 1)
@@ -310,9 +330,22 @@ A way for syndies to track where the player ship is going in advance, so they ca
if(auto_spool_enabled)
active = TRUE
spoolup()
- START_PROCESSING(SSmachines, src)
+ if(!(datum_flags & DF_ISPROCESSING))
+ START_PROCESSING(SSmachines, src)
+ else if(datum_flags & DF_ISPROCESSING)
+ STOP_PROCESSING(SSmachines, src)
return TRUE
return FALSE
/obj/machinery/computer/ship/ftl_computer/proc/get_jump_speed()
return jump_speed_factor
+
+///Requests emergency FTL, needs manual confirm at the machine itself.
+/obj/machinery/computer/ship/ftl_computer/proc/request_emergency_ftl_confirm()
+ if(await_emergency_ftl_confirm - world.time > 0)
+ return
+ if(!linked.ftl_safety_override)
+ return
+ await_emergency_ftl_confirm = world.time + 15 SECONDS
+ say("Emergency FTL request signal received from Navigation system. Manual confirmation required.")
+ radio.talk_into(src, "Emergency FTL request signal received from Navigation system. Manual confirmation required.", radio_channel)
diff --git a/nsv13/code/modules/overmap/ai-skynet.dm b/nsv13/code/modules/overmap/ai-skynet.dm
index 650158d08c2..65ed142df1a 100644
--- a/nsv13/code/modules/overmap/ai-skynet.dm
+++ b/nsv13/code/modules/overmap/ai-skynet.dm
@@ -228,7 +228,8 @@ Adding tasks is easy! Just define a datum for it.
if(world.time < last_encounter_time + combat_move_delay) //So that fleets don't leave mid combat.
return FALSE
- if(SEND_GLOBAL_SIGNAL(COMSIG_GLOB_CHECK_INTERDICT, pick(all_ships)) & BEING_INTERDICTED) //Hypothesis: All ships within a fleet should have the same faction.
+ var/interdict_return = SEND_GLOBAL_SIGNAL(COMSIG_GLOB_CHECK_INTERDICT, pick(all_ships)) //Hypothesis: All ships within a fleet should have the same faction.
+ if((interdict_return & (WEAK_INTERDICT|STRONG_INTERDICT)))
return FALSE
current_system.fleets -= src
diff --git a/nsv13/code/modules/overmap/fighters/_fighters.dm b/nsv13/code/modules/overmap/fighters/_fighters.dm
index b44e62bf267..5d120b5b21b 100644
--- a/nsv13/code/modules/overmap/fighters/_fighters.dm
+++ b/nsv13/code/modules/overmap/fighters/_fighters.dm
@@ -407,7 +407,7 @@ Been a mess since 2018, we'll fix it someday (probably)
name = "Peregrine class attack fighter"
desc = "A Peregrine class attack fighter, solgov's only premiere fighter, mounting minature capital grade phasers and a tiny shield generator."
icon = 'nsv13/icons/overmap/new/solgov/playablefighter.dmi'
- armor = list("melee" = 60, "bullet" = 60, "laser" = 60, "energy" = 30, "bomb" = 30, "bio" = 100, "rad" = 90, "fire" = 90, "acid" = 80, "overmap_light" = 5, "overmap_medium" = 0, "overmap_heavy" = 10)
+ armor = list("melee" = 60, "bullet" = 60, "laser" = 60, "energy" = 30, "bomb" = 30, "bio" = 100, "rad" = 90, "fire" = 90, "acid" = 80, "overmap_light" = 5, "overmap_medium" = 0, "overmap_heavy" = 10)
sprite_size = 32
damage_states = FALSE //temp
max_integrity = 25 //shields.
@@ -770,7 +770,7 @@ Been a mess since 2018, we'll fix it someday (probably)
return ..()
-/obj/structure/overmap/small_craft/take_damage(damage_amount, damage_type = BRUTE, damage_flag = 0, sound_effect = 1, bypasses_shields = FALSE)
+/obj/structure/overmap/small_craft/take_damage(damage_amount, damage_type = BRUTE, damage_flag = 0, sound_effect = 1, bypasses_shields = FALSE, nsv_damagesound = TRUE)
var/obj/item/fighter_component/armour_plating/A = loadout.get_slot(HARDPOINT_SLOT_ARMOUR)
if(A && istype(A))
A.take_damage(damage_amount, damage_type, damage_flag, sound_effect)
diff --git a/nsv13/code/modules/overmap/interdiction.dm b/nsv13/code/modules/overmap/interdiction.dm
index 9a80525514f..f18e72ff062 100644
--- a/nsv13/code/modules/overmap/interdiction.dm
+++ b/nsv13/code/modules/overmap/interdiction.dm
@@ -19,7 +19,7 @@ Welcome to the gardens of kadesh. You shall never leave.
if(owner.faction == interdicted.faction)
return
owner.on_interdict()
- return BEING_INTERDICTED
+ return WEAK_INTERDICT
/*
diff --git a/nsv13/code/modules/overmap/overmap.dm b/nsv13/code/modules/overmap/overmap.dm
index 2c5eba460a9..aad2662871a 100644
--- a/nsv13/code/modules/overmap/overmap.dm
+++ b/nsv13/code/modules/overmap/overmap.dm
@@ -28,6 +28,9 @@
var/overmap_deletion_traits = DAMAGE_DELETES_UNOCCUPIED | DAMAGE_STARTS_COUNTDOWN
var/deletion_teleports_occupants = FALSE
+ ///Should sound be relayed & the destruction overlay be created on destruction?
+ var/destruction_effects = TRUE
+
var/sprite_size = 64 //Pixels. This represents 64x64 and allows for the bullets that you fire to align properly.
var/area_type = null //Set the type of the desired area you want a ship to link to, assuming it's not the main player ship.
var/impact_sound_cooldown = FALSE //Avoids infinite spamming of the ship taking damage.
@@ -188,6 +191,11 @@
// It's terrible I know, but until we decide/are bothered enough to throw out the legacy drive (or subtype it), this'll have to do
var/obj/machinery/computer/ship/ftl_core/ftl_drive
+ ///FTL safety state
+ var/ftl_safety_override = FALSE
+ ///FTL emergency jump cooldown; Only available once every 25 minutes.
+ var/next_emergency_jump = 0
+
//Misc variables
var/list/scanned = list() //list of scanned overmap anomalies
var/reserved_z = 0 //The Z level we were spawned on, and thus inhabit. This can be changed if we "swap" positions with another ship.
@@ -516,15 +524,17 @@ Proc to spool up a new Z-level for a player ship and assign it a treadmill.
for(var/mob/living/M in operators)
stop_piloting(M)
GLOB.overmap_objects -= src
- relay('nsv13/sound/effects/ship/damage/ship_explode.ogg')
- relay_to_nearby('nsv13/sound/effects/ship/damage/disable.ogg') //Kaboom.
- new /obj/effect/temp_visual/fading_overmap(get_turf(src), name, icon, icon_state)
+ if(destruction_effects)
+ relay('nsv13/sound/effects/ship/damage/ship_explode.ogg')
+ relay_to_nearby('nsv13/sound/effects/ship/damage/disable.ogg') //Kaboom.
+ new /obj/effect/temp_visual/fading_overmap(get_turf(src), name, icon, icon_state)
for(var/obj/structure/overmap/OM in enemies) //If target's in enemies, return
var/sound = pick('nsv13/sound/effects/computer/alarm.ogg','nsv13/sound/effects/computer/alarm_2.ogg')
var/message = "ATTENTION: [src]'s reactor is going supercritical. Destruction imminent."
OM?.tactical?.relay_sound(sound, message)
OM.enemies -= src //Stops AI from spamming ships that are already dead
- overmap_explode(linked_areas)
+ if(length(linked_areas))
+ overmap_explode(linked_areas)
if(role == MAIN_OVERMAP)
priority_announce("WARNING: ([rand(10,100)]) Attempts to establish DRADIS uplink with [station_name()] have failed. Unable to ascertain operational status. Presumed status: TERMINATED","Central Intelligence Unit", 'nsv13/sound/effects/ship/reactor/explode.ogg')
Cinematic(CINEMATIC_NSV_SHIP_KABOOM,world)
@@ -839,9 +849,9 @@ Proc to spool up a new Z-level for a player ship and assign it a treadmill.
progress = round(((progress / goal) * 100), 25)//Round it down to 20%. We now apply visual damage
icon_state = "[initial(icon_state)]-[progress]"
-/obj/structure/overmap/proc/relay(S, var/message=null, loop = FALSE, channel = null) //Sends a sound + text message to the crew of a ship
+/obj/structure/overmap/proc/relay(S, var/message=null, loop = FALSE, channel = null) //Sends a sound and / or text message to the crew of a ship
for(var/mob/M as() in mobs_in_ship)
- if(M.can_hear())
+ if(S && M.can_hear())
if(channel) //Doing this forbids overlapping of sounds
SEND_SOUND(M, sound(S, repeat = loop, wait = 0, volume = 100, channel = channel))
else
diff --git a/nsv13/code/modules/overmap/starmap.dm b/nsv13/code/modules/overmap/starmap.dm
index 154f7ab7fe0..dc8d2787885 100644
--- a/nsv13/code/modules/overmap/starmap.dm
+++ b/nsv13/code/modules/overmap/starmap.dm
@@ -74,7 +74,13 @@
if(linked.ftl_drive.lockout)
to_chat(usr, "[icon2html(src, viewers(src))] Unable to comply. Invalid authkey to unlock remove override code.")
return
- linked.ftl_drive.jump(selected_system)
+ if(linked.ftl_safety_override)
+ if(linked.next_emergency_jump > world.time)
+ say("Drive Emergency Capacitor is still recharging. Emergency jump unavailable.")
+ return TRUE
+ linked.ftl_drive.request_emergency_ftl_confirm()
+ else
+ linked.ftl_drive.jump(selected_system)
. = TRUE
if("cancel_jump")
if(linked.ftl_drive.lockout)
@@ -213,14 +219,15 @@
if(info["current_system"])
var/datum/star_system/curr = info["current_system"]
data["star_dist"] = curr.dist(selected_system)
- data["can_jump"] = current_system.dist(selected_system) < linked.ftl_drive?.max_range && linked.ftl_drive.ftl_state == FTL_STATE_READY && LAZYFIND(current_system.adjacency_list, selected_system.name)
+ data["can_jump"] = (current_system.dist(selected_system) < linked.ftl_drive?.max_range && linked.ftl_drive.ftl_state == FTL_STATE_READY && LAZYFIND(current_system.adjacency_list, selected_system.name)) || (linked.ftl_safety_override && linked.ftl_drive && linked.ftl_drive.ftl_state != FTL_STATE_JUMPING)
if(return_jump_check(selected_system) && linked.ftl_drive.ftl_state == FTL_STATE_READY)
data["can_jump"] = TRUE
if(!can_control_ship) //For public consoles
data["can_jump"] = FALSE
data["can_cancel"] = FALSE
+ data["ftl_safety_override"] = linked?.ftl_safety_override
data["screen"] = screen
- data["can_cancel"] = linked?.ftl_drive?.ftl_state == FTL_STATE_JUMPING && linked?.ftl_drive?.can_cancel_jump
+ data["can_cancel"] = linked?.ftl_drive?.ftl_state == FTL_STATE_JUMPING && linked?.ftl_drive?.can_cancel_jump && !linked?.ftl_safety_override
return data
/obj/machinery/computer/ship/navigation/proc/is_in_range(datum/star_system/current_system, datum/star_system/system)
diff --git a/nsv13/code/modules/overmap/weapons/damage.dm b/nsv13/code/modules/overmap/weapons/damage.dm
index 09147b657e4..d1b75b92f79 100644
--- a/nsv13/code/modules/overmap/weapons/damage.dm
+++ b/nsv13/code/modules/overmap/weapons/damage.dm
@@ -75,7 +75,7 @@ Bullet reactions
/obj/structure/overmap/small_craft/relay_damage(proj_type)
return
-/obj/structure/overmap/take_damage(damage_amount, damage_type = BRUTE, damage_flag = 0, sound_effect = 1, bypasses_shields = FALSE)
+/obj/structure/overmap/take_damage(damage_amount, damage_type = BRUTE, damage_flag = 0, sound_effect = 1, bypasses_shields = FALSE, nsv_damagesound = TRUE)
var/blocked = FALSE
var/damage_sound = pick(GLOB.overmap_impact_sounds)
if(!bypasses_shields && shields && shields.absorb_hit(damage_amount))
@@ -83,7 +83,7 @@ Bullet reactions
damage_sound = pick('nsv13/sound/effects/ship/damage/shield_hit.ogg', 'nsv13/sound/effects/ship/damage/shield_hit2.ogg')
if(!impact_sound_cooldown)
add_overlay(new /obj/effect/temp_visual/overmap_shield_hit(get_turf(src), src))
- if(!impact_sound_cooldown && damage_sound)
+ if(nsv_damagesound && !impact_sound_cooldown && damage_sound)
relay(damage_sound)
if(damage_amount >= 15) //Flak begone
shake_everyone(5)
diff --git a/nsv13/sound/effects/ship/misjump/misjump_exit_01.ogg b/nsv13/sound/effects/ship/misjump/misjump_exit_01.ogg
new file mode 100644
index 00000000000..051963221df
Binary files /dev/null and b/nsv13/sound/effects/ship/misjump/misjump_exit_01.ogg differ
diff --git a/nsv13/sound/effects/ship/misjump/misjump_exit_02.ogg b/nsv13/sound/effects/ship/misjump/misjump_exit_02.ogg
new file mode 100644
index 00000000000..3945fe10d77
Binary files /dev/null and b/nsv13/sound/effects/ship/misjump/misjump_exit_02.ogg differ
diff --git a/nsv13/sound/misc/triple_boop_alert.ogg b/nsv13/sound/misc/triple_boop_alert.ogg
new file mode 100644
index 00000000000..d25bd7c77dd
Binary files /dev/null and b/nsv13/sound/misc/triple_boop_alert.ogg differ
diff --git a/tgui/packages/tgui/interfaces/FTLComputer.js b/tgui/packages/tgui/interfaces/FTLComputer.js
index fe9c3699f0e..44e5fb35446 100644
--- a/tgui/packages/tgui/interfaces/FTLComputer.js
+++ b/tgui/packages/tgui/interfaces/FTLComputer.js
@@ -10,48 +10,63 @@ export const FTLComputer = (props, context) => {
return (
-
-
- act('toggle_power')} />
+ {(data.await_emergency_ftl_confirm && (
+
+
+
-
-
+ )) || (
+
+
+ act('toggle_power')} />
+
+
+
+ {Object.keys(data.tracking).map(key => {
+ let value = data.tracking[key];
+ return (
+
+
+ );
+ })}
+
-
- {Object.keys(data.tracking).map(key => {
- let value = data.tracking[key];
- return (
-
-
- );
- })}
-
-
+ )}
);
diff --git a/tgui/packages/tgui/interfaces/FTLComputerModular.js b/tgui/packages/tgui/interfaces/FTLComputerModular.js
index 56a6153648f..b6323dd6e16 100644
--- a/tgui/packages/tgui/interfaces/FTLComputerModular.js
+++ b/tgui/packages/tgui/interfaces/FTLComputerModular.js
@@ -8,88 +8,103 @@ export const FTLComputerModular = (props, context) => {
return (
-
-
-
- {Object.keys(data.pylons).map(key => {
- let value = data.pylons[key];
- return (
-
-
-
- );
- })}
-
- act('find_pylons')} />
-
-
-
- act('toggle_power')} />
- act('toggle_autospool')} />
+ {(data.await_emergency_ftl_confirm && (
+
+
+ act('emergency_jump')}
+ content="CONFIRM EMERGENCY JUMP?"
+ />
+
-
-
+
+
+ {Object.keys(data.pylons).map(key => {
+ let value = data.pylons[key];
+ return (
+
+
+ act('pylon_power', { id: value.id })} />
+ act('toggle_shield', { id: value.id })} />
+
+ Cycle Status: {value.status}
+
+
+ Gyro Speed:
+
+
+ Capacitor Charge:
+
+
+ Power Draw: {value.draw}
+
+ Nucleium: {value.nucleium} mol{value.nucleium !== 1 ? "s" : ""} / s
+
+ );
+ })}
+
+ act('find_pylons')} />
+
+
+
+ act('toggle_power')} />
+ act('toggle_autospool')} />
+
+
-
+ )}
);
diff --git a/tgui/packages/tgui/interfaces/KeycardAuth.js b/tgui/packages/tgui/interfaces/KeycardAuth.js
index 3229bf2d077..1b646643265 100644
--- a/tgui/packages/tgui/interfaces/KeycardAuth.js
+++ b/tgui/packages/tgui/interfaces/KeycardAuth.js
@@ -7,7 +7,7 @@ export const KeycardAuth = (props, context) => {
return (
+ height={150}>
@@ -47,6 +47,12 @@ export const KeycardAuth = (props, context) => {
fluid
onClick={() => act('bsa_unlock')}
content="Bluespace Artillery Unlock" />
+ {data.ftl_safety_override >= 0 && (
+ act('ftl_safety_override')}
+ content="FTL Drive Safety Override" />)}
>
)}
>
diff --git a/tgui/packages/tgui/interfaces/Starmap.js b/tgui/packages/tgui/interfaces/Starmap.js
index d5e4948fe96..74cf5874229 100644
--- a/tgui/packages/tgui/interfaces/Starmap.js
+++ b/tgui/packages/tgui/interfaces/Starmap.js
@@ -212,6 +212,7 @@ export const Starmap = (props, context) => {
act('jump')} />