diff --git a/aurorastation.dme b/aurorastation.dme
index 101fb30d9ac..5c89d677e76 100644
--- a/aurorastation.dme
+++ b/aurorastation.dme
@@ -2636,10 +2636,10 @@
#include "code\modules\shareddream\dream_entry.dm"
#include "code\modules\shieldgen\emergency_shield.dm"
#include "code\modules\shieldgen\energy_field.dm"
-#include "code\modules\shieldgen\sheldwallgen.dm"
#include "code\modules\shieldgen\shield_capacitor.dm"
#include "code\modules\shieldgen\shield_gen.dm"
#include "code\modules\shieldgen\shield_gen_external.dm"
+#include "code\modules\shieldgen\shieldwallgen.dm"
#include "code\modules\shuttles\antagonist.dm"
#include "code\modules\shuttles\departmental.dm"
#include "code\modules\shuttles\escape_pods.dm"
diff --git a/code/modules/power/singularity/singularity.dm b/code/modules/power/singularity/singularity.dm
index a373108aacd..72d4eaab405 100644
--- a/code/modules/power/singularity/singularity.dm
+++ b/code/modules/power/singularity/singularity.dm
@@ -410,7 +410,7 @@
else if (locate(/obj/machinery/shieldwallgen) in T)
var/obj/machinery/shieldwallgen/S = locate(/obj/machinery/shieldwallgen) in T
- if (S && S.active)
+ if (S?.power_state)
return 0
return 1
diff --git a/code/modules/shieldgen/sheldwallgen.dm b/code/modules/shieldgen/sheldwallgen.dm
deleted file mode 100644
index 8ca6ae07467..00000000000
--- a/code/modules/shieldgen/sheldwallgen.dm
+++ /dev/null
@@ -1,325 +0,0 @@
-////FIELD GEN START //shameless copypasta from fieldgen, powersink, and grille
-/obj/machinery/shieldwallgen
- name = "Shield Generator"
- desc = "A shield generator."
- icon = 'icons/obj/stationobjs.dmi'
- icon_state = "Shield_Gen"
- anchored = 0
- density = 1
- req_access = list(access_engine_equip)
- var/active = 0
- var/power = 0
- var/state = 0
- var/steps = 0
- var/last_check = 0
- var/check_delay = 10
- var/recalc = 0
- var/locked = 1
- var/destroyed = 0
- var/directwired = 1
-// var/maxshieldload = 200
- var/obj/structure/cable/attached // the attached cable
- var/storedpower = 0
- flags = CONDUCT
- //There have to be at least two posts, so these are effectively doubled
- var/power_draw = 30000 //30 kW. How much power is drawn from powernet. Increase this to allow the generator to sustain longer shields, at the cost of more power draw.
- var/max_stored_power = 50000 //50 kW
- use_power = 0 //Draws directly from power net. Does not use APC power.
-
-/obj/machinery/shieldwallgen/attack_hand(mob/user as mob)
- if(state != 1)
- to_chat(user, "The shield generator needs to be firmly secured to the floor first.")
- return 1
- if(src.locked && !istype(user, /mob/living/silicon))
- to_chat(user, "The controls are locked!")
- return 1
- if(power != 1)
- to_chat(user, "The shield generator needs to be powered by wire underneath.")
- return 1
-
- if(src.active >= 1)
- src.active = 0
- icon_state = "Shield_Gen"
-
- user.visible_message("[user] turned the shield generator off.", \
- "You turn off the shield generator.", \
- "You hear heavy droning fade out.")
- for(var/dir in list(1,2,4,8)) src.cleanup(dir)
- else
- src.active = 1
- icon_state = "Shield_Gen +a"
- user.visible_message("[user] turned the shield generator on.", \
- "You turn on the shield generator.", \
- "You hear heavy droning.")
- src.add_fingerprint(user)
-
-/obj/machinery/shieldwallgen/proc/power()
- if(!anchored)
- power = 0
- return 0
- var/turf/T = src.loc
- if (!istype(T))
- power = 0
- return 0
-
- var/obj/structure/cable/C = T.get_cable_node()
- var/datum/powernet/PN
- if(C) PN = C.powernet // find the powernet of the connected cable
-
- if(!PN)
- power = 0
- return 0
-
- var/shieldload = between(500, max_stored_power - storedpower, power_draw) //what we try to draw
- shieldload = PN.draw_power(shieldload) //what we actually get
- storedpower += shieldload
-
- //If we're still in the red, then there must not be enough available power to cover our load.
- if(storedpower <= 0)
- power = 0
- return 0
-
- power = 1 // IVE GOT THE POWER!
- return 1
-
-/obj/machinery/shieldwallgen/machinery_process()
- power()
- if(power)
- storedpower -= 2500 //the generator post itself uses some power
-
- if(storedpower >= max_stored_power)
- storedpower = max_stored_power
- if(storedpower <= 0)
- storedpower = 0
-// if(shieldload >= maxshieldload) //there was a loop caused by specifics of process(), so this was needed.
-// shieldload = maxshieldload
-
- if(src.active == 1)
- if(!src.state == 1)
- src.active = 0
- return
- addtimer(CALLBACK(src, .proc/setup_field, 1), 1)
- addtimer(CALLBACK(src, .proc/setup_field, 2), 2)
- addtimer(CALLBACK(src, .proc/setup_field, 3), 4)
- addtimer(CALLBACK(src, .proc/setup_field, 4), 8)
- src.active = 2
- if(src.active >= 1)
- if(src.power == 0)
- src.visible_message("The [src.name] shuts down due to lack of power!", \
- "You hear heavy droning fade out")
- icon_state = "Shield_Gen"
- src.active = 0
- for(var/dir in list(1,2,4,8))
- cleanup(dir)
-
-/obj/machinery/shieldwallgen/proc/setup_field(var/NSEW = 0)
- var/turf/T = src.loc
- var/turf/T2 = src.loc
- var/obj/machinery/shieldwallgen/G
- var/steps = 0
- var/oNSEW = 0
-
- if(!NSEW)//Make sure its ran right
- return
-
- if(NSEW == 1)
- oNSEW = 2
- else if(NSEW == 2)
- oNSEW = 1
- else if(NSEW == 4)
- oNSEW = 8
- else if(NSEW == 8)
- oNSEW = 4
-
- for(var/dist = 0, dist <= 9, dist += 1) // checks out to 8 tiles away for another generator
- T = get_step(T2, NSEW)
- T2 = T
- steps += 1
- if(locate(/obj/machinery/shieldwallgen) in T)
- G = (locate(/obj/machinery/shieldwallgen) in T)
- steps -= 1
- if(!G.active)
- return
- G.cleanup(oNSEW)
- break
-
- if(isnull(G))
- return
-
- T2 = src.loc
-
- for(var/dist = 0, dist < steps, dist += 1) // creates each field tile
- var/field_dir = get_dir(T2,get_step(T2, NSEW))
- T = get_step(T2, NSEW)
- T2 = T
- var/obj/shieldwall/CF = new/obj/shieldwall/(T, src, G) //(ref to this gen, ref to connected gen)
- CF.set_dir(field_dir)
-
-
-/obj/machinery/shieldwallgen/attackby(obj/item/W, mob/user)
- if(W.iswrench())
- if(active)
- to_chat(user, "Turn off the field generator first.")
- return
-
- else if(state == 0)
- state = 1
- playsound(src.loc, W.usesound, 75, 1)
- to_chat(user, "You secure the external reinforcing bolts to the floor.")
- src.anchored = 1
- return
-
- else if(state == 1)
- state = 0
- playsound(src.loc, W.usesound, 75, 1)
- to_chat(user, "You undo the external reinforcing bolts.")
- src.anchored = 0
- return
-
- if(istype(W, /obj/item/card/id)||istype(W, /obj/item/device/pda))
- if (src.allowed(user))
- src.locked = !src.locked
- to_chat(user, "Controls are now [src.locked ? "locked." : "unlocked."]")
- else
- to_chat(user, "Access denied.")
-
- else
- src.add_fingerprint(user)
- visible_message("The [src.name] has been hit with \the [W.name] by [user.name]!")
-
-/obj/machinery/shieldwallgen/proc/cleanup(var/NSEW)
- var/obj/shieldwall/F
- var/obj/machinery/shieldwallgen/G
- var/turf/T = src.loc
- var/turf/T2 = src.loc
-
- for(var/dist = 0, dist <= 9, dist += 1) // checks out to 8 tiles away for fields
- T = get_step(T2, NSEW)
- T2 = T
- if(locate(/obj/shieldwall) in T)
- F = (locate(/obj/shieldwall) in T)
- qdel(F)
-
- if(locate(/obj/machinery/shieldwallgen) in T)
- G = (locate(/obj/machinery/shieldwallgen) in T)
- if(!G.active)
- break
-
-/obj/machinery/shieldwallgen/Destroy()
- src.cleanup(1)
- src.cleanup(2)
- src.cleanup(4)
- src.cleanup(8)
- return ..()
-
-/obj/machinery/shieldwallgen/bullet_act(var/obj/item/projectile/Proj)
- storedpower -= 400 * Proj.get_structure_damage()
- ..()
- return
-
-
-//////////////Containment Field START
-/obj/shieldwall
- name = "shield"
- desc = "An energy shield."
- icon = 'icons/effects/effects.dmi'
- icon_state = "shieldwall"
- anchored = 1
- density = 1
- unacidable = 1
- light_range = 3
- light_color = LIGHT_COLOR_BLUE
- var/needs_power = 0
- var/active = 1
-// var/power = 10
- var/delay = 5
- var/last_active
- var/mob/U
- var/obj/machinery/shieldwallgen/gen_primary
- var/obj/machinery/shieldwallgen/gen_secondary
- var/power_usage = 2500 //how much power it takes to sustain the shield
- var/generate_power_usage = 7500 //how much power it takes to start up the shield
-
-/obj/shieldwall/Initialize(mapload, var/obj/machinery/shieldwallgen/A, var/obj/machinery/shieldwallgen/B)
- . = ..()
- update_nearby_tiles()
- gen_primary = A
- gen_secondary = B
- if(A && B && A.active && B.active)
- needs_power = 1
- A.storedpower -= generate_power_usage/2
- B.storedpower -= generate_power_usage/2
- START_PROCESSING(SSprocessing, src)
- else
- qdel(src) //need at least two generator posts
-
-/obj/shieldwall/Destroy()
- update_nearby_tiles()
- STOP_PROCESSING(SSprocessing, src)
- return ..()
-
-/obj/shieldwall/attack_hand(mob/user as mob)
- return
-
-/obj/shieldwall/process()
- if(needs_power)
- if(!gen_primary || !gen_secondary)
- qdel(src)
- return
-
- if(!(gen_primary.active) || !(gen_secondary.active))
- qdel(src)
- return
-
- gen_primary.storedpower -= power_usage/2
- gen_secondary.storedpower -= power_usage/2
-
-/obj/shieldwall/bullet_act(var/obj/item/projectile/Proj)
- if(needs_power)
- var/obj/machinery/shieldwallgen/G
- if(prob(50))
- G = gen_primary
- else
- G = gen_secondary
- G.storedpower -= 400 * Proj.get_structure_damage()
- ..()
- return
-
-
-/obj/shieldwall/ex_act(severity)
- if(needs_power)
- var/obj/machinery/shieldwallgen/G
- switch(severity)
- if(1.0) //big boom
- if(prob(50))
- G = gen_primary
- else
- G = gen_secondary
- G.storedpower -= 120000
-
- if(2.0) //medium boom
- if(prob(50))
- G = gen_primary
- else
- G = gen_secondary
- G.storedpower -= 30000
-
- if(3.0) //lil boom
- if(prob(50))
- G = gen_primary
- else
- G = gen_secondary
- G.storedpower -= 12000
- return
-
-
-/obj/shieldwall/CanPass(atom/movable/mover, turf/target, height=0, air_group=0)
- if(air_group || (height==0)) return 1
-
- if(istype(mover) && mover.checkpass(PASSGLASS))
- return prob(20)
- else
- if (istype(mover, /obj/item/projectile))
- return prob(10)
- else
- return !src.density
diff --git a/code/modules/shieldgen/shieldwallgen.dm b/code/modules/shieldgen/shieldwallgen.dm
new file mode 100644
index 00000000000..37255968283
--- /dev/null
+++ b/code/modules/shieldgen/shieldwallgen.dm
@@ -0,0 +1,304 @@
+#define POWER_INACTIVE 0
+#define POWER_STARTING 1
+#define POWER_ACTIVE 2
+
+/obj/machinery/shieldwallgen
+ name = "shield generator"
+ desc = "A portable shield generator, capable of casting a shield to another powered generator in range."
+ icon = 'icons/obj/stationobjs.dmi'
+ icon_state = "Shield_Gen"
+ anchored = FALSE
+ density = TRUE
+ req_access = list(access_engine_equip)
+
+ var/power_state = FALSE
+ var/is_powered = FALSE
+ var/wrenched = FALSE
+ var/steps = 0
+ var/last_check = 0
+ var/check_delay = 10
+ var/locked = TRUE
+ var/storedpower = 0
+ flags = CONDUCT
+
+ //There have to be at least two posts, so these are effectively doubled
+ var/power_draw = 30000 //30 kW. How much power is drawn from powernet. Increase this to allow the generator to sustain longer shields, at the cost of more power draw.
+ var/max_stored_power = 50000 //50 kW
+ use_power = FALSE //Draws directly from power net. Does not use APC power.
+
+/obj/machinery/shieldwallgen/update_icon()
+ if(power_state >= POWER_STARTING)
+ icon_state = "Shield_Gen +a"
+ else
+ icon_state = "Shield_Gen"
+
+/obj/machinery/shieldwallgen/attack_hand(mob/user)
+ if(!wrenched)
+ to_chat(user, SPAN_WARNING("The shield generator needs to be firmly secured to the floor first."))
+ return TRUE
+ if(locked && !issilicon(user))
+ to_chat(user, SPAN_WARNING("The controls are locked!"))
+ return TRUE
+ if(!is_powered)
+ to_chat(user, SPAN_WARNING("The shield generator needs to be powered by wire underneath."))
+ return TRUE
+
+ if(power_state >= POWER_STARTING)
+ power_state = POWER_INACTIVE
+ user.visible_message("[user] turns \the [src] off.", SPAN_NOTICE("You turn off \the [src]."), SPAN_NOTICE("You hear a heavy droning fade out."))
+ alldir_cleanup()
+ else
+ power_state = POWER_STARTING
+ user.visible_message("[user] turns \the [src] on.", SPAN_NOTICE("You turn on \the [src]."), SPAN_NOTICE("You hear a heavy droning start up."))
+ update_icon()
+ add_fingerprint(user)
+
+/obj/machinery/shieldwallgen/proc/power()
+ if(!anchored)
+ is_powered = FALSE
+ return FALSE
+ var/turf/T = loc
+ if(!istype(T))
+ is_powered = FALSE
+ return FALSE
+
+ var/obj/structure/cable/C = T.get_cable_node()
+ var/datum/powernet/PN
+ if(C)
+ PN = C.powernet // find the powernet of the connected cable
+
+ if(!PN)
+ is_powered = FALSE
+ return FALSE
+
+ var/shieldload = between(500, max_stored_power - storedpower, power_draw) //what we try to draw
+ shieldload = PN.draw_power(shieldload) //what we actually get
+ storedpower += shieldload
+
+ //If we're still in the red, then there must not be enough available power to cover our load.
+ if(storedpower <= 0)
+ is_powered = FALSE
+ return FALSE
+
+ is_powered = TRUE // IVE GOT THE POWER!
+ return TRUE
+
+/obj/machinery/shieldwallgen/machinery_process()
+ power()
+ if(is_powered)
+ storedpower -= 2500
+
+ storedpower = clamp(storedpower, 0, max_stored_power)
+
+ if(power_state == POWER_STARTING)
+ if(!wrenched)
+ power_state = POWER_INACTIVE
+ return
+ addtimer(CALLBACK(src, .proc/setup_field, 1), 1)
+ addtimer(CALLBACK(src, .proc/setup_field, 2), 2)
+ addtimer(CALLBACK(src, .proc/setup_field, 3), 4)
+ addtimer(CALLBACK(src, .proc/setup_field, 4), 8)
+ power_state = POWER_ACTIVE
+
+ if(power_state >= POWER_STARTING)
+ if(!is_powered)
+ visible_message(SPAN_WARNING("\The [src] shuts down due to a lack of power."), SPAN_NOTICE("You hear a heavy droning fade out."))
+ power_state = POWER_INACTIVE
+ update_icon()
+ alldir_cleanup()
+
+/obj/machinery/shieldwallgen/proc/setup_field(var/NSEW)
+ var/turf/T = loc
+ var/turf/T2 = loc
+ var/obj/machinery/shieldwallgen/G
+ var/steps = 0
+ var/oNSEW = 0
+
+ if(!NSEW)//Make sure its ran right
+ return
+
+ oNSEW = reverse_direction(NSEW)
+
+ for(var/dist = 0, dist <= 9, dist++) // checks out to 8 tiles away for another generator
+ T = get_step(T2, NSEW)
+ T2 = T
+ steps += 1
+ if(locate(/obj/machinery/shieldwallgen) in T)
+ G = (locate(/obj/machinery/shieldwallgen) in T)
+ steps -= 1
+ if(!G.power_state)
+ return
+ G.cleanup(oNSEW)
+ break
+
+ if(isnull(G))
+ return
+
+ T2 = loc
+
+ for(var/dist = 0, dist < steps, dist++) // creates each field tile
+ var/field_dir = get_dir(T2, get_step(T2, NSEW))
+ T = get_step(T2, NSEW)
+ T2 = T
+ var/obj/shieldwall/CF = new /obj/shieldwall/(T, src, G) //(ref to this gen, ref to connected gen)
+ CF.set_dir(field_dir)
+
+/obj/machinery/shieldwallgen/attackby(obj/item/W, mob/user)
+ if(W.iswrench())
+ if(power_state)
+ to_chat(user, SPAN_WARNING("You cannot unsecure \the [src] while it's active."))
+ return
+
+ wrenched = !wrenched
+ anchored = wrenched
+ playsound(loc, W.usesound, 75, TRUE)
+ add_fingerprint(user)
+ var/others_msg = wrenched ? "[user] secures the external reinforcing bolts to the floor." : "[user] unsecures the external reinforcing bolts."
+ var/self_msg = wrenched ? "You secure the external reinforcing bolts to the floor." : "You unsecure the external reinforcing bolts."
+ user.visible_message(others_msg, SPAN_NOTICE(self_msg), SPAN_NOTICE("You hear a ratcheting noise."))
+ return
+
+ if(istype(W, /obj/item/card/id) || istype(W, /obj/item/device/pda))
+ add_fingerprint(user)
+ if(allowed(user))
+ locked = !locked
+ var/msg = "The controls are now [locked ? "locked" : "unlocked"]."
+ to_chat(user, SPAN_NOTICE(msg))
+ else
+ to_chat(user, SPAN_WARNING("Access denied."))
+ return
+
+ return ..()
+
+/obj/machinery/shieldwallgen/proc/alldir_cleanup()
+ for(var/dir in list(NORTH, SOUTH, EAST, WEST))
+ cleanup(dir)
+
+/obj/machinery/shieldwallgen/proc/cleanup(var/NSEW)
+ var/obj/shieldwall/F
+ var/obj/machinery/shieldwallgen/G
+ var/turf/T = loc
+ var/turf/T2 = loc
+
+ for(var/dist = 0, dist <= 9, dist++) // checks out to 8 tiles away for fields
+ T = get_step(T2, NSEW)
+ T2 = T
+ if(locate(/obj/shieldwall) in T)
+ F = (locate(/obj/shieldwall) in T)
+ qdel(F)
+
+ if(locate(/obj/machinery/shieldwallgen) in T)
+ G = (locate(/obj/machinery/shieldwallgen) in T)
+ if(!G.power_state)
+ break
+
+/obj/machinery/shieldwallgen/Destroy()
+ alldir_cleanup()
+ return ..()
+
+/obj/machinery/shieldwallgen/bullet_act(var/obj/item/projectile/Proj)
+ storedpower -= 400 * Proj.get_structure_damage()
+ if(power_state >= POWER_STARTING)
+ visible_message(SPAN_WARNING("\The [src]'s shielding sparks as \the [Proj] hits it!"))
+ return ..()
+
+/obj/shieldwall
+ name = "energy shield"
+ desc = "An energy shield."
+ icon = 'icons/effects/effects.dmi'
+ icon_state = "shieldwall"
+ anchored = TRUE
+ density = TRUE
+ unacidable = TRUE
+ light_range = 3
+ light_color = LIGHT_COLOR_BLUE
+ var/needs_power = FALSE
+ var/power_state = POWER_STARTING
+ var/delay = 5
+ var/last_active
+ var/mob/U
+ var/obj/machinery/shieldwallgen/gen_primary
+ var/obj/machinery/shieldwallgen/gen_secondary
+ var/power_usage = 2500 //how much power it takes to sustain the shield
+ var/generate_power_usage = 7500 //how much power it takes to start up the shield
+
+/obj/shieldwall/Initialize(mapload, var/obj/machinery/shieldwallgen/A, var/obj/machinery/shieldwallgen/B)
+ . = ..()
+ update_nearby_tiles()
+ gen_primary = A
+ gen_secondary = B
+ if(A?.power_state && B?.power_state)
+ needs_power = TRUE
+ A.storedpower -= generate_power_usage / 2
+ B.storedpower -= generate_power_usage / 2
+ START_PROCESSING(SSprocessing, src)
+ else
+ qdel(src) //need at least two generator posts
+
+/obj/shieldwall/Destroy()
+ update_nearby_tiles()
+ STOP_PROCESSING(SSprocessing, src)
+ return ..()
+
+/obj/shieldwall/attack_hand(mob/user)
+ to_chat(user, SPAN_WARNING("\The [src] pushes you back as you try to touch it."))
+
+/obj/shieldwall/process()
+ if(needs_power)
+ if(!gen_primary || !gen_secondary)
+ qdel(src)
+ return
+
+ if(!gen_primary.power_state || !gen_secondary.power_state)
+ qdel(src)
+ return
+
+ gen_primary.storedpower -= power_usage / 2
+ gen_secondary.storedpower -= power_usage / 2
+
+/obj/shieldwall/bullet_act(var/obj/item/projectile/Proj)
+ if(needs_power)
+ var/obj/machinery/shieldwallgen/G
+ if(prob(50))
+ G = gen_primary
+ else
+ G = gen_secondary
+ visible_message(SPAN_WARNING("\The [src] wobbles precariously as \the [Proj] impacts it!"))
+ G.storedpower -= 400 * Proj.get_structure_damage()
+ return ..()
+
+/obj/shieldwall/ex_act(severity)
+ if(needs_power)
+ var/obj/machinery/shieldwallgen/G
+ switch(severity)
+ if(1.0) //big boom
+ if(prob(50))
+ G = gen_primary
+ else
+ G = gen_secondary
+ G.storedpower -= 120000
+
+ if(2.0) //medium boom
+ if(prob(50))
+ G = gen_primary
+ else
+ G = gen_secondary
+ G.storedpower -= 30000
+
+ if(3.0) //lil boom
+ if(prob(50))
+ G = gen_primary
+ else
+ G = gen_secondary
+ G.storedpower -= 12000
+
+/obj/shieldwall/CanPass(atom/movable/mover, turf/target, height=0, air_group=0)
+ if(air_group || (height==0))
+ return TRUE
+ if(istype(mover) && mover.checkpass(PASSGLASS))
+ return prob(20)
+ else
+ if(istype(mover, /obj/item/projectile))
+ return prob(10)
+ else
+ return !density
\ No newline at end of file
diff --git a/html/changelogs/geeves-shieldwall_responsiveness.yml b/html/changelogs/geeves-shieldwall_responsiveness.yml
new file mode 100644
index 00000000000..a0542ad8af9
--- /dev/null
+++ b/html/changelogs/geeves-shieldwall_responsiveness.yml
@@ -0,0 +1,6 @@
+author: Geeves
+
+delete-after: True
+
+changes:
+ - rscadd: "Cleaned up some Shield Generator code, and added some text to generated shields being hit by projectiles, making it more clear that projectiles can dissipate those shields."
\ No newline at end of file