diff --git a/code/WorkInProgress/Cael_Aislinn/energy_field.dm b/code/WorkInProgress/Cael_Aislinn/energy_field.dm
new file mode 100644
index 00000000000..363b1ada26b
--- /dev/null
+++ b/code/WorkInProgress/Cael_Aislinn/energy_field.dm
@@ -0,0 +1,41 @@
+
+//---------- actual energy field
+
+/obj/effect/energy_field
+ name = "energy field"
+ desc = "Impenetrable field of energy, capable of blocking anything as long as it's active."
+ icon = 'shielding.dmi'
+ icon_state = "shieldsparkles"
+ anchored = 1
+ layer = 2.1
+ density = 0
+ invisibility = 2
+ var/strength = 0
+ var/obj/machinery/shield_gen/parent
+ var/stress = 0
+
+/obj/effect/energy_field/ex_act(var/severity)
+ Stress(2)
+ //nothing
+
+/obj/effect/energy_field/meteorhit(obj/effect/meteor/M as obj)
+ if(M)
+ walk(M,0)
+
+/obj/effect/energy_field/proc/Stress(var/severity)
+ strength -= severity
+ stress += severity
+
+ //if we take too much damage, drop out - the generator will bring us back up if we have enough power
+ if(strength < 1)
+ invisibility = 2
+ density = 0
+
+/obj/effect/energy_field/CanPass(atom/movable/mover, turf/target, height=1.5, air_group = 0)
+ //Purpose: Determines if the object (or airflow) can pass this atom.
+ //Called by: Movement, airflow.
+ //Inputs: The moving atom (optional), target turf, "height" and air group
+ //Outputs: Boolean if can pass.
+
+ //return (!density || !height || air_group)
+ return 0
diff --git a/code/WorkInProgress/Cael_Aislinn/external_shield_gen.dm b/code/WorkInProgress/Cael_Aislinn/external_shield_gen.dm
new file mode 100644
index 00000000000..c4524ad94e0
--- /dev/null
+++ b/code/WorkInProgress/Cael_Aislinn/external_shield_gen.dm
@@ -0,0 +1,64 @@
+
+//---------- external shield generator
+//generates an energy field that loops around any built up area in space (is useless inside) halts movement and airflow, is blocked by walls, windows, airlocks etc
+
+/obj/machinery/shield_gen/external/New()
+ ..()
+
+/obj/machinery/shield_gen/external/get_shielded_turfs()
+ var
+ list
+ open = list(get_turf(src))
+ closed = list()
+
+ while(open.len)
+ for(var/turf/T in open)
+ for(var/turf/O in orange(1, T))
+ if(get_dist(O,src) > field_radius)
+ continue
+ var/add_this_turf = 0
+ if(istype(O,/turf/space))
+ for(var/turf/simulated/G in orange(1, O))
+ add_this_turf = 1
+ break
+ for(var/obj/structure/S in orange(1, O))
+ add_this_turf = 1
+ break
+ for(var/obj/structure/S in O)
+ add_this_turf = 0
+ break
+
+ if(add_this_turf && !(O in open) && !(O in closed))
+ open += O
+ open -= T
+ closed += T
+
+ return closed
+
+/obj/machinery/shield_gen/external/process()
+ /*if(stat & (NOPOWER|BROKEN))
+ return*/
+ if(!active)
+ return
+ /*spawn(100)
+ power()*/
+ /*if(src.active >= 1)
+ if(src.power == 0)
+ src.visible_message("\red The [src.name] shuts down due to lack of power!", \
+ "You hear heavy droning fade out")
+ icon_state = "generator0"
+ src.active = 0*/
+ ..()
+
+/obj/item/weapon/circuitboard/shield_gen/external
+ name = "Circuit Board (External Shield Generator)"
+ build_path = "/obj/machinery/shield_gen/external"
+ board_type = "machine"
+ origin_tech = "electromagnetic=3;engineering=2;power=1"
+ frame_desc = "Requires, 2 Cable Coil, 2 Nano Manipulator, 1 Advanced Matter Bin, 1 Console Screen and 1 High-Power Micro-Laser. "
+ req_components = list(
+ "/obj/item/weapon/cable_coil" = 2,
+ "/obj/item/weapon/stock_parts/manipulator/nano" = 2,
+ "/obj/item/weapon/stock_parts/matter_bin/adv" = 1,
+ "/obj/item/weapon/stock_parts/console_screen" = 1,
+ "/obj/item/weapon/stock_parts/micro_laser/high" = 1)
diff --git a/code/WorkInProgress/Cael_Aislinn/shield_capacitor.dm b/code/WorkInProgress/Cael_Aislinn/shield_capacitor.dm
new file mode 100644
index 00000000000..50896434d7f
--- /dev/null
+++ b/code/WorkInProgress/Cael_Aislinn/shield_capacitor.dm
@@ -0,0 +1,156 @@
+
+//---------- shield capacitor
+//pulls energy out of a power net and charges an adjacent generator
+
+/obj/machinery/shield_capacitor
+ name = "shield capacitor"
+ desc = "Machine that charges a shield generator."
+ icon = 'shielding.dmi'
+ icon_state = "capacitor"
+ var/active = 1
+ density = 1
+ anchored = 1
+ var/obj/machinery/shield_gen/target_generator
+ var/stored_charge = 0
+ var/time_since_fail = 100
+ var/max_charge = 1000000
+ var/max_charge_rate = 100000
+ var/min_charge_rate = 0
+ var/locked = 0
+ //
+ use_power = 1 //0 use nothing
+ //1 use idle power
+ //2 use active power
+ idle_power_usage = 10
+ active_power_usage = 100
+ var/charge_rate = 100
+
+/obj/machinery/shield_capacitor/New()
+ ..()
+ target_generator = locate() in get_step(src,dir)
+ if(target_generator && !target_generator.owned_capacitor)
+ target_generator.owned_capacitor = src
+ /*spawn(10)
+ check_powered()*/
+
+/obj/machinery/shield_capacitor/power_change()
+ if(stat & BROKEN)
+ icon_state = "broke"
+ else
+ if( powered() )
+ if (src.active)
+ icon_state = "capacitor"
+ else
+ icon_state = "capacitor"
+ stat &= ~NOPOWER
+ else
+ spawn(rand(0, 15))
+ src.icon_state = "capacitor"
+ stat |= NOPOWER
+
+/obj/machinery/shield_capacitor/process()
+ //
+ if(active)
+ use_power = 2
+ if(stored_charge + charge_rate > max_charge)
+ active_power_usage = max_charge - stored_charge
+ else
+ active_power_usage = charge_rate
+ stored_charge += active_power_usage
+ else
+ use_power = 1
+
+ time_since_fail++
+ if(stored_charge < active_power_usage * 1.5)
+ time_since_fail = 0
+ //
+ updateDialog()
+
+/obj/machinery/shield_capacitor/attackby(obj/item/W, mob/user)
+ /*if(istype(W, /obj/item/weapon/wrench))
+ if(active)
+ user << "Turn off the field generator first."
+ return
+
+ else if(state == 0)
+ state = 1
+ playsound(src.loc, 'Ratchet.ogg', 75, 1)
+ user << "You secure the external reinforcing bolts to the floor."
+ src.anchored = 1
+ return
+
+ else if(state == 1)
+ state = 0
+ playsound(src.loc, 'Ratchet.ogg', 75, 1)
+ user << "You undo the external reinforcing bolts."
+ src.anchored = 0
+ return*/
+
+ if(istype(W, /obj/item/weapon/card/id)||istype(W, /obj/item/device/pda))
+ if (src.allowed(user))
+ src.locked = !src.locked
+ user << "Controls are now [src.locked ? "locked." : "unlocked."]"
+ else
+ user << "\red Access denied."
+
+ else
+ src.add_fingerprint(user)
+ user << "\red You hit the [src.name] with your [W.name]!"
+ for(var/mob/M in viewers(src))
+ if(M == user) continue
+ M.show_message("\red The [src.name] has been hit with the [W.name] by [user.name]!")
+
+/obj/machinery/shield_capacitor/attack_hand(mob/user as mob)
+ interact(user)
+ src.add_fingerprint(user)
+
+/obj/machinery/shield_capacitor/Topic(href, href_list[])
+ ..()
+ if( href_list["close"] )
+ usr << browse(null, "window=shield_capacitor")
+ usr.machine = null
+ return
+ if( href_list["toggle"] )
+ active = !active
+ if(active)
+ use_power = 2
+ else
+ use_power = 1
+ if( href_list["charge_rate"] )
+ charge_rate += text2num(href_list["charge_rate"])
+ if(charge_rate > max_charge_rate)
+ charge_rate = max_charge_rate
+ else if(charge_rate < min_charge_rate)
+ charge_rate = min_charge_rate
+ //
+ updateDialog()
+
+/obj/machinery/shield_capacitor/proc/interact(mob/user)
+ if ( (get_dist(src, user) > 1 ) || (stat & (BROKEN|NOPOWER)) )
+ if (!istype(user, /mob/living/silicon))
+ user.machine = null
+ user << browse(null, "window=shield_capacitor")
+ return
+ var/t = "Shield Capacitor Control Console
"
+ t += "[target_generator ? "Shield generator connected." : "Unable to locate shield generator!"]
"
+ t += "This capacitor is: [active ? "Online" : "Offline" ] [active ? "\[Deactivate\]" : "\[Activate\]"]
"
+ t += "[time_since_fail > 2 ? "Charging stable." : "Warning, low charge!"]
"
+ t += "Capacitor charge: [stored_charge] Watts ([100 * stored_charge/max_charge]%)
"
+ t += "Capacitor charge rate (approx): \[min\] \[--\] \[-\][charge_rate] Watts/sec \[+\] \[++\] \[max\]
"
+ t += "
"
+ t += "Close
"
+ user << browse(t, "window=shield_capacitor;size=500x800")
+ user.machine = src
+
+/obj/item/weapon/circuitboard/shield_capacitor
+ name = "Circuit Board (Shield Capacitor)"
+ build_path = "/obj/machinery/shield_capacitor"
+ board_type = "machine"
+ origin_tech = "electromagnetic=3;engineering=2;power=1"
+ frame_desc = "Requires, 2 Cable Coil, 2 Nano Manipulator, 1 Advanced Matter Bin, 1 Console Screen and 1 High-Power Micro-Laser. "
+ req_components = list(
+ "/obj/item/weapon/cable_coil" = 2,
+ "/obj/item/weapon/stock_parts/manipulator/nano" = 2,
+ "/obj/item/weapon/stock_parts/matter_bin/adv" = 1,
+ "/obj/item/weapon/stock_parts/console_screen" = 1,
+ "/obj/item/weapon/stock_parts/micro_laser/high" = 1)
diff --git a/code/WorkInProgress/Cael_Aislinn/shield_gen.dm b/code/WorkInProgress/Cael_Aislinn/shield_gen.dm
new file mode 100644
index 00000000000..46f1f4c6abb
--- /dev/null
+++ b/code/WorkInProgress/Cael_Aislinn/shield_gen.dm
@@ -0,0 +1,280 @@
+//renwicks: fictional unit to describe shield strength
+//a small meteor hit will deduct 1 renwick of strength from that shield tile
+//light explosion range will do 1 renwick's damage
+//medium explosion range will do 2 renwick's damage
+//heavy explosion range will do 3 renwick's damage
+//explosion damage is cumulative. if a tile is in range of light, medium and heavy damage, it will take a hit from all three
+
+/obj/machinery/shield_gen
+ name = "shield generator"
+ desc = "Machine that generates an impenetrable field of energy when activated."
+ icon = 'shielding.dmi'
+ icon_state = "generator0"
+ var/active = 0
+ var/field_radius = 3
+ var/list/field
+ density = 1
+ anchored = 1
+ var/locked = 0
+ var/average_field_strength = 0
+ var/strengthen_rate = 0.2
+ var/max_strengthen_rate = 0.2
+ var/powered = 0
+ var/check_powered = 1
+ var/obj/machinery/shield_capacitor/owned_capacitor
+ var/max_field_strength = 10
+ var/time_since_fail = 100
+ var/energy_conversion_rate = 0.01 //how many renwicks per watt?
+ var/flicker_shield_glitch = 1 //shield is slightly faulty, and flickers
+ //
+ use_power = 1 //0 use nothing
+ //1 use idle power
+ //2 use active power
+ idle_power_usage = 20
+ active_power_usage = 100
+
+/obj/machinery/shield_gen/New()
+ ..()
+ field = new/list()
+ for(var/obj/machinery/shield_capacitor/possible_cap in range(1))
+ if(get_dir(possible_cap, src) == possible_cap.dir)
+ owned_capacitor = possible_cap
+ break
+ /*spawn(10)
+ check_powered()*/
+
+//copied from a copypaste. DRY, right?
+/obj/machinery/shield_gen/proc/check_powered()
+ /*
+ check_powered = 1
+ if(!anchored)
+ powered = 0
+ return 0
+ var/turf/T = src.loc
+ var/obj/structure/cable/C = T.get_cable_node()
+ var/net
+ if (C)
+ net = C.netnum // find the powernet of the connected cable
+
+ if(!net)
+ powered = 0
+ return 0
+ var/datum/powernet/PN = powernets[net] // find the powernet. Magic code, voodoo code.
+
+ if(!PN)
+ powered = 0
+ return 0
+ var/surplus = max(PN.avail-PN.load, 0)
+ var/shieldload = min(rand(50,200), surplus)
+ if(shieldload==0 && !storedpower) // no cable or no power, and no power stored
+ powered = 0
+ return 0
+ else
+ powered = 1
+ if(PN)
+ storedpower += shieldload
+ PN.newload += shieldload //uses powernet power.
+ */
+
+/obj/machinery/shield_gen/process()
+
+ if(!owned_capacitor)
+ for(var/obj/machinery/shield_capacitor/possible_cap in range(1))
+ if(get_dir(possible_cap, src) == possible_cap.dir)
+ owned_capacitor = possible_cap
+ break
+
+ if(active && field.len)
+ var/stored_renwicks = 0
+ var/target_field_strength = min(average_field_strength + strengthen_rate, max_field_strength)
+ if(owned_capacitor)
+ var/assumed_charge = min(owned_capacitor.stored_charge, (target_field_strength / energy_conversion_rate) * field.len)
+ stored_renwicks = assumed_charge * energy_conversion_rate
+ owned_capacitor.stored_charge -= assumed_charge
+
+ time_since_fail++
+
+ average_field_strength = 0
+ target_field_strength = stored_renwicks / field.len
+
+ if(!flicker_shield_glitch)
+ for(var/obj/effect/energy_field/E in field)
+ //check to see if the shield is strengthening or failing
+ if(E.strength > target_field_strength)
+ E.strength = target_field_strength
+ else if(E.strength + strengthen_rate > target_field_strength)
+ E.strength = target_field_strength
+ else
+ E.strength += strengthen_rate
+
+ if(stored_renwicks - E.strength < 0)
+ E.strength = stored_renwicks
+ stored_renwicks -= E.strength
+
+ average_field_strength += E.strength
+ //check if the current shield tile has enough energy to maintain itself
+ if(E.strength >= 1)
+ E.density = 1
+ E.invisibility = 0
+ else
+ E.density = 0
+ E.invisibility = 2
+ else
+ //the flicker shield glitch is an intersting quirk in 'older' and/or faulty shielding models
+ //basically, it strengthens the shields continuously until it can no longer sustain them... then it drops out for a few seconds and starts again
+ //this makes the shield 'flicker' every now and then until it stabilises
+ //when this glitch is fixed, shields will only be charged as much as is sustainable
+ for(var/obj/effect/energy_field/E in field)
+ //check to see if the shield is strengthening or failing
+ if(E.strength < target_field_strength)
+ E.strength += strengthen_rate
+
+ retry:
+ if(stored_renwicks - E.strength < 0)
+ if(owned_capacitor.stored_charge > 0)
+ var/emergency_renwicks = min(E.strength, owned_capacitor.stored_charge * energy_conversion_rate)
+ owned_capacitor.stored_charge -= emergency_renwicks / energy_conversion_rate
+ stored_renwicks += emergency_renwicks
+ goto retry
+ else
+ E.strength = stored_renwicks
+ stored_renwicks -= E.strength
+
+ average_field_strength += E.strength
+ //check if the current shield tile has enough energy to maintain itself
+ if(E.strength >= 1)
+ E.density = 1
+ E.invisibility = 0
+ else
+ E.density = 0
+ E.invisibility = 2
+
+ //add any leftover charge back to the capacitor
+ if(owned_capacitor && stored_renwicks >= 0)
+ owned_capacitor.stored_charge += stored_renwicks / energy_conversion_rate
+
+ average_field_strength /= field.len
+ if(average_field_strength < 0)
+ time_since_fail = 0
+ else
+ average_field_strength = 0
+ //
+ updateDialog()
+
+/obj/machinery/shield_gen/attack_hand(mob/user as mob)
+
+ interact(user)
+ src.add_fingerprint(user)
+
+/obj/machinery/shield_gen/attackby(obj/item/W, mob/user)
+
+ if(istype(W, /obj/item/weapon/card/id)||istype(W, /obj/item/device/pda))
+ if (src.allowed(user))
+ src.locked = !src.locked
+ user << "Controls are now [src.locked ? "locked." : "unlocked."]"
+ else
+ user << "\red Access denied."
+
+ else
+ src.add_fingerprint(user)
+ user << "\red You hit the [src.name] with your [W.name]!"
+ for(var/mob/M in viewers(src))
+ if(M == user) continue
+ M.show_message("\red The [src.name] has been hit with the [W.name] by [user.name]!")
+
+/obj/machinery/shield_gen/power_change()
+ if(stat & BROKEN)
+ icon_state = "broke"
+ else
+ if( powered() )
+ if (src.active)
+ icon_state = "generator1"
+ else
+ icon_state = "generator0"
+ stat &= ~NOPOWER
+ else
+ spawn(rand(0, 15))
+ src.icon_state = "generator0"
+ stat |= NOPOWER
+ if (src.active)
+ toggle()
+
+/obj/machinery/shield_gen/proc/toggle()
+ active = !active
+ power_change()
+ if(active)
+ var/list/covered_turfs = get_shielded_turfs()
+ if(get_turf(src) in covered_turfs)
+ covered_turfs.Remove(get_turf(src))
+ for(var/turf/O in covered_turfs)
+ var/obj/effect/energy_field/E = new(O)
+ field.Add(E)
+ del covered_turfs
+
+ for(var/mob/M in view(5,src))
+ M << "\icon[src] You hear heavy droning start up."
+ else
+ for(var/obj/effect/energy_field/D in field)
+ field.Remove(D)
+ del D
+
+ for(var/mob/M in view(5,src))
+ M << "\icon[src] You hear heavy droning fade out."
+
+/obj/machinery/shield_gen/Topic(href, href_list[])
+ ..()
+ if( href_list["close"] )
+ usr << browse(null, "window=shield_generator")
+ usr.machine = null
+ return
+ else if( href_list["toggle"] )
+ toggle()
+ else if( href_list["change_radius"] )
+ field_radius += text2num(href_list["change_radius"])
+ if(field_radius > 200)
+ field_radius = 200
+ else if(field_radius < 0)
+ field_radius = 0
+ else if( href_list["strengthen_rate"] )
+ strengthen_rate += text2num(href_list["strengthen_rate"])
+ if(strengthen_rate > 0.2)
+ strengthen_rate = 0.2
+ else if(strengthen_rate < 0)
+ strengthen_rate = 0
+ else if( href_list["max_field_strength"] )
+ max_field_strength += text2num(href_list["max_field_strength"])
+ if(max_field_strength > 1000)
+ max_field_strength = 1000
+ else if(max_field_strength < 0)
+ max_field_strength = 0
+ //
+ updateDialog()
+
+/obj/machinery/shield_gen/proc/interact(mob/user)
+ if ( (get_dist(src, user) > 1 ) || (stat & (BROKEN|NOPOWER)) )
+ if (!istype(user, /mob/living/silicon))
+ user.machine = null
+ user << browse(null, "window=shield_generator")
+ return
+ var/t = "Shield Generator Control Console
"
+ t += "[owned_capacitor ? "Charge capacitor connected." : "Unable to locate charge capacitor!"]
"
+ t += "This generator is: [active ? "Online" : "Offline" ] [active ? "\[Deactivate\]" : "\[Activate\]"]
"
+ t += "[time_since_fail > 2 ? "Field is stable." : "Warning, field is unstable!"]
"
+ t += "Coverage radius (generator will need a restart to take effect): -- - [field_radius * 2]m + ++
"
+ t += "Overall field strength: [average_field_strength] Renwicks ([100 * average_field_strength / max_field_strength]%)
"
+ t += "Charge consumption: [( (min(average_field_strength + strengthen_rate, max_field_strength)) / energy_conversion_rate) * field.len] Watts/sec
"
+ t += "Field charge rate (approx): -- -[strengthen_rate] Renwicks/sec + ++
"
+ t += "Maximum field strength (avg across field): \[min\] -- -[max_field_strength] Renwicks + ++ \[max\]
"
+ t += "
"
+ t += "Close
"
+ user << browse(t, "window=shield_generator;size=500x800")
+ user.machine = src
+
+/obj/machinery/shield_gen/proc/get_shielded_turfs()
+ return list()
+
+/obj/machinery/shield_gen/ex_act(var/severity)
+
+ if(active)
+ toggle()
+ return ..()
diff --git a/code/game/objects/explosion.dm b/code/game/objects/explosion.dm
index f701024bd6a..658d1a26c4c 100644
--- a/code/game/objects/explosion.dm
+++ b/code/game/objects/explosion.dm
@@ -36,7 +36,8 @@ proc/explosion(turf/epicenter, devastation_range, heavy_impact_range, light_impa
var/list/fTurfs = list() //Holds turfs to loop through for mobs to flash. (Hehehe, dirty)
//cael - replaced range() and circlerange() with FloodFill() to prevent explosions getting through shielding (ultrarealism mode)
- //if testing indicates this is adding too much lag, roll back all shield handling
+ //also lag is pre'y bad
+ /*
if(roundExplosions)
if(/obj/effect/energy_field in range(src, max(devastation_range, heavy_impact_range, light_impact_range)))
fTurfs = ExplosionCircleFloodFill(epicenter,max(devastation_range, heavy_impact_range, light_impact_range, flash_range))
@@ -68,6 +69,45 @@ proc/explosion(turf/epicenter, devastation_range, heavy_impact_range, light_impa
hTurfs = range(epicenter,heavy_impact_range) - dTurfs
lTurfs = range(epicenter,light_impact_range) - dTurfs - hTurfs
+ //add some stress to nearby shields
+ for(var/obj/effect/energy_field/E in range(epicenter, devastation_range))
+ E.Stress(3)
+ for(var/obj/effect/energy_field/E in range(epicenter, heavy_impact_range))
+ E.Stress(2)
+ for(var/obj/effect/energy_field/E in range(epicenter, light_impact_range))
+ E.Stress(1)*/
+
+ if(roundExplosions)
+ if(/obj/effect/energy_field in range(src, max(devastation_range, heavy_impact_range, light_impact_range)))
+ fTurfs = circlerange(epicenter,max(devastation_range, heavy_impact_range, light_impact_range, flash_range))
+ dTurfs = circlerange(epicenter,devastation_range)
+ hTurfs = circlerange(epicenter,heavy_impact_range) - dTurfs
+ lTurfs = circlerange(epicenter,light_impact_range) - dTurfs - hTurfs
+ else
+ fTurfs = circlerange(epicenter,max(devastation_range, heavy_impact_range, light_impact_range, flash_range))
+ dTurfs = circlerange(epicenter,devastation_range)
+ hTurfs = circlerange(epicenter,heavy_impact_range) - dTurfs
+ lTurfs = circlerange(epicenter,light_impact_range) - dTurfs - hTurfs
+
+ //add some stress to nearby shields
+ for(var/obj/effect/energy_field/E in circlerange(epicenter, devastation_range))
+ E.Stress(3)
+ for(var/obj/effect/energy_field/E in circlerange(epicenter, heavy_impact_range))
+ E.Stress(2)
+ for(var/obj/effect/energy_field/E in circlerange(epicenter, light_impact_range))
+ E.Stress(1)
+ else
+ if(/obj/effect/energy_field in range(src, max(devastation_range, heavy_impact_range, light_impact_range)))
+ fTurfs = range(epicenter,max(devastation_range, heavy_impact_range, light_impact_range, flash_range))
+ dTurfs = range(epicenter,devastation_range)
+ hTurfs = range(epicenter,heavy_impact_range) - dTurfs
+ lTurfs = range(epicenter,light_impact_range) - dTurfs - hTurfs
+ else
+ fTurfs = range(epicenter,max(devastation_range, heavy_impact_range, light_impact_range, flash_range))
+ dTurfs = range(epicenter,devastation_range)
+ hTurfs = range(epicenter,heavy_impact_range) - dTurfs
+ lTurfs = range(epicenter,light_impact_range) - dTurfs - hTurfs
+
//add some stress to nearby shields
for(var/obj/effect/energy_field/E in range(epicenter, devastation_range))
E.Stress(3)