Convert ZAS "Airflow" into a subsystem plus fixes

* Port of the "Airflow" portions of Yonaguni/EuropaStation#618
* The "airflow" part of ZAS used to be handled by a sleep'd loop.   This has the potential to bunch up and lag.  Switching to a StonedMC managed subsystem improves it.
* Fixed to ensure that zshadow mobs cannot be blown around by the wind no matter how fierce.
* Added a message to mobs informing them when their boots save them from being wind-thwapped.
* Check w_class on non-item objects if they have it defined (might as well since var/w_class is on /obj)
* Tiny optimization of c_airblock
This commit is contained in:
Leshana
2018-01-27 15:42:16 -05:00
parent 8e22707e24
commit 8c09d39ef1
4 changed files with 181 additions and 119 deletions

View File

@@ -26,15 +26,17 @@ mob/living/simple_animal/slime/airflow_stun()
return
mob/living/carbon/human/airflow_stun()
if(shoes)
if(shoes.item_flags & NOSLIP) return 0
if(shoes && (shoes.item_flags & NOSLIP))
to_chat(src, "<span class='notice'>Air suddenly rushes past you!</span>")
return 0
..()
atom/movable/proc/check_airflow_movable(n)
if(!simulated) return 0
if(anchored && !ismob(src)) return 0
if(!istype(src,/obj/item) && n < vsc.airflow_dense_pressure) return 0
if(!isobj(src) && n < vsc.airflow_dense_pressure) return 0
return 1
@@ -50,15 +52,20 @@ mob/living/silicon/check_airflow_movable()
return 0
obj/item/check_airflow_movable(n)
. = ..()
obj/check_airflow_movable(n)
if (!(. = ..()))
return 0
if(isnull(w_class))
if(n < vsc.airflow_dense_pressure) return 0 //most non-item objs don't have a w_class yet
switch(w_class)
if(2)
if(ITEMSIZE_TINY,ITEMSIZE_SMALL)
if(n < vsc.airflow_lightest_pressure) return 0
if(3)
if(ITEMSIZE_NORMAL)
if(n < vsc.airflow_light_pressure) return 0
if(4,5)
if(ITEMSIZE_LARGE,ITEMSIZE_HUGE)
if(n < vsc.airflow_medium_pressure) return 0
else
if(n < vsc.airflow_dense_pressure) return 0
/atom/movable/var/tmp/turf/airflow_dest
/atom/movable/var/tmp/airflow_speed = 0
@@ -78,116 +85,6 @@ obj/item/check_airflow_movable(n)
return 0
return 1
/atom/movable/proc/GotoAirflowDest(n)
if(!airflow_dest) return
if(airflow_speed < 0) return
if(last_airflow > world.time - vsc.airflow_delay) return
if(airflow_speed)
airflow_speed = n/max(get_dist(src,airflow_dest),1)
return
if(airflow_dest == loc)
step_away(src,loc)
if(!src.AirflowCanMove(n))
return
if(ismob(src))
src << "<span class='danger'>You are sucked away by airflow!</span>"
last_airflow = world.time
var/airflow_falloff = 9 - sqrt((x - airflow_dest.x) ** 2 + (y - airflow_dest.y) ** 2)
if(airflow_falloff < 1)
airflow_dest = null
return
airflow_speed = min(max(n * (9/airflow_falloff),1),9)
var
xo = airflow_dest.x - src.x
yo = airflow_dest.y - src.y
od = 0
airflow_dest = null
if(!density)
density = 1
od = 1
while(airflow_speed > 0)
if(airflow_speed <= 0) break
airflow_speed = min(airflow_speed,15)
airflow_speed -= vsc.airflow_speed_decay
if(airflow_speed > 7)
if(airflow_time++ >= airflow_speed - 7)
if(od)
density = 0
sleep(1 * tick_multiplier)
else
if(od)
density = 0
sleep(max(1,10-(airflow_speed+3)) * tick_multiplier)
if(od)
density = 1
if ((!( src.airflow_dest ) || src.loc == src.airflow_dest))
src.airflow_dest = locate(min(max(src.x + xo, 1), world.maxx), min(max(src.y + yo, 1), world.maxy), src.z)
if ((src.x == 1 || src.x == world.maxx || src.y == 1 || src.y == world.maxy))
break
if(!istype(loc, /turf))
break
step_towards(src, src.airflow_dest)
var/mob/M = src
if(istype(M) && M.client)
M.setMoveCooldown(vsc.airflow_mob_slowdown)
airflow_dest = null
airflow_speed = 0
airflow_time = 0
if(od)
density = 0
/atom/movable/proc/RepelAirflowDest(n)
if(!airflow_dest) return
if(airflow_speed < 0) return
if(last_airflow > world.time - vsc.airflow_delay) return
if(airflow_speed)
airflow_speed = n/max(get_dist(src,airflow_dest),1)
return
if(airflow_dest == loc)
step_away(src,loc)
if(!src.AirflowCanMove(n))
return
if(ismob(src))
src << "<span clas='danger'>You are pushed away by airflow!</span>"
last_airflow = world.time
var/airflow_falloff = 9 - sqrt((x - airflow_dest.x) ** 2 + (y - airflow_dest.y) ** 2)
if(airflow_falloff < 1)
airflow_dest = null
return
airflow_speed = min(max(n * (9/airflow_falloff),1),9)
var
xo = -(airflow_dest.x - src.x)
yo = -(airflow_dest.y - src.y)
od = 0
airflow_dest = null
if(!density)
density = 1
od = 1
while(airflow_speed > 0)
if(airflow_speed <= 0) return
airflow_speed = min(airflow_speed,15)
airflow_speed -= vsc.airflow_speed_decay
if(airflow_speed > 7)
if(airflow_time++ >= airflow_speed - 7)
sleep(1 * tick_multiplier)
else
sleep(max(1,10-(airflow_speed+3)) * tick_multiplier)
if ((!( src.airflow_dest ) || src.loc == src.airflow_dest))
src.airflow_dest = locate(min(max(src.x + xo, 1), world.maxx), min(max(src.y + yo, 1), world.maxy), src.z)
if ((src.x == 1 || src.x == world.maxx || src.y == 1 || src.y == world.maxy))
return
if(!istype(loc, /turf))
return
step_towards(src, src.airflow_dest)
if(ismob(src) && src:client)
src:client:move_delay = world.time + vsc.airflow_mob_slowdown
airflow_dest = null
airflow_speed = 0
airflow_time = 0
if(od)
density = 0
/atom/movable/Bump(atom/A)
if(airflow_speed > 0 && airflow_dest)
airflow_hit(A)

View File

@@ -76,7 +76,8 @@ turf/c_airblock(turf/other)
return AIR_BLOCKED
var/result = 0
for(var/atom/movable/M in contents)
for(var/mm in contents)
var/atom/movable/M = mm
result |= M.c_airblock(other)
if(result == BLOCKED) return BLOCKED
return result