diff --git a/_maps/map_files/Galactica/Galactica2.dmm b/_maps/map_files/Galactica/Galactica2.dmm
index 671564e3edb..a94c783bad5 100644
--- a/_maps/map_files/Galactica/Galactica2.dmm
+++ b/_maps/map_files/Galactica/Galactica2.dmm
@@ -8596,9 +8596,9 @@
/obj/effect/turf_decal/stripes/line{
dir = 1
},
-/obj/machinery/atmospherics/components/binary/valve/digital/on/layer4{
- dir = 8;
- name = "To Fueltank"
+/obj/machinery/atmospherics/components/binary/volume_pump/layer4{
+ dir = 4;
+ name = "Nucleium Tank To FTL"
},
/turf/open/floor/durasteel/techfloor_grid,
/area/engine/engineering/reactor_core)
@@ -38352,9 +38352,9 @@
/obj/machinery/atmospherics/pipe/simple/orange/visible/layer2{
dir = 4
},
-/obj/machinery/atmospherics/components/binary/valve/digital/on/layer4{
- dir = 8;
- name = "To Fueltank"
+/obj/machinery/atmospherics/components/binary/volume_pump/layer4{
+ name = "Nucleium Tank Out";
+ dir = 8
},
/turf/open/floor/durasteel/techfloor_grid,
/area/engine/engineering/reactor_core)
diff --git a/code/controllers/subsystem/explosion.dm b/code/controllers/subsystem/explosion.dm
index 88560ae1d4f..f038003535e 100644
--- a/code/controllers/subsystem/explosion.dm
+++ b/code/controllers/subsystem/explosion.dm
@@ -415,6 +415,8 @@ SUBSYSTEM_DEF(explosions)
var/turf/T = locate(epicenter.x, epicenter.y, affecting_z)
if(!T)
continue
+ if(devastation_range - z_reduction <= 0 && heavy_impact_range - z_reduction <= 0 && light_impact_range - z_reduction <= 0) //NSV13 - explosions still relaying with 0-0-0 can cause REALLY weird behavior.
+ continue
SSexplosions.explode(T,
max(devastation_range - z_reduction, 0),
max(heavy_impact_range - z_reduction, 0),
diff --git a/nsv13/code/__DEFINES/overmap.dm b/nsv13/code/__DEFINES/overmap.dm
index beb76f66c13..8bb8ce50961 100644
--- a/nsv13/code/__DEFINES/overmap.dm
+++ b/nsv13/code/__DEFINES/overmap.dm
@@ -113,3 +113,9 @@ GLOBAL_LIST_INIT(overmap_impact_sounds, list('nsv13/sound/effects/ship/freespace
#define MASS_LARGE 7 //20-40 Players - Medium Capital Ships
#define MASS_TITAN 150 //40+ Players - Large Capital Ships
#define MASS_IMMOBILE 200 //Things that should not be moving. See: stations
+
+//Fun tools
+#define SHIELD_NOEFFECT 0 //!Shield failed to absorb hit.
+#define SHIELD_ABSORB 1 //!Shield absorbed hit.
+#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.
diff --git a/nsv13/code/datums/holocall.dm b/nsv13/code/datums/holocall.dm
index 9f7b712eab5..8b6d7711b09 100644
--- a/nsv13/code/datums/holocall.dm
+++ b/nsv13/code/datums/holocall.dm
@@ -26,7 +26,7 @@
DELAY 20
PRESET /datum/preset_holoimage/corgi
NAME Burst Data
- LANGUAGE /datum/language/eal
+ LANGUAGE /datum/language/machine
SAY START NTINTEL METADATA
SAY RECORDED 12-17-0000
SAY SECURITY CLASS UNCLASSIFIED
@@ -320,7 +320,7 @@
DELAY 50
SAY If you need to shut down the reactor, lower the nucleium injection rate slowly. You can cycle coolant in an emergency for a quick cooling boost.
DELAY 50
- SAY The reaction can be terminated when the reactor core is under 100 Celsius. Ensure cooling is adequate to achieve this.
+ SAY The reaction can be terminated when the reactor core is under 200 Celsius. Ensure cooling is adequate to achieve this.
DELAY 50
SAY Finally. If your minimum input power ever starts to converge on the maximum, you are heading towards an emission. Rectify this immediately, or shut down the reactor safely.
DELAY 50
@@ -328,7 +328,7 @@
DELAY 50
SAY Do your duty. This tape should be destroyed after use. Shield technology does not exist. Glory to Nanotrasen.
NAME Burst Data
- LANGUAGE /datum/language/eal
+ LANGUAGE /datum/language/machine
DELAY 20
SAY START METADATA
SAY RECORDED 5-25-0000
diff --git a/nsv13/code/modules/overmap/pdsr.dm b/nsv13/code/modules/overmap/pdsr.dm
index 36ee7c4b56f..6c52dcb62d7 100644
--- a/nsv13/code/modules/overmap/pdsr.dm
+++ b/nsv13/code/modules/overmap/pdsr.dm
@@ -9,8 +9,11 @@
#define REACTOR_STATE_SHUTTING_DOWN 4
#define REACTOR_STATE_EMISSION 5
+#define DENSITY_LOW 0 //! Deflects only heavy hits.
+#define DENSITY_HIGH 1 //! Deflects all hits.
+
/obj/machinery/atmospherics/components/trinary/defence_screen_reactor
- name = "mk I Prototype Defence Screen Reactor"
+ name = "mk II Prototype Defence Screen Reactor"
desc = "A highly experimental, unstable and highly illegal nucleium driven reactor for the generation of defensive screens."
icon = 'nsv13/icons/obj/machinery/pdsr.dmi'
icon_state = "idle"
@@ -46,10 +49,20 @@
var/last_coolant_time = 0 //Last time we called to flush coolant
var/flushing_coolant = 0 //Are we currently flushing coolant
var/emission_tracker = 0 //Used to track emission timers
+ ///Time when our reactor was last shutdown.
+ var/powerdown_time = 0
+ ///If this is already detonating
+ var/detonating = FALSE
//!Shield Vars
- var/list/shield = list("integrity" = 0, "max_integrity" = 0, "stability" = 0)
+ var/list/shield = list("integrity" = 0, "max_integrity" = 0, "stability" = 0, "density" = DENSITY_HIGH)
var/power_input = 0 //How much power is currently allocated
+ ///Did we get enough power last power tick?
+ var/power_demand_met = FALSE
+ ///How much power did we use during the power tick?
+ var/last_power_use = 0
+ ///How much power was in the grid during power tick?
+ var/last_avail_power = 0
var/screen_regen = 50 //Allocation to regenerate the !shields
var/screen_hardening = 50 //Allocation to strengthen the !shields
var/min_power_input = 0 //Minimum power required to sustain !shield integrity
@@ -95,17 +108,28 @@
/obj/machinery/atmospherics/components/trinary/defence_screen_reactor/proc/try_use_power(amount)
var/turf/T = get_turf(src)
C = T.get_cable_node()
- if(C?.surplus() > amount)
+ if(C?.surplus() >= amount)
C.powernet.load += amount
+ last_power_use = amount
+ power_demand_met = TRUE
+ last_avail_power = C?.surplus()
return TRUE
+ power_demand_met = FALSE
+ last_power_use = 0
+ last_avail_power = C?.surplus()
return FALSE
-/obj/machinery/atmospherics/components/trinary/defence_screen_reactor/process()
+/obj/machinery/atmospherics/components/trinary/defence_screen_reactor/process_atmos()
update_parents()
- if(next_slowprocess < world.time)
+ if(next_slowprocess <= world.time)
slowprocess()
next_slowprocess = world.time + 1 SECONDS
+/obj/machinery/atmospherics/components/trinary/defence_screen_reactor/process()
+ if(state == REACTOR_STATE_IDLE)
+ return
+ try_use_power(power_input)
+
/obj/machinery/atmospherics/components/trinary/defence_screen_reactor/proc/slowprocess()
var/datum/gas_mixture/nucleium_input = airs[2]
var/datum/gas_mixture/coolant_input = airs[1]
@@ -124,31 +148,32 @@
return
current_uptime ++
- reaction_containment += 5
+ reaction_containment += 20 // ~5 seconds as opposed to 20 for core start.
if(reaction_containment >= 100)
reaction_containment = 100
if(reaction_injection_rate < 2.5)
say("Error: Unable to initialise reaction, insufficient nucleium injection.")
- reaction_containment = 0
- current_uptime = 0
- state = REACTOR_STATE_IDLE
+ handle_shutdown()
return
if(nuc_in < reaction_injection_rate)
say("Error: Unable to initialise reaction, insufficient nucleium available.")
- reaction_containment = 0
- current_uptime = 0
- state = REACTOR_STATE_IDLE
+ handle_shutdown()
+ return
+ if(!power_demand_met)
+ say("Error: Power allocation exceeding grid capacity. Failed to initiate reaction.")
+ handle_shutdown()
return
- var/errors = rand(20, 200)
+ var/errors = rand(20, 199)
say("Initiating Reaction - Injecting Nucleium.")
say("Reaction Initialized - [errors] runtimes supressed.")
reaction_temperature = 100 //Flash start to 100
+ shield["stability"] = 50 //begin at 50 during startup.
state = REACTOR_STATE_RUNNING
if(state == REACTOR_STATE_RUNNING)
- if(nuc_in >= reaction_injection_rate) //If we are running in nominal conditions...
+ if(nuc_in >= reaction_injection_rate && reaction_injection_rate >= 2.5) //If we are running in nominal conditions...
nucleium_input.adjust_moles(GAS_NUCLEIUM, -reaction_injection_rate)
//Handle reaction rate adjustments here
var/target_reaction_rate = ((0.5 + (1e-03 * (reaction_injection_rate ** 2))) + (current_uptime / 2000)) * 16
@@ -157,7 +182,7 @@
reaction_temperature += reaction_rate * 0.35 //Function goes
handle_polarity(TRUE)
- else if(nuc_in < reaction_injection_rate) //If we are running without sufficient nucleium...
+ else //If we are running without sufficient nucleium...
if(nuc_in <= 0) //...and none at all
var/target_reaction_rate = 0
var/delta_reaction_rate = target_reaction_rate - reaction_rate
@@ -176,7 +201,7 @@
handle_polarity(TRUE)
if(reaction_rate > 5) //TEMP USE FUNCTIONS
- reaction_energy_output = (reaction_rate + (reaction_injection_rate / 2)) * (2 - (current_uptime / 20000)) //FUNCTIONS
+ reaction_energy_output = (reaction_rate + (min(nuc_in, reaction_injection_rate) / 2)) * (2 - (current_uptime / 20000)) //FUNCTIONS
radiation_pulse(src, reaction_energy_output)
else
@@ -205,21 +230,21 @@
state = REACTOR_STATE_SHUTTING_DOWN
else
say("Error: Reaction Prematurely Terminated - Inspect all systems for damage.")
- state = REACTOR_STATE_IDLE
+ var/list/overload_candidate = list()
+ for(var/obj/machinery/defence_screen_relay/DSR in GLOB.machines)
+ if(DSR.powered() && DSR.overloaded == FALSE)
+ overload_candidate += DSR
for(var/I = 0, I < 3, I++) //Overload Three Relays
- var/list/overload_candidate = list()
- for(var/obj/machinery/defence_screen_relay/DSR in GLOB.machines)
- if(DSR.powered() && DSR.overloaded == FALSE)
- overload_candidate += DSR
- if(overload_candidate.len > 0)
- var/obj/machinery/defence_screen_relay/DSRC = pick(overload_candidate)
- DSRC.overload()
+ if(overload_candidate.len > 0)
+ var/obj/machinery/defence_screen_relay/DSRC = pick_n_take(overload_candidate)
+ DSRC.overload()
depower_shield()
OM.take_quadrant_hit(rand(100, 200), "forward_port")
OM.take_quadrant_hit(rand(100, 200), "forward_starboard")
OM.take_quadrant_hit(rand(100, 200), "aft_port")
OM.take_quadrant_hit(rand(100, 200), "aft_starboard")
+ state = REACTOR_STATE_SHUTTING_DOWN
handle_screens()
handle_temperature()
@@ -283,22 +308,23 @@
//////Reactor Procs//////
/obj/machinery/atmospherics/components/trinary/defence_screen_reactor/proc/handle_containment() //We manage poweruse and containment here
- if(try_use_power(power_input))
- if(power_input > max_power_input && power_input <= 1.25 * max_power_input) //Overloading Containment - Rapid Rise
+ if(power_demand_met)
+ if(last_power_use > max_power_input && last_power_use <= 1.25 * max_power_input) //Overloading Containment - Rapid Rise
var/overloading_containment = reaction_containment
if(overloading_containment < 25)
overloading_containment = 25
var/overloading_function = ((382 * NUM_E **(0.0764 * overloading_containment)) / ((50 + NUM_E ** (0.0764 * overloading_containment)) ** 2)) * 14
- reaction_containment += overloading_function * (power_input / max_power_input)
+ reaction_containment += overloading_function * (last_power_use / max_power_input)
current_uptime ++ //Overloading has a cost
- else if(power_input >= min_power_input && power_input <= max_power_input) //Nominal Containment - Maintain Containment
+ else if(last_power_use >= min_power_input && last_power_use <= max_power_input) //Nominal Containment - Maintain Containment
var/containment_function = ((382 * NUM_E **(0.0764 * reaction_containment)) / ((50 + NUM_E ** (0.0764 * reaction_containment)) ** 2)) * 10
- reaction_containment += containment_function * (power_input / max_power_input)
+ reaction_containment += containment_function * (last_power_use / max_power_input)
- else if(power_input < min_power_input && power_input >= 0.75 * min_power_input) //Insufficient Power for Containment - Slow Loss
+ else if(last_power_use < min_power_input && last_power_use >= 0.75 * min_power_input) //Insufficient Power for Containment - Slow Loss
var/loss_function = ((382 * NUM_E **(0.0764 * reaction_containment)) / ((50 + NUM_E ** (0.0764 * reaction_containment)) ** 2)) * 4
- reaction_containment += loss_function * (power_input / max_power_input)
+ reaction_containment += loss_function * (last_power_use / max_power_input)
+
if(reaction_containment > 100)
reaction_containment = 100
@@ -307,7 +333,7 @@
reaction_containment = 0
emission_tracker = world.time
say("Error: Catatstropic Containment Failure - Initializing Emergency Termination Protocols")
- playsound(src, 'sound/magic/lightning_chargeup.ogg', 100, 0, 15, 10, 10) //Replace me later?
+ playsound(src, 'sound/magic/lightning_chargeup.ogg', 100, FALSE, 15) //Replace me later?
state = REACTOR_STATE_EMISSION //Whoops
/obj/machinery/atmospherics/components/trinary/defence_screen_reactor/proc/handle_power_reqs() //How much power is required
@@ -320,7 +346,7 @@
if(reaction_containment < 33 && state == REACTOR_STATE_RUNNING)
if(next_alarm_sfx < world.time)
next_alarm_sfx = world.time + 3 SECONDS
- playsound(src, 'nsv13/sound/effects/ship/pdsr_warning.ogg', 100, 0, 10, 10)
+ playsound(src, 'nsv13/sound/effects/ship/pdsr_warning.ogg', 100, FALSE, 10)
if(next_alarm_message < world.time)
next_alarm_message = world.time + 15 SECONDS
say("DANGER: Reaction Containment Critical. Emission Imminent.")
@@ -328,7 +354,7 @@
if(state == REACTOR_STATE_EMISSION)
if(next_alarm_sfx < world.time)
next_alarm_sfx = world.time + 3 SECONDS
- playsound(src, 'nsv13/sound/effects/ship/pdsr_warning.ogg', 100, 0, 10, 10)
+ playsound(src, 'nsv13/sound/effects/ship/pdsr_warning.ogg', 100, FALSE, 10)
/obj/machinery/atmospherics/components/trinary/defence_screen_reactor/proc/handle_polarity(var/injecting = FALSE)
if(reaction_polarity_timer < world.time) //Handle the trend
@@ -343,11 +369,7 @@
else
reaction_polarity -= 0.027
- if(reaction_polarity > 1)
- reaction_polarity = 1
-
- if(reaction_polarity < -1)
- reaction_polarity = -1
+ reaction_polarity = clamp(reaction_polarity, -1, 1)
var/polarity_function = abs(0.5 * (reaction_polarity ** 2)) //RECHECK THIS WHEN NOT DEAD
reaction_containment -= polarity_function
@@ -360,7 +382,7 @@
if(in_view_range(M, src))
to_chat(M, "A stream of particles erupts from the [src]!")
M.flash_act(1, 0, 1)
- playsound(src, 'sound/magic/repulse.ogg', 100, 0, 5, 5)
+ playsound(src, 'sound/magic/repulse.ogg', 100, FALSE, 5)
//more goes here
/obj/machinery/atmospherics/components/trinary/defence_screen_reactor/proc/handle_emission_release()
@@ -368,13 +390,13 @@
if(DSR.powered() && DSR.overloaded == FALSE)
DSR.overload()
- var/emission_energy = reaction_energy_output * (1 + (current_uptime / 1000))
+ var/emission_energy = max(10, reaction_energy_output) * (1 + (current_uptime / 1000))
radiation_pulse(src, emission_energy ** 2, 10, 1, 1)
for(var/mob/living/M in OM.mobs_in_ship)
if(M.client)
- M.flash_act((emission_energy / 10), 0 , 1)
- M.Knockdown(emission_energy / 10)
+ M.flash_act(clamp(emission_energy, 30, 100), TRUE, TRUE)
+ M.Knockdown(clamp(emission_energy, 20, 100))
M.adjust_disgust(rand(20, 50))
to_chat(M, "A wash of radiation passes through you!")
@@ -390,6 +412,7 @@
say("Inspect all systems for damage.")
/obj/machinery/atmospherics/components/trinary/defence_screen_reactor/proc/handle_temperature()
+ reaction_containment -= (reaction_temperature / 50) + (current_uptime / 2000)
var/turf/open/L = get_turf(src)
if(!istype(L) || !(L.air))
return
@@ -401,7 +424,6 @@
env.set_temperature(temperature += delta_env / 2)
air_update_turf()
- reaction_containment -= (reaction_temperature / 50) + (current_uptime / 2000)
/obj/machinery/atmospherics/components/trinary/defence_screen_reactor/proc/handle_atmos_check()
for(var/obj/machinery/defence_screen_relay/DSR in GLOB.machines)
@@ -418,6 +440,10 @@
flushing_coolant = 0
reaction_energy_output = 0
emission_tracker = 0
+ powerdown_time = world.time
+ last_power_use = 0
+ power_demand_met = FALSE
+ last_avail_power = 0
depower_shield()
/obj/machinery/atmospherics/components/trinary/defence_screen_reactor/update_icon()
@@ -442,22 +468,28 @@
//////Shield Procs//////
-/obj/machinery/atmospherics/components/trinary/defence_screen_reactor/proc/absorb_hit(damage)
+/obj/machinery/atmospherics/components/trinary/defence_screen_reactor/proc/absorb_hit(obj/item/projectile/proj)
+ var/damage = proj.damage
if(!active)
- return FALSE //!shields not raised
+ return SHIELD_NOEFFECT //!shields not raised
+
+ if(shield["density"] == DENSITY_LOW && (proj.flag != "overmap_heavy" || proj.damage_type == BURN)) //Low density mode does not get hit by low impact projectiles, but also does not help vs. energy weapons.
+ return SHIELD_NOEFFECT
if(shield["integrity"] >= damage)
shield["integrity"] -= damage //Deduct from !shield
var/current_hit = world.time
- if(current_hit <= last_hit + 10) //1 Second
- shield["stability"] -= rand((damage / 10), (damage / 5)) //Rapid hits will reduce stability greatly
+ if(current_hit <= last_hit + 1 SECONDS) //1 Second
+ shield["stability"] -= min(30, rand((damage / 10), (damage / 5))) //Rapid hits will reduce stability greatly
else
- shield["stability"] -= rand((damage / 50), (damage / 25)) //Reduce !shield stability
+ shield["stability"] -= min(10, rand((damage / 50), (damage / 25))) //Reduce !shield stability
last_hit = current_hit //Set our last hit
check_stability()
- return TRUE
+ return SHIELD_FORCE_DEFLECT
+
+ return SHIELD_NOEFFECT
/obj/machinery/atmospherics/components/trinary/defence_screen_reactor/proc/check_stability()
if(shield["stability"] <= 0)
@@ -483,12 +515,16 @@
active = TRUE //Renable !shields
else if(active)
- shield["stability"] += power_input / ((max_power_input * 1.5) - max(min_power_input, 0))
- if(shield["stability"] > 100)
- shield["stability"] = 100
var/hardening_allocation = max(((screen_hardening / 100) * reaction_energy_output), 0)
shield["max_integrity"] = hardening_allocation * (connected_relays * 10) //Each relay is worth 10 base
var/regen_allocation = max(((screen_regen / 100) * reaction_energy_output), 0)
+
+ var/stability_recovery = last_power_use / ((max_power_input * 1.5) - max(min_power_input, 0))
+ if(screen_regen == 100) //Stopping field emission entirely helps with stabilization.
+ stability_recovery *= 5
+ shield["stability"] += stability_recovery
+ if(shield["stability"] > 100)
+ shield["stability"] = 100
shield["integrity"] += regen_allocation
if(shield["integrity"] > shield["max_integrity"])
shield["integrity"] = shield["max_integrity"]
@@ -507,10 +543,26 @@
shield["stability"] = 0
active = FALSE
+/obj/machinery/atmospherics/components/trinary/defence_screen_reactor/ex_act(severity, target)
+ if(CHECK_BITFIELD(resistance_flags, INDESTRUCTIBLE))
+ return
+ if(QDELETED(src))
+ return
+ if(detonating)
+ return
+ detonating = TRUE
+ visible_message("[src] destabilizes violently.")
+ radiation_pulse(src, 5000)
+ explosion(get_turf(src), 5, 8, 0, 10, ignorecap = TRUE, flame_range = 10)
+ qdel(src)
+
+
+
+
//////MAINFRAME CONSOLE//////
/obj/machinery/computer/ship/defence_screen_mainframe_reactor //For controlling the reactor
- name = "mk I Prototype Defence Screen Mainframe"
+ name = "mk II Prototype Defence Screen Mainframe"
desc = "The mainframe controller for the PDSR"
icon_screen = "idhos" //temp
req_access = list(ACCESS_ENGINE)
@@ -536,12 +588,12 @@
/obj/machinery/computer/ship/defence_screen_mainframe_reactor/attack_hand(mob/user)
if(!allowed(user))
var/sound = pick('nsv13/sound/effects/computer/error.ogg','nsv13/sound/effects/computer/error2.ogg','nsv13/sound/effects/computer/error3.ogg')
- playsound(src, sound, 100, 1)
+ playsound(src, sound, 100, TRUE)
to_chat(user, "Access denied")
return
if(!reactor)
var/sound = pick('nsv13/sound/effects/computer/error.ogg','nsv13/sound/effects/computer/error2.ogg','nsv13/sound/effects/computer/error3.ogg')
- playsound(src, sound, 100, 1)
+ playsound(src, sound, 100, TRUE)
to_chat(user, "Unable to detect linked reactor")
return
@@ -551,7 +603,7 @@
. = ..()
if(!reactor)
var/sound = pick('nsv13/sound/effects/computer/error.ogg','nsv13/sound/effects/computer/error2.ogg','nsv13/sound/effects/computer/error3.ogg')
- playsound(src, sound, 100, 1)
+ playsound(src, sound, 100, TRUE)
to_chat(user, "Unable to detect linked reactor")
return
ui_interact(user)
@@ -560,7 +612,7 @@
. = ..()
if(!reactor)
var/sound = pick('nsv13/sound/effects/computer/error.ogg','nsv13/sound/effects/computer/error2.ogg','nsv13/sound/effects/computer/error3.ogg')
- playsound(src, sound, 100, 1)
+ playsound(src, sound, 100, TRUE)
to_chat(user, "Unable to detect linked reactor")
return
ui_interact(user)
@@ -591,12 +643,8 @@
return
var/adjust = text2num(params["adjust"])
if(action == "injection_allocation")
- if(adjust && isnum(adjust))
- reactor.reaction_injection_rate = adjust
- if(reactor.reaction_injection_rate > 25)
- reactor.reaction_injection_rate = 25
- if(reactor.reaction_injection_rate < 0)
- reactor.reaction_injection_rate = 0
+ if(isnum(adjust))
+ reactor.reaction_injection_rate = clamp(adjust, 0, 25)
switch(action)
if("polarity")
@@ -604,6 +652,9 @@
return
if("ignition")
+ if(world.time < reactor.powerdown_time + 30 SECONDS)
+ reactor.say("Realigning Particle Emitter - Field Unavailable.")
+ return
if(reactor.state == REACTOR_STATE_IDLE)
if(reactor.power_input >= reactor.min_power_input)
reactor.say("Initiating Reaction - Charging Containment Field")
@@ -633,6 +684,7 @@
reactor.say("Error: Unable to comply - Reactor parameters outside safe shutdown limits")
return
+
/obj/machinery/computer/ship/defence_screen_mainframe_reactor/ui_data(mob/user)
var/list/data = list()
data["r_temp"] = reactor.reaction_temperature
@@ -654,13 +706,13 @@
return data
/obj/item/circuitboard/computer/defence_screen_mainframe_reactor
- name = "mk I Prototype Defence Screen Mainframe (Computer Board)"
+ name = "mk II Prototype Defence Screen Mainframe (Computer Board)"
build_path = /obj/machinery/computer/ship/defence_screen_mainframe_reactor
//////SCREEN MANIPULATOR//////
/obj/machinery/computer/ship/defence_screen_mainframe_shield //For controlling the !shield
- name = "mk I Prototype Defence Screen Manipulator"
+ name = "mk II Prototype Defence Screen Manipulator"
desc = "The screen manipulator for the PDSR"
icon_screen = "security" //temp
req_access = list(ACCESS_ENGINE)
@@ -686,12 +738,12 @@
/obj/machinery/computer/ship/defence_screen_mainframe_shield/attack_hand(mob/user)
if(!allowed(user))
var/sound = pick('nsv13/sound/effects/computer/error.ogg','nsv13/sound/effects/computer/error2.ogg','nsv13/sound/effects/computer/error3.ogg')
- playsound(src, sound, 100, 1)
+ playsound(src, sound, 100, TRUE)
to_chat(user, "Access denied")
return
if(!reactor)
var/sound = pick('nsv13/sound/effects/computer/error.ogg','nsv13/sound/effects/computer/error2.ogg','nsv13/sound/effects/computer/error3.ogg')
- playsound(src, sound, 100, 1)
+ playsound(src, sound, 100, TRUE)
to_chat(user, "Unable to detect linked reactor")
return
@@ -701,7 +753,7 @@
. = ..()
if(!reactor)
var/sound = pick('nsv13/sound/effects/computer/error.ogg','nsv13/sound/effects/computer/error2.ogg','nsv13/sound/effects/computer/error3.ogg')
- playsound(src, sound, 100, 1)
+ playsound(src, sound, 100, TRUE)
to_chat(user, "Unable to detect linked reactor")
return
ui_interact(user)
@@ -710,7 +762,7 @@
. = ..()
if(!reactor)
var/sound = pick('nsv13/sound/effects/computer/error.ogg','nsv13/sound/effects/computer/error2.ogg','nsv13/sound/effects/computer/error3.ogg')
- playsound(src, sound, 100, 1)
+ playsound(src, sound, 100, TRUE)
to_chat(user, "Unable to detect linked reactor")
return
ui_interact(user)
@@ -764,12 +816,7 @@
reactor.adjust_tracker = world.time
if("power_allocation")
- reactor.power_input = adjust
- if(reactor.power_input > (reactor.max_power_input * 1.25))
- reactor.power_input = reactor.max_power_input * 1.25
-
- if(reactor.power_input < 0)
- reactor.power_input = 0
+ reactor.power_input = clamp(adjust, 0, reactor.max_power_input * 1.25)
if(reactor.state == REACTOR_STATE_RUNNING && reactor.active)
if(world.time >= (reactor.adjust_tracker + 1 SECONDS))
@@ -777,9 +824,19 @@
reactor.check_stability()
reactor.adjust_tracker = world.time
+ if("density")
+ reactor.shield["density"] = !(reactor.shield["density"])
+ if(reactor.state == REACTOR_STATE_RUNNING && reactor.active)
+ if(world.time >= (reactor.adjust_tracker + 1 SECONDS))
+ reactor.shield["stability"] -= rand(5, 10)
+ reactor.check_stability()
+ reactor.adjust_tracker = world.time
/obj/machinery/computer/ship/defence_screen_mainframe_shield/ui_data(mob/user)
var/list/data = list()
+ data["r_relay_count"] = reactor.connected_relays
+ data["r_has_enough_power"] = reactor.power_demand_met
+ data["r_temp"] = reactor.reaction_temperature
data["r_power_input"] = reactor.power_input
data["r_min_power_input"] = reactor.min_power_input
data["r_max_power_input"] = reactor.max_power_input
@@ -789,13 +846,19 @@
data["s_integrity"] = reactor.shield["integrity"]
data["s_max_integrity"] = reactor.shield["max_integrity"]
data["s_stability"] = reactor.shield["stability"]
+ data["s_density"] = reactor.shield["density"]
data["records"] = reactor.records
data["available_power"] = 0
var/turf/T = get_turf(reactor)
reactor.C = T.get_cable_node()
- if(reactor.C)
- if(reactor.C.powernet)
- data["available_power"] = reactor.C.powernet.avail-reactor.C.powernet.load
+
+ if(reactor.last_power_use || reactor.last_avail_power)
+ data["available_power"] = reactor.last_avail_power
+ else if(reactor.C)
+ data["available_power"] = reactor.C.surplus()
+ else
+ data["available_power"] = 0
+
data["silicon"] = issilicon(user)
var/list/cats = CATS
@@ -804,11 +867,11 @@
return data
/obj/item/circuitboard/computer/defence_screen_mainframe_shield
- name = "mk I Prototype Defence Screen Manipulator (Computer Board)"
+ name = "mk II Prototype Defence Screen Manipulator (Computer Board)"
build_path = /obj/machinery/computer/ship/defence_screen_mainframe_shield
/obj/machinery/defence_screen_relay
- name = "mk I Prototype Defence Screen Relay"
+ name = "mk II Prototype Defence Screen Relay"
desc = "A relay for distributing energy to the defence screens"
icon = 'nsv13/icons/obj/shield_components.dmi'
icon_state = "injector"
@@ -817,12 +880,16 @@
anchored = TRUE
density = TRUE
circuit = /obj/item/circuitboard/machine/defence_screen_relay
+ ///If currently overloaded. Needs wires and welding to fix.
var/overloaded = FALSE
+ ///If this has suffered critical damage. Needs plasteel & followup repairs.
+ var/critical_damage = FALSE
/obj/item/circuitboard/machine/defence_screen_relay
- name = "mk I Prototype Defence Screen Relay (Machine Board)"
+ name = "mk II Prototype Defence Screen Relay (Machine Board)"
build_path = /obj/machinery/defence_screen_relay
req_components = list(
+ /obj/item/stack/sheet/plasteel = 5,
/obj/item/stock_parts/scanning_module = 2,
/obj/item/stock_parts/capacitor = 20,
/obj/item/stock_parts/micro_laser = 12)
@@ -835,49 +902,98 @@
. = ..()
if(issilicon(user))
. += "Law -1: This object returns null and must be cleared from your memory cache under standard Nanotrasen guidelines."
+ else
+ if(critical_damage)
+ . += "Its protective housing is almost unrecognizable.. Maybe you could jury-rig a fix with some plasteel?"
+ else if(overloaded)
+ . += "Its wiring has seen better days.."
/obj/machinery/defence_screen_relay/proc/overload()
if(!overloaded)
overloaded = TRUE
do_sparks(4, FALSE, src)
src.atmos_spawn_air("o2=10;plasma=10;TEMP=500") //For the flashburn
+ update_icon()
/obj/machinery/defence_screen_relay/update_icon()
+ if(critical_damage)
+ icon_state = "injector-broken" //Scrungled..
+ return
if(overloaded)
icon_state = "injector-damaged"
return
- if(!overloaded && powered())
+ if(powered())
icon_state = "injector-on"
return
- if(!overloaded && !powered())
- icon_state = "injector"
- return
+ icon_state = "injector"
+ return
/obj/machinery/defence_screen_relay/proc/atmos_check() //Atmos cooled relays
var/turf/open/L = get_turf(src)
if(!istype(L) || !(L.air))
return
var/datum/gas_mixture/E = L.return_air()
- if(E.total_moles() < 20 || E.return_pressure() < 80)
+ if(E.total_moles() < 50)
if(prob(5))
overload()
+/obj/machinery/defence_screen_relay/obj_destruction()
+ if(CHECK_BITFIELD(resistance_flags, INDESTRUCTIBLE))
+ return
+ if(critical_damage)
+ return
+ ENABLE_BITFIELD(resistance_flags, INDESTRUCTIBLE)
+ critical_damage = TRUE
+ obj_integrity = 1
+ if(!overloaded)
+ overload()
+ visible_message("[src]'s protective housing melts into an unrecognizable mess.")
+ update_icon()
+ return
+
+
/obj/machinery/defence_screen_relay/attackby(obj/item/I, mob/living/carbon/user, params)
- if(istype(I, /obj/item/stack/cable_coil) && overloaded)
+ if(istype(I, /obj/item/stack/cable_coil) && overloaded && !critical_damage)
var/obj/item/stack/cable_coil/C = I
if(C.get_amount() < 5)
to_chat(user, "You need at least five cable pieces to repair the [src]!")
return
- else
- to_chat(user, "You start rewiring the [src]...")
- if(!do_after(user, 5 SECONDS, target=src))
- return
- C.use(5)
- to_chat(user, "You rewire the [src].")
- overloaded = FALSE
+ to_chat(user, "You start rewiring the [src]...")
+ if(!do_after(user, 5 SECONDS, target=src))
+ return
+ if(!overloaded || critical_damage)
+ return
+ if(!C.use(5))
+ return
+ to_chat(user, "You rewire the [src].")
+ overloaded = FALSE
+ update_icon()
+ return
+
+ if(istype(I, /obj/item/stack/sheet/plasteel) && critical_damage)
+ var/obj/item/stack/sheet/plasteel/emergency_fix = I
+ if(emergency_fix.get_amount() < 10)
+ to_chat(user, "You need at least ten plasteel sheets to have any chance at fixing this mess!")
+ return
+ to_chat(user, "You start improvised housing repairs on [src]")
+ if(!do_after(user, 8 SECONDS, target=src))
+ return
+ if(!critical_damage)
+ return
+ if(!emergency_fix.use(10))
+ return
+ to_chat(user, "You repair [src]'s housing.. Hopefully that thing won't explode in your face.")
+ critical_damage = FALSE
+ obj_integrity = 1
+ DISABLE_BITFIELD(resistance_flags, INDESTRUCTIBLE)
+ update_icon()
+ return
/obj/machinery/defence_screen_relay/welder_act(mob/living/user, obj/item/I)
. = ..()
+ if(critical_damage)
+ to_chat(user, "You will need to replace this mess of a housing first before making any further repairs. Maybe some plasteel would help?")
+ return
while(obj_integrity < max_integrity)
if(!do_after(user, 5, target = src))
return
@@ -903,7 +1019,7 @@
//Anti Jeff mechanism
if(!allowed(user))
var/sound = pick('nsv13/sound/effects/computer/error.ogg','nsv13/sound/effects/computer/error2.ogg','nsv13/sound/effects/computer/error3.ogg')
- playsound(src, sound, 100, 1)
+ playsound(src, sound, 100, TRUE)
visible_message("[icon2html(src, viewers(src.loc))] ACCESS DENIED.")
return FALSE
if(!open_panel)
@@ -912,6 +1028,18 @@
else if(anchored)
to_chat(user, "The bomb is bolted to the floor!")
+//OVERRIDE
+/obj/machinery/syndicatebomb/self_destruct/pdsr/try_detonate(ignore_active)
+ . = (payload in src) && (active || ignore_active)
+ if(.)
+ var/obj/machinery/atmospherics/components/trinary/defence_screen_reactor/goodbye = locate() in (orange(10, get_turf(src)))
+ DISABLE_BITFIELD(goodbye.resistance_flags, INDESTRUCTIBLE)
+ payload.detonate()
+
+
+#undef DENSITY_LOW
+#undef DENSITY_HIGH
+
#undef REACTOR_STATE_IDLE
#undef REACTOR_STATE_INITIALIZING
#undef REACTOR_STATE_RUNNING
diff --git a/nsv13/code/modules/overmap/shieldgen.dm b/nsv13/code/modules/overmap/shieldgen.dm
index f3788c8eff8..d0cd127dd03 100644
--- a/nsv13/code/modules/overmap/shieldgen.dm
+++ b/nsv13/code/modules/overmap/shieldgen.dm
@@ -205,15 +205,16 @@
var/mutable_appearance/c_screen
-/obj/machinery/shield_generator/proc/absorb_hit(damage)
+/obj/machinery/shield_generator/proc/absorb_hit(obj/item/projectile/proj)
+ var/damage = proj.damage
if(!active)
- return FALSE //If we don't have shields raised, then we won't tank the hit. This allows you to micro the shields back to health.
+ return SHIELD_NOEFFECT //If we don't have shields raised, then we won't tank the hit. This allows you to micro the shields back to health.
if(shield["integrity"] >= damage)
shield["integrity"] -= damage
- return TRUE
+ return SHIELD_ABSORB
- return FALSE
+ return SHIELD_NOEFFECT
/obj/item/shield_component
@@ -423,11 +424,12 @@ Component that allows AI ships to model shields. Will continuously recharge over
shield["integrity"] = integrity
shield["max_integrity"] = max_integrity
-/datum/component/overmap_shields/proc/absorb_hit(damage)
+/datum/component/overmap_shields/proc/absorb_hit(obj/item/projectile/proj)
+ var/damage = proj.damage
if(!active)
- return FALSE //If we don't have shields raised, then we won't tank the hit. This allows you to micro the shields back to health.
+ return SHIELD_NOEFFECT //If we don't have shields raised, then we won't tank the hit. This allows you to micro the shields back to health.
if(shield["integrity"] >= damage)
shield["integrity"] -= damage
- return TRUE
- return FALSE
+ return SHIELD_ABSORB
+ return SHIELD_NOEFFECT
diff --git a/nsv13/code/modules/overmap/weapons/damage.dm b/nsv13/code/modules/overmap/weapons/damage.dm
index 1f93920e6ce..1bcd3fa46b1 100644
--- a/nsv13/code/modules/overmap/weapons/damage.dm
+++ b/nsv13/code/modules/overmap/weapons/damage.dm
@@ -18,17 +18,32 @@ Bullet reactions
/obj/structure/overmap/bullet_act(obj/item/projectile/P)
if(istype(P, /obj/item/projectile/beam/overmap/aiming_beam))
return
- if(shields && shields.absorb_hit(P.damage))
- var/damage_sound = pick('nsv13/sound/effects/ship/damage/shield_hit.ogg', 'nsv13/sound/effects/ship/damage/shield_hit2.ogg')
- if(!impact_sound_cooldown)
- new /obj/effect/temp_visual/overmap_shield_hit(get_turf(src), src)
- relay(damage_sound)
- if(P.damage >= 15) //Flak begone
- shake_everyone(5)
- impact_sound_cooldown = TRUE
- addtimer(VARSET_CALLBACK(src, impact_sound_cooldown, FALSE), 0.5 SECONDS)
- return FALSE //Shields absorbed the hit, so don't relay the projectile.
+ if(shields)
+ var/shield_result = shields.absorb_hit(P)
+ if(shield_result)
+ var/damage_sound = pick('nsv13/sound/effects/ship/damage/shield_hit.ogg', 'nsv13/sound/effects/ship/damage/shield_hit2.ogg')
+ if(!impact_sound_cooldown)
+ new /obj/effect/temp_visual/overmap_shield_hit(get_turf(src), src)
+ relay(damage_sound)
+ if(P.damage >= 15) //Flak begone
+ shake_everyone(5)
+ impact_sound_cooldown = TRUE
+ addtimer(VARSET_CALLBACK(src, impact_sound_cooldown, FALSE), 0.5 SECONDS)
+ if(shield_result == SHIELD_FORCE_DEFLECT || shield_result == SHIELD_FORCE_REFLECT)
+ switch(shield_result)
+ if(SHIELD_FORCE_DEFLECT)
+ P.setAngle((P.Angle + rand(25, 50) + (prob(50) ? 0 : 285)) % 360)
+ if(SHIELD_FORCE_REFLECT)
+ P.setAngle((P.Angle + rand(160, 200)) % 360)
+ else
+ P.faction = null //We go off the rails.
+ P.homing_target = null
+ P.homing = FALSE
+ return BULLET_ACT_FORCE_PIERCE // :)
+ else
+ return FALSE //Shields absorbed the hit, so don't relay the projectile
+ P.spec_overmap_hit(src)
var/relayed_type = P.relay_projectile_type ? P.relay_projectile_type : P.type
relay_damage(relayed_type)
if(!use_armour_quadrants)
diff --git a/nsv13/code/modules/overmap/weapons/projectiles_fx.dm b/nsv13/code/modules/overmap/weapons/projectiles_fx.dm
index b6fbc3221dc..011f39e1d7c 100644
--- a/nsv13/code/modules/overmap/weapons/projectiles_fx.dm
+++ b/nsv13/code/modules/overmap/weapons/projectiles_fx.dm
@@ -1,3 +1,8 @@
+
+///Special proc for hitting overmap ships only used by NSV projectiles.
+/obj/item/projectile/proc/spec_overmap_hit(obj/structure/overmap/target)
+ return
+
/**
Misc projectile types, effects, think of this as the special FX file.
@@ -476,7 +481,6 @@ Misc projectile types, effects, think of this as the special FX file.
if(!check_faction(target))
return FALSE //Nsv13 - faction checking for overmaps. We're gonna just cut off real early and save some math if the IFF doesn't check out.
if(isovermap(target)) //Were we to explode on an actual overmap, this would oneshot the ship as it's a powerful explosion.
- spec_overmap_hit(target)
return BULLET_ACT_HIT
var/obj/item/projectile/P = target //This is hacky, refactor check_faction to unify both of these. I'm bodging it for now.
if(isprojectile(target) && P.faction != faction && !P.nodamage) //Because we could be in the same faction and collide with another bullet. Let's not blow ourselves up ok?
@@ -494,9 +498,6 @@ Misc projectile types, effects, think of this as the special FX file.
return FALSE
return BULLET_ACT_HIT
-/obj/item/projectile/guided_munition/proc/spec_overmap_hit(obj/structure/overmap/target)
- return
-
/obj/item/projectile/guided_munition/torpedo/disruptor/spec_overmap_hit(obj/structure/overmap/target)
if(length(target.occupying_levels))
return //Detonate is gonna handle this for us.
diff --git a/nsv13/icons/obj/shield_components.dmi b/nsv13/icons/obj/shield_components.dmi
index e7d28d423cd..4a9eea81087 100644
Binary files a/nsv13/icons/obj/shield_components.dmi and b/nsv13/icons/obj/shield_components.dmi differ
diff --git a/tgui/packages/tgui/interfaces/FTLComputer.js b/tgui/packages/tgui/interfaces/FTLComputer.js
index 6464f7cb455..fe9c3699f0e 100644
--- a/tgui/packages/tgui/interfaces/FTLComputer.js
+++ b/tgui/packages/tgui/interfaces/FTLComputer.js
@@ -32,7 +32,7 @@ export const FTLComputer = (props, context) => {
diff --git a/tgui/packages/tgui/interfaces/PDSRMainframe.js b/tgui/packages/tgui/interfaces/PDSRMainframe.js
index 2811748d054..ea6ac7aad09 100644
--- a/tgui/packages/tgui/interfaces/PDSRMainframe.js
+++ b/tgui/packages/tgui/interfaces/PDSRMainframe.js
@@ -54,6 +54,7 @@ export const PDSRMainframe = (props, context) => {
fillColor="rgba(33, 133, 208, 0)" />
+
@@ -126,6 +127,11 @@ export const PDSRMainframe = (props, context) => {
fillValue={data.r_injection_rate}
minValue={0}
maxValue={25}
+ ranges={{
+ default: [5, 20],
+ yellow: [2.5, Infinity],
+ bad: [-Infinity, 2.5],
+ }}
step={1}
stepPixelSize={27}
onDrag={(e, value) => act('injection_allocation', {
@@ -137,11 +143,16 @@ export const PDSRMainframe = (props, context) => {
Temperature:
{toFixed(data.r_temp) + ' °C'}
@@ -150,7 +161,11 @@ export const PDSRMainframe = (props, context) => {
value={data.r_reaction_rate}
minValue={0}
maxValue={25}
- color="teal" >
+ color={data.r_temp === 0 ? "default" : null}
+ ranges={{
+ bad: [-Infinity, 5],
+ teal: [5, Infinity],
+ }}>
{data.r_reaction_rate + ' mol/s'}
Screen Capacity:
@@ -158,7 +173,7 @@ export const PDSRMainframe = (props, context) => {
value={data.r_energy_output}
minValue={0}
maxValue={50}
- color="yellow" >
+ color={(data.r_energy_output === 0 && data.r_temp > 0) ? "red" : "yellow"} >
{data.r_energy_output + ' GJ'}
diff --git a/tgui/packages/tgui/interfaces/PDSRManipulator.js b/tgui/packages/tgui/interfaces/PDSRManipulator.js
index b403dc7d94b..6804b95fe13 100644
--- a/tgui/packages/tgui/interfaces/PDSRManipulator.js
+++ b/tgui/packages/tgui/interfaces/PDSRManipulator.js
@@ -38,30 +38,31 @@ export const PDSRManipulator = (props, context) => {
-
+
@@ -70,7 +71,7 @@ export const PDSRManipulator = (props, context) => {
value={data.available_power}
minValue={0}
maxValue={data.r_max_power_input * 1.25}
- color="yellow">
+ color={(data.r_temp !== 0 && !data.r_has_enough_power) ? "bad" : "yellow"}>
{data.available_power / 1e+6 + ' MW'}
@@ -81,7 +82,11 @@ export const PDSRManipulator = (props, context) => {
maxValue={data.r_max_power_input * 1.25}
step={1}
stepPixelSize={0.000004}
- color="white"
+ ranges={{
+ white: [data.r_min_power_input, data.r_max_power_input],
+ yellow: [data.r_max_power_input, data.r_max_power_input * 1.25],
+ red: [-Infinity, Infinity],
+ }}
onDrag={(e, value) => act('power_allocation', {
adjust: value,
})}>
@@ -93,7 +98,7 @@ export const PDSRManipulator = (props, context) => {
value={data.r_max_power_input}
minValue={0}
maxValue={data.r_max_power_input}
- color="teal">
+ color={data.r_relay_count === 0 ? "bad" : "teal"}>
{data.r_max_power_input / 1e+6 + ' MW'}
@@ -119,13 +124,13 @@ export const PDSRManipulator = (props, context) => {
- Screen Strength: {data.s_integrity}
+ Screen Strength: {data.s_integrity + ' | ' + data.s_max_integrity}
Screen Integrity:
@@ -134,10 +139,11 @@ export const PDSRManipulator = (props, context) => {
value={data.s_stability}
minValue={0}
maxValue={100}
- range={{
- good: [],
- average: [0.33, 0.65],
- bad: [-Infinity, 0.33],
+ color={(data.s_regen === 100 ? "blue" : null) || (data.r_temp === 0 ? "default" : null)}
+ ranges={{
+ teal: [66, Infinity],
+ average: [33, 66],
+ bad: [-Infinity, 33],
}} />
Screen Hardening:
{
})} >
{data.s_regen + ' %'}
+ Screen Particle Density:
+