mirror of
https://github.com/CHOMPStation2/CHOMPStation2.git
synced 2025-12-10 10:12:45 +00:00
Ports MultiZAS
This commit is contained in:
@@ -57,11 +57,11 @@ turf/c_airblock(turf/other)
|
||||
#ifdef ZASDBG
|
||||
ASSERT(isturf(other))
|
||||
#endif
|
||||
if(blocks_air || other.blocks_air)
|
||||
if(((blocks_air & AIR_BLOCKED) || (other.blocks_air & AIR_BLOCKED)))
|
||||
return BLOCKED
|
||||
|
||||
//Z-level handling code. Always block if there isn't an open space.
|
||||
#ifdef ZLEVELS
|
||||
#ifdef MULTIZAS
|
||||
if(other.z != src.z)
|
||||
if(other.z < src.z)
|
||||
if(!istype(src, /turf/simulated/open)) return BLOCKED
|
||||
@@ -69,6 +69,12 @@ turf/c_airblock(turf/other)
|
||||
if(!istype(other, /turf/simulated/open)) return BLOCKED
|
||||
#endif
|
||||
|
||||
if(((blocks_air & ZONE_BLOCKED) || (other.blocks_air & ZONE_BLOCKED)))
|
||||
if(z == other.z)
|
||||
return ZONE_BLOCKED
|
||||
else
|
||||
return AIR_BLOCKED
|
||||
|
||||
var/result = 0
|
||||
for(var/atom/movable/M in contents)
|
||||
result |= M.c_airblock(other)
|
||||
|
||||
@@ -37,7 +37,7 @@ Class Procs:
|
||||
/connection_manager/var/connection/E
|
||||
/connection_manager/var/connection/W
|
||||
|
||||
#ifdef ZLEVELS
|
||||
#ifdef MULTIZAS
|
||||
/connection_manager/var/connection/U
|
||||
/connection_manager/var/connection/D
|
||||
#endif
|
||||
@@ -57,7 +57,7 @@ Class Procs:
|
||||
if(check(W)) return W
|
||||
else return null
|
||||
|
||||
#ifdef ZLEVELS
|
||||
#ifdef MULTIZAS
|
||||
if(UP)
|
||||
if(check(U)) return U
|
||||
else return null
|
||||
@@ -73,7 +73,7 @@ Class Procs:
|
||||
if(EAST) E = c
|
||||
if(WEST) W = c
|
||||
|
||||
#ifdef ZLEVELS
|
||||
#ifdef MULTIZAS
|
||||
if(UP) U = c
|
||||
if(DOWN) D = c
|
||||
#endif
|
||||
@@ -83,7 +83,7 @@ Class Procs:
|
||||
if(check(S)) S.update()
|
||||
if(check(E)) E.update()
|
||||
if(check(W)) W.update()
|
||||
#ifdef ZLEVELS
|
||||
#ifdef MULTIZAS
|
||||
if(check(U)) U.update()
|
||||
if(check(D)) D.update()
|
||||
#endif
|
||||
@@ -93,7 +93,7 @@ Class Procs:
|
||||
if(check(S)) S.erase()
|
||||
if(check(E)) E.erase()
|
||||
if(check(W)) W.erase()
|
||||
#ifdef ZLEVELS
|
||||
#ifdef MULTIZAS
|
||||
if(check(U)) U.erase()
|
||||
if(check(D)) D.erase()
|
||||
#endif
|
||||
|
||||
@@ -158,6 +158,9 @@ Total Unsimulated Turfs: [world.maxx*world.maxy*world.maxz - simulated_turf_coun
|
||||
//defer updating of self-zone-blocked turfs until after all other turfs have been updated.
|
||||
//this hopefully ensures that non-self-zone-blocked turfs adjacent to self-zone-blocked ones
|
||||
//have valid zones when the self-zone-blocked turfs update.
|
||||
|
||||
//This ensures that doorways don't form their own single-turf zones, since doorways are self-zone-blocked and
|
||||
//can merge with an adjacent zone, whereas zones that are formed on adjacent turfs cannot merge with the doorway.
|
||||
var/list/deferred = list()
|
||||
|
||||
for(var/turf/T in updating)
|
||||
|
||||
@@ -39,6 +39,10 @@ client/proc/Test_ZAS_Connection(var/turf/simulated/T as turf)
|
||||
"South" = SOUTH,\
|
||||
"East" = EAST,\
|
||||
"West" = WEST,\
|
||||
#ifdef MULTIZAS
|
||||
"Up" = UP,\
|
||||
"Down" = DOWN,\
|
||||
#endif
|
||||
"N/A" = null)
|
||||
var/direction = input("What direction do you wish to test?","Set direction") as null|anything in direction_list
|
||||
if(!direction)
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
//dbg(blocked)
|
||||
return 1
|
||||
|
||||
#ifdef ZLEVELS
|
||||
#ifdef MULTIZAS
|
||||
for(var/d = 1, d < 64, d *= 2)
|
||||
#else
|
||||
for(var/d = 1, d < 16, d *= 2)
|
||||
@@ -52,34 +52,36 @@
|
||||
*/
|
||||
|
||||
/turf/simulated/proc/can_safely_remove_from_zone()
|
||||
#ifdef ZLEVELS
|
||||
return 0 //TODO generalize this to multiz.
|
||||
#else
|
||||
|
||||
|
||||
|
||||
if(!zone) return 1
|
||||
|
||||
|
||||
var/check_dirs = get_zone_neighbours(src)
|
||||
var/unconnected_dirs = check_dirs
|
||||
|
||||
for(var/dir in list(NORTHWEST, NORTHEAST, SOUTHEAST, SOUTHWEST))
|
||||
|
||||
var/to_check = list(NORTHEAST, NORTHWEST, SOUTHEAST, SOUTHWEST)
|
||||
#ifdef MULTIZAS
|
||||
to_check += list(NORTHUP, EASTUP, WESTUP, SOUTHUP, NORTHDOWN, EASTDOWN, WESTDOWN, SOUTHDOWN)
|
||||
#endif
|
||||
for(var/dir in to_check)
|
||||
//for each pair of "adjacent" cardinals (e.g. NORTH and WEST, but not NORTH and SOUTH)
|
||||
if((dir & check_dirs) == dir)
|
||||
//check that they are connected by the corner turf
|
||||
var/connected_dirs = get_zone_neighbours(get_step(src, dir))
|
||||
if(connected_dirs && (dir & turn(connected_dirs, 180)) == dir)
|
||||
if(connected_dirs && (dir & reverse_dir[connected_dirs]) == dir)
|
||||
unconnected_dirs &= ~dir //they are, so unflag the cardinals in question
|
||||
|
||||
|
||||
//it is safe to remove src from the zone if all cardinals are connected by corner turfs
|
||||
return !unconnected_dirs
|
||||
|
||||
#endif
|
||||
|
||||
//helper for can_safely_remove_from_zone()
|
||||
/turf/simulated/proc/get_zone_neighbours(turf/simulated/T)
|
||||
. = 0
|
||||
if(istype(T) && T.zone)
|
||||
for(var/dir in cardinal)
|
||||
var/to_check = cardinal.Copy()
|
||||
#ifdef MULTIZAS
|
||||
to_check += list(UP, DOWN)
|
||||
#endif
|
||||
for(var/dir in to_check)
|
||||
var/turf/simulated/other = get_step(T, dir)
|
||||
if(istype(other) && other.zone == T.zone && !(other.c_airblock(T) & AIR_BLOCKED) && get_dist(src, other) <= 1)
|
||||
. |= dir
|
||||
@@ -98,7 +100,7 @@
|
||||
#endif
|
||||
if(zone)
|
||||
var/zone/z = zone
|
||||
|
||||
|
||||
if(can_safely_remove_from_zone()) //Helps normal airlocks avoid rebuilding zones all the time
|
||||
z.remove(src)
|
||||
else
|
||||
@@ -110,7 +112,7 @@
|
||||
open_directions = 0
|
||||
|
||||
var/list/postponed
|
||||
#ifdef ZLEVELS
|
||||
#ifdef MULTIZAS
|
||||
for(var/d = 1, d < 64, d *= 2)
|
||||
#else
|
||||
for(var/d = 1, d < 16, d *= 2)
|
||||
@@ -161,7 +163,7 @@
|
||||
//Might have assigned a zone, since this happens for each direction.
|
||||
if(!zone)
|
||||
|
||||
//We do not merge if
|
||||
//We do not merge if
|
||||
// they are blocking us and we are not blocking them, or if
|
||||
// we are blocking them and not blocking ourselves - this prevents tiny zones from forming on doorways.
|
||||
if(((block & ZONE_BLOCKED) && !(r_block & ZONE_BLOCKED)) || ((r_block & ZONE_BLOCKED) && !(s_block & ZONE_BLOCKED)))
|
||||
|
||||
@@ -28,8 +28,7 @@ Notes for people who used ZAS before:
|
||||
*/
|
||||
|
||||
//#define ZASDBG
|
||||
//#define ZLEVELS
|
||||
|
||||
//#define MULTIZAS
|
||||
#define AIR_BLOCKED 1
|
||||
#define ZONE_BLOCKED 2
|
||||
#define BLOCKED 3
|
||||
|
||||
@@ -196,3 +196,13 @@
|
||||
#define TSC_MORPH "Morpheus"
|
||||
#define TSC_XION "Xion" // Not really needed but consistancy I guess.
|
||||
#define TSC_GIL "Gilthari"
|
||||
|
||||
//MultiZ directions for ZAS checks.
|
||||
#define NORTHUP (NORTH|UP)
|
||||
#define EASTUP (EAST|UP)
|
||||
#define SOUTHUP (SOUTH|UP)
|
||||
#define WESTUP (WEST|UP)
|
||||
#define NORTHDOWN (NORTH|DOWN)
|
||||
#define EASTDOWN (EAST|DOWN)
|
||||
#define SOUTHDOWN (SOUTH|DOWN)
|
||||
#define WESTDOWN (WEST|DOWN)
|
||||
|
||||
@@ -1,23 +1,26 @@
|
||||
//TODO: Flash range does nothing currently
|
||||
|
||||
proc/explosion(turf/epicenter, devastation_range, heavy_impact_range, light_impact_range, flash_range, adminlog = 1, z_transfer = UP|DOWN)
|
||||
proc/explosion(turf/epicenter, devastation_range, heavy_impact_range, light_impact_range, flash_range, adminlog = 1, z_transfer = UP|DOWN, shaped)
|
||||
var/multi_z_scalar = 0.35
|
||||
src = null //so we don't abort once src is deleted
|
||||
spawn(0)
|
||||
if(config.use_recursive_explosions)
|
||||
var/power = devastation_range * 2 + heavy_impact_range + light_impact_range //The ranges add up, ie light 14 includes both heavy 7 and devestation 3. So this calculation means devestation counts for 4, heavy for 2 and light for 1 power, giving us a cap of 27 power.
|
||||
explosion_rec(epicenter, power)
|
||||
return
|
||||
|
||||
var/start = world.timeofday
|
||||
epicenter = get_turf(epicenter)
|
||||
if(!epicenter) return
|
||||
|
||||
// Handles recursive propagation of explosions.
|
||||
if(devastation_range > 2 || heavy_impact_range > 2)
|
||||
if(HasAbove(epicenter.z) && z_transfer & UP)
|
||||
explosion(GetAbove(epicenter), max(0, devastation_range - 2), max(0, heavy_impact_range - 2), max(0, light_impact_range - 2), max(0, flash_range - 2), 0, UP)
|
||||
if(HasBelow(epicenter.z) && z_transfer & DOWN)
|
||||
explosion(GetAbove(epicenter), max(0, devastation_range - 2), max(0, heavy_impact_range - 2), max(0, light_impact_range - 2), max(0, flash_range - 2), 0, DOWN)
|
||||
if(z_transfer)
|
||||
var/adj_dev = max(0, (multi_z_scalar * devastation_range) - (shaped ? 2 : 0) )
|
||||
var/adj_heavy = max(0, (multi_z_scalar * heavy_impact_range) - (shaped ? 2 : 0) )
|
||||
var/adj_light = max(0, (multi_z_scalar * light_impact_range) - (shaped ? 2 : 0) )
|
||||
var/adj_flash = max(0, (multi_z_scalar * flash_range) - (shaped ? 2 : 0) )
|
||||
|
||||
|
||||
if(adj_dev > 0 || adj_heavy > 0)
|
||||
if(HasAbove(epicenter.z) && z_transfer & UP)
|
||||
explosion(GetAbove(epicenter), round(adj_dev), round(adj_heavy), round(adj_light), round(adj_flash), 0, UP, shaped)
|
||||
if(HasBelow(epicenter.z) && z_transfer & DOWN)
|
||||
explosion(GetBelow(epicenter), round(adj_dev), round(adj_heavy), round(adj_light), round(adj_flash), 0, DOWN, shaped)
|
||||
|
||||
var/max_range = max(devastation_range, heavy_impact_range, light_impact_range, flash_range)
|
||||
|
||||
@@ -30,34 +33,22 @@ proc/explosion(turf/epicenter, devastation_range, heavy_impact_range, light_impa
|
||||
far_dist += devastation_range * 20
|
||||
var/frequency = get_rand_frequency()
|
||||
for(var/mob/M in player_list)
|
||||
// Double check for client
|
||||
if(M && M.client)
|
||||
if(M.z == epicenter.z)
|
||||
var/turf/M_turf = get_turf(M)
|
||||
if(M_turf && M_turf.z == epicenter.z)
|
||||
var/dist = get_dist(M_turf, epicenter)
|
||||
// If inside the blast radius + world.view - 2
|
||||
if(dist <= round(max_range + world.view - 2, 1))
|
||||
M.playsound_local(epicenter, get_sfx("explosion"), 100, 1, frequency, falloff = 5) // get_sfx() is so that everyone gets the same sound
|
||||
var/dist = get_dist(M_turf, epicenter)
|
||||
// If inside the blast radius + world.view - 2
|
||||
if(dist <= round(max_range + world.view - 2, 1))
|
||||
M.playsound_local(epicenter, get_sfx("explosion"), 100, 1, frequency, falloff = 5) // get_sfx() is so that everyone gets the same sound
|
||||
else if(dist <= far_dist)
|
||||
var/far_volume = Clamp(far_dist, 30, 50) // Volume is based on explosion size and dist
|
||||
far_volume += (dist <= far_dist * 0.5 ? 50 : 0) // add 50 volume if the mob is pretty close to the explosion
|
||||
M.playsound_local(epicenter, 'sound/effects/explosionfar.ogg', far_volume, 1, frequency, falloff = 5)
|
||||
|
||||
//You hear a far explosion if you're outside the blast radius. Small bombs shouldn't be heard all over the station.
|
||||
|
||||
else if(dist <= far_dist)
|
||||
var/far_volume = Clamp(far_dist, 30, 50) // Volume is based on explosion size and dist
|
||||
far_volume += (dist <= far_dist * 0.5 ? 50 : 0) // add 50 volume if the mob is pretty close to the explosion
|
||||
M.playsound_local(epicenter, 'sound/effects/explosionfar.ogg', far_volume, 1, frequency, falloff = 5)
|
||||
|
||||
var/close = range(world.view+round(devastation_range,1), epicenter)
|
||||
// to all distanced mobs play a different sound
|
||||
for(var/mob/M in world) if(M.z == epicenter.z) if(!(M in close))
|
||||
// check if the mob can hear
|
||||
if(M.ear_deaf <= 0 || !M.ear_deaf) if(!istype(M.loc,/turf/space))
|
||||
M << 'sound/effects/explosionfar.ogg'
|
||||
if(adminlog)
|
||||
message_admins("Explosion with size ([devastation_range], [heavy_impact_range], [light_impact_range]) in area [epicenter.loc.name] ([epicenter.x],[epicenter.y],[epicenter.z]) (<A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[epicenter.x];Y=[epicenter.y];Z=[epicenter.z]'>JMP</a>)")
|
||||
log_game("Explosion with size ([devastation_range], [heavy_impact_range], [light_impact_range]) in area [epicenter.loc.name] ")
|
||||
|
||||
var/approximate_intensity = (devastation_range * 3) + (heavy_impact_range * 2) + light_impact_range
|
||||
var/powernet_rebuild_was_deferred_already = defer_powernet_rebuild
|
||||
// Large enough explosion. For performance reasons, powernets will be rebuilt manually
|
||||
if(!defer_powernet_rebuild && (approximate_intensity > 25))
|
||||
defer_powernet_rebuild = 1
|
||||
@@ -70,41 +61,41 @@ proc/explosion(turf/epicenter, devastation_range, heavy_impact_range, light_impa
|
||||
var/x0 = epicenter.x
|
||||
var/y0 = epicenter.y
|
||||
var/z0 = epicenter.z
|
||||
if(config.use_recursive_explosions)
|
||||
var/power = devastation_range * 2 + heavy_impact_range + light_impact_range //The ranges add up, ie light 14 includes both heavy 7 and devestation 3. So this calculation means devestation counts for 4, heavy for 2 and light for 1 power, giving us a cap of 27 power.
|
||||
explosion_rec(epicenter, power, shaped)
|
||||
else
|
||||
for(var/turf/T in trange(max_range, epicenter))
|
||||
var/dist = sqrt((T.x - x0)**2 + (T.y - y0)**2)
|
||||
|
||||
for(var/turf/T in trange(max_range, epicenter))
|
||||
var/dist = sqrt((T.x - x0)**2 + (T.y - y0)**2)
|
||||
if(dist < devastation_range) dist = 1
|
||||
else if(dist < heavy_impact_range) dist = 2
|
||||
else if(dist < light_impact_range) dist = 3
|
||||
else continue
|
||||
|
||||
if(dist < devastation_range) dist = 1
|
||||
else if(dist < heavy_impact_range) dist = 2
|
||||
else if(dist < light_impact_range) dist = 3
|
||||
else continue
|
||||
|
||||
T.ex_act(dist)
|
||||
if(T)
|
||||
T.ex_act(dist)
|
||||
if(!T)
|
||||
T = locate(x0,y0,z0)
|
||||
for(var/atom_movable in T.contents) //bypass type checking since only atom/movable can be contained by turfs anyway
|
||||
var/atom/movable/AM = atom_movable
|
||||
if(AM && AM.simulated) AM.ex_act(dist)
|
||||
|
||||
var/took = (world.timeofday-start)/10
|
||||
//You need to press the DebugGame verb to see these now....they were getting annoying and we've collected a fair bit of data. Just -test- changes to explosion code using this please so we can compare
|
||||
if(Debug2) world.log << "## DEBUG: Explosion([x0],[y0],[z0])(d[devastation_range],h[heavy_impact_range],l[light_impact_range]): Took [took] seconds."
|
||||
if(Debug2) world.log << "## DEBUG: Explosion([x0],[y0],[z0])(d[devastation_range],h[heavy_impact_range],l[light_impact_range]): Took [took] seconds."
|
||||
|
||||
//Machines which report explosions.
|
||||
for(var/i,i<=doppler_arrays.len,i++)
|
||||
var/obj/machinery/doppler_array/Array = doppler_arrays[i]
|
||||
if(Array)
|
||||
Array.sense_explosion(x0,y0,z0,devastation_range,heavy_impact_range,light_impact_range,took)
|
||||
|
||||
sleep(8)
|
||||
|
||||
if(!powernet_rebuild_was_deferred_already && defer_powernet_rebuild)
|
||||
makepowernets()
|
||||
defer_powernet_rebuild = 0
|
||||
|
||||
return 1
|
||||
|
||||
|
||||
|
||||
proc/secondaryexplosion(turf/epicenter, range)
|
||||
for(var/turf/tile in range(range, epicenter))
|
||||
tile.ex_act(2)
|
||||
tile.ex_act(2)
|
||||
@@ -1,3 +1,6 @@
|
||||
#define ZONE_BLOCKED 2
|
||||
#define AIR_BLOCKED 1
|
||||
|
||||
//Interactions
|
||||
/turf/simulated/wall/proc/toggle_open(var/mob/user)
|
||||
|
||||
@@ -8,7 +11,9 @@
|
||||
can_open = WALL_OPENING
|
||||
//flick("[material.icon_base]fwall_opening", src)
|
||||
density = 0
|
||||
blocks_air = ZONE_BLOCKED
|
||||
update_icon()
|
||||
update_air()
|
||||
set_light(0)
|
||||
src.blocks_air = 0
|
||||
set_opacity(0)
|
||||
@@ -18,7 +23,9 @@
|
||||
can_open = WALL_OPENING
|
||||
//flick("[material.icon_base]fwall_closing", src)
|
||||
density = 1
|
||||
blocks_air = AIR_BLOCKED
|
||||
update_icon()
|
||||
update_air()
|
||||
set_light(1)
|
||||
src.blocks_air = 1
|
||||
set_opacity(1)
|
||||
@@ -28,6 +35,25 @@
|
||||
can_open = WALL_CAN_OPEN
|
||||
update_icon()
|
||||
|
||||
#undef ZONE_BLOCKED
|
||||
#undef AIR_BLOCKED
|
||||
|
||||
/turf/simulated/wall/proc/update_air()
|
||||
if(!air_master)
|
||||
return
|
||||
|
||||
for(var/turf/simulated/turf in loc)
|
||||
update_thermal(turf)
|
||||
air_master.mark_for_update(turf)
|
||||
|
||||
|
||||
/turf/simulated/wall/proc/update_thermal(var/turf/simulated/source)
|
||||
if(istype(source))
|
||||
if(density && opacity)
|
||||
source.thermal_conductivity = WALL_HEAT_TRANSFER_COEFFICIENT
|
||||
else
|
||||
source.thermal_conductivity = initial(source.thermal_conductivity)
|
||||
|
||||
/turf/simulated/wall/proc/fail_smash(var/mob/user)
|
||||
user << "<span class='danger'>You smash against the wall!</span>"
|
||||
take_damage(rand(25,75))
|
||||
|
||||
Reference in New Issue
Block a user