diff --git a/code/ZAS/Creation.dm b/code/ZAS/Creation.dm index 225fc02eff7..b283cd56d43 100644 --- a/code/ZAS/Creation.dm +++ b/code/ZAS/Creation.dm @@ -67,10 +67,10 @@ proc/FloodFill(turf/start) return closed -turf/proc/ZCanPass(turf/T) +turf/proc/ZCanPass(turf/T, var/include_space = 0) //Fairly standard pass checks for turfs, objects and directional windows. Also stops at the edge of space. - if(istype(T,/turf/space)) return 0 + if(istype(T,/turf/space) && !include_space) return 0 else if(T.blocks_air||blocks_air) return 0 diff --git a/code/defines/procs/gamehelpers.dm b/code/defines/procs/gamehelpers.dm index 5b5b1bc8845..51b4adfee44 100644 --- a/code/defines/procs/gamehelpers.dm +++ b/code/defines/procs/gamehelpers.dm @@ -295,3 +295,124 @@ proc/is_carrying(var/M as mob, var/O as obj) return 1 O = O:loc return 0 + +//hackcopy from a ZAS function, first created for use with intertial_damper/new shielding +proc/CircleFloodFill(turf/start, var/radius = 3) + if(!istype(start)) + return list() + var + list + open = list(start) + closed = list() + possibles = circlerange(start,radius) + + while(open.len) + for(var/turf/T in open) + //Stop if there's a door, even if it's open. These are handled by indirect connection. + if(!T.HasDoor()) + + for(var/d in cardinal) + var/turf/O = get_step(T,d) + //Simple pass check. + if(O.ZCanPass(T, 1) && !(O in open) && !(O in closed) && O in possibles) + open += O + + open -= T + closed += T + + return closed + +//floods in a square area, flowing around any shielding but including all other turf types +//created initially for explosion / shield interaction +proc/ExplosionFloodFill(turf/start, var/radius = 3) + if(!istype(start)) + return list() + var + list + open = list(start) + closed = list() + possibles = range(start,radius) + + while(open.len) + for(var/turf/T in open) + for(var/turf/O in range(T,1)) + if( !(O in possibles) || O in open || O in closed ) + continue + var/shield_here = 0 + for(var/obj/effect/energy_field/E in O) + if(E.density) + shield_here = 1 + break + if(!shield_here) + open += O + + open -= T + closed += T + + return closed + +/* + +/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 +*/ + +//floods in a circular area, flowing around any shielding but including all other turf types +//created initially for explosion / shield interaction +proc/ExplosionCircleFloodFill(turf/start, var/radius = 3) + if(!istype(start)) + return list() + var + list + open = list(start) + closed = list() + possibles = circlerange(start,radius) + + while(open.len) + for(var/turf/T in open) + for(var/turf/O in range(T,1)) + if(get_dist(O,start) > radius) + continue + + if( !(O in possibles) || O in open || O in closed ) + continue + var/shield_here = 0 + for(var/obj/effect/energy_field/E in O) + if(E.density) + shield_here = 1 + break + if(!shield_here && (O in possibles) && !(O in open) && !(O in closed)) + open += O + + open -= T + closed += T + + return closed + diff --git a/code/game/objects/explosion.dm b/code/game/objects/explosion.dm index 3210d70d6ef..47c9e3f2459 100644 --- a/code/game/objects/explosion.dm +++ b/code/game/objects/explosion.dm @@ -28,22 +28,51 @@ proc/explosion(turf/epicenter, devastation_range, heavy_impact_range, light_impa E.set_up(epicenter) E.start() - var/list/dTurfs = list() //Holds the turfs in devestation range. - var/list/hTurfs = list() //Holds the turfs in heavy impact range, minus turfs in devestation range. - var/list/lTurfs = list() //Holds the turfs in light impact range, minus turfs in devestation range and heavy impact range. - var/list/fTurfs = list() //Holds turfs to loop through for mobs to flash. (Hehehe, dirty) + var/list/dTurfs = list() //Holds the turfs in devestation range. + var/list/hTurfs = list() //Holds the turfs in heavy impact range, minus turfs in devestation range. + var/list/lTurfs = list() //Holds the turfs in light impact range, minus turfs in devestation range and heavy impact range. + 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 if(roundExplosions) - 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 = 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 + 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)) + dTurfs = ExplosionCircleFloodFill(epicenter,devastation_range) + hTurfs = ExplosionCircleFloodFill(epicenter,heavy_impact_range) - dTurfs + lTurfs = ExplosionCircleFloodFill(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 = ExplosionFloodFill(epicenter,max(devastation_range, heavy_impact_range, light_impact_range, flash_range)) + dTurfs = ExplosionFloodFill(epicenter,devastation_range) + hTurfs = ExplosionFloodFill(epicenter,heavy_impact_range) - dTurfs + lTurfs = ExplosionFloodFill(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) + 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) for(var/turf/T in dTurfs) //Loop through the turfs in devestation range. spawn() //Try to pop each turf into it's own thread, speed things along.