mirror of
https://github.com/CHOMPStation2/CHOMPStation2.git
synced 2025-12-10 18:22:39 +00:00
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:
@@ -26,15 +26,17 @@ mob/living/simple_animal/slime/airflow_stun()
|
|||||||
return
|
return
|
||||||
|
|
||||||
mob/living/carbon/human/airflow_stun()
|
mob/living/carbon/human/airflow_stun()
|
||||||
if(shoes)
|
if(shoes && (shoes.item_flags & NOSLIP))
|
||||||
if(shoes.item_flags & NOSLIP) return 0
|
to_chat(src, "<span class='notice'>Air suddenly rushes past you!</span>")
|
||||||
|
return 0
|
||||||
..()
|
..()
|
||||||
|
|
||||||
atom/movable/proc/check_airflow_movable(n)
|
atom/movable/proc/check_airflow_movable(n)
|
||||||
|
if(!simulated) return 0
|
||||||
|
|
||||||
if(anchored && !ismob(src)) 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
|
return 1
|
||||||
|
|
||||||
@@ -50,15 +52,20 @@ mob/living/silicon/check_airflow_movable()
|
|||||||
return 0
|
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)
|
switch(w_class)
|
||||||
if(2)
|
if(ITEMSIZE_TINY,ITEMSIZE_SMALL)
|
||||||
if(n < vsc.airflow_lightest_pressure) return 0
|
if(n < vsc.airflow_lightest_pressure) return 0
|
||||||
if(3)
|
if(ITEMSIZE_NORMAL)
|
||||||
if(n < vsc.airflow_light_pressure) return 0
|
if(n < vsc.airflow_light_pressure) return 0
|
||||||
if(4,5)
|
if(ITEMSIZE_LARGE,ITEMSIZE_HUGE)
|
||||||
if(n < vsc.airflow_medium_pressure) return 0
|
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/turf/airflow_dest
|
||||||
/atom/movable/var/tmp/airflow_speed = 0
|
/atom/movable/var/tmp/airflow_speed = 0
|
||||||
@@ -78,116 +85,6 @@ obj/item/check_airflow_movable(n)
|
|||||||
return 0
|
return 0
|
||||||
return 1
|
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)
|
/atom/movable/Bump(atom/A)
|
||||||
if(airflow_speed > 0 && airflow_dest)
|
if(airflow_speed > 0 && airflow_dest)
|
||||||
airflow_hit(A)
|
airflow_hit(A)
|
||||||
|
|||||||
@@ -76,7 +76,8 @@ turf/c_airblock(turf/other)
|
|||||||
return AIR_BLOCKED
|
return AIR_BLOCKED
|
||||||
|
|
||||||
var/result = 0
|
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)
|
result |= M.c_airblock(other)
|
||||||
if(result == BLOCKED) return BLOCKED
|
if(result == BLOCKED) return BLOCKED
|
||||||
return result
|
return result
|
||||||
|
|||||||
163
code/controllers/subsystems/airflow.dm
Normal file
163
code/controllers/subsystems/airflow.dm
Normal file
@@ -0,0 +1,163 @@
|
|||||||
|
#define CLEAR_OBJECT(TARGET) \
|
||||||
|
processing -= TARGET; \
|
||||||
|
TARGET.airflow_dest = null; \
|
||||||
|
TARGET.airflow_speed = 0; \
|
||||||
|
TARGET.airflow_time = 0; \
|
||||||
|
TARGET.airflow_skip_speedcheck = FALSE; \
|
||||||
|
if (TARGET.airflow_od) { \
|
||||||
|
TARGET.density = 0; \
|
||||||
|
}
|
||||||
|
|
||||||
|
// No point in making this a processing substem, it overrides fire() and handles its own processing list!
|
||||||
|
SUBSYSTEM_DEF(airflow)
|
||||||
|
name = "Airflow"
|
||||||
|
wait = 2
|
||||||
|
flags = SS_NO_INIT
|
||||||
|
runlevels = RUNLEVEL_GAME | RUNLEVEL_POSTGAME
|
||||||
|
priority = 15
|
||||||
|
|
||||||
|
var/list/processing = list()
|
||||||
|
var/list/currentrun = list()
|
||||||
|
|
||||||
|
/datum/controller/subsystem/airflow/fire(resumed = FALSE)
|
||||||
|
if (!resumed)
|
||||||
|
currentrun = processing.Copy()
|
||||||
|
|
||||||
|
var/mywait = wait
|
||||||
|
var/list/curr = currentrun // Cache for sanic speed
|
||||||
|
while (curr.len)
|
||||||
|
var/atom/movable/target = curr[curr.len]
|
||||||
|
curr.len--
|
||||||
|
if(QDELETED(target))
|
||||||
|
processing -= target
|
||||||
|
if (MC_TICK_CHECK)
|
||||||
|
return
|
||||||
|
continue
|
||||||
|
|
||||||
|
if (target.airflow_speed <= 0)
|
||||||
|
CLEAR_OBJECT(target)
|
||||||
|
if (MC_TICK_CHECK)
|
||||||
|
return
|
||||||
|
continue
|
||||||
|
|
||||||
|
if (target.airflow_process_delay > 0)
|
||||||
|
target.airflow_process_delay -= mywait
|
||||||
|
if (MC_TICK_CHECK)
|
||||||
|
return
|
||||||
|
continue
|
||||||
|
else if (target.airflow_process_delay)
|
||||||
|
target.airflow_process_delay = 0
|
||||||
|
|
||||||
|
target.airflow_speed = min(target.airflow_speed, 15)
|
||||||
|
target.airflow_speed -= vsc.airflow_speed_decay
|
||||||
|
if (!target.airflow_skip_speedcheck)
|
||||||
|
if (target.airflow_speed > 7)
|
||||||
|
if (target.airflow_time++ >= target.airflow_speed - 7)
|
||||||
|
if (target.airflow_od)
|
||||||
|
target.density = 0
|
||||||
|
target.airflow_skip_speedcheck = TRUE
|
||||||
|
|
||||||
|
if (MC_TICK_CHECK)
|
||||||
|
return
|
||||||
|
continue
|
||||||
|
else
|
||||||
|
if (target.airflow_od)
|
||||||
|
target.density = 0
|
||||||
|
target.airflow_process_delay = max(1, 10 - (target.airflow_speed + 3))
|
||||||
|
target.airflow_skip_speedcheck = TRUE
|
||||||
|
|
||||||
|
if (MC_TICK_CHECK)
|
||||||
|
return
|
||||||
|
continue
|
||||||
|
|
||||||
|
target.airflow_skip_speedcheck = FALSE
|
||||||
|
|
||||||
|
if (target.airflow_od)
|
||||||
|
target.density = 1
|
||||||
|
|
||||||
|
if (!target.airflow_dest || target.loc == target.airflow_dest)
|
||||||
|
target.airflow_dest = locate(min(max(target.x + target.airflow_xo, 1), world.maxx), min(max(target.y + target.airflow_yo, 1), world.maxy), target.z)
|
||||||
|
|
||||||
|
if ((target.x == 1) || (target.x == world.maxx) || (target.y == 1) || (target.y == world.maxy))
|
||||||
|
CLEAR_OBJECT(target)
|
||||||
|
if (MC_TICK_CHECK)
|
||||||
|
return
|
||||||
|
continue
|
||||||
|
|
||||||
|
if (!isturf(target.loc))
|
||||||
|
CLEAR_OBJECT(target)
|
||||||
|
if (MC_TICK_CHECK)
|
||||||
|
return
|
||||||
|
continue
|
||||||
|
|
||||||
|
step_towards(target, target.airflow_dest)
|
||||||
|
var/mob/M = target
|
||||||
|
if (ismob(target) && M.client)
|
||||||
|
M.setMoveCooldown(vsc.airflow_mob_slowdown)
|
||||||
|
|
||||||
|
if (MC_TICK_CHECK)
|
||||||
|
return
|
||||||
|
|
||||||
|
#undef CLEAR_OBJECT
|
||||||
|
|
||||||
|
/atom/movable
|
||||||
|
var/tmp/airflow_xo
|
||||||
|
var/tmp/airflow_yo
|
||||||
|
var/tmp/airflow_od
|
||||||
|
var/tmp/airflow_process_delay
|
||||||
|
var/tmp/airflow_skip_speedcheck
|
||||||
|
|
||||||
|
/atom/movable/proc/prepare_airflow(n)
|
||||||
|
if (!airflow_dest || airflow_speed < 0 || last_airflow > world.time - vsc.airflow_delay)
|
||||||
|
return FALSE
|
||||||
|
if (airflow_speed)
|
||||||
|
airflow_speed = n / max(get_dist(src, airflow_dest), 1)
|
||||||
|
return FALSE
|
||||||
|
|
||||||
|
if (airflow_dest == loc)
|
||||||
|
step_away(src, loc)
|
||||||
|
|
||||||
|
if (!src.AirflowCanMove(n))
|
||||||
|
return FALSE
|
||||||
|
|
||||||
|
if (ismob(src))
|
||||||
|
to_chat(src,"<span class='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 FALSE
|
||||||
|
|
||||||
|
airflow_speed = min(max(n * (9 / airflow_falloff), 1), 9)
|
||||||
|
|
||||||
|
airflow_od = 0
|
||||||
|
|
||||||
|
if (!density)
|
||||||
|
density = 1
|
||||||
|
airflow_od = 1
|
||||||
|
|
||||||
|
return TRUE
|
||||||
|
|
||||||
|
/atom/movable/proc/GotoAirflowDest(n)
|
||||||
|
if (!prepare_airflow(n))
|
||||||
|
return
|
||||||
|
|
||||||
|
airflow_xo = airflow_dest.x - src.x
|
||||||
|
airflow_yo = airflow_dest.y - src.y
|
||||||
|
|
||||||
|
airflow_dest = null
|
||||||
|
|
||||||
|
SSairflow.processing += src
|
||||||
|
|
||||||
|
/atom/movable/proc/RepelAirflowDest(n)
|
||||||
|
if (!prepare_airflow(n))
|
||||||
|
return
|
||||||
|
|
||||||
|
airflow_xo = -(airflow_dest.x - src.x)
|
||||||
|
airflow_yo = -(airflow_dest.y - src.y)
|
||||||
|
|
||||||
|
airflow_dest = null
|
||||||
|
|
||||||
|
SSairflow.processing += src
|
||||||
@@ -173,6 +173,7 @@
|
|||||||
#include "code\controllers\ProcessScheduler\core\process.dm"
|
#include "code\controllers\ProcessScheduler\core\process.dm"
|
||||||
#include "code\controllers\ProcessScheduler\core\processScheduler.dm"
|
#include "code\controllers\ProcessScheduler\core\processScheduler.dm"
|
||||||
#include "code\controllers\subsystems\air.dm"
|
#include "code\controllers\subsystems\air.dm"
|
||||||
|
#include "code\controllers\subsystems\airflow.dm"
|
||||||
#include "code\controllers\subsystems\creation.dm"
|
#include "code\controllers\subsystems\creation.dm"
|
||||||
#include "code\controllers\subsystems\garbage.dm"
|
#include "code\controllers\subsystems\garbage.dm"
|
||||||
#include "code\controllers\subsystems\lighting.dm"
|
#include "code\controllers\subsystems\lighting.dm"
|
||||||
|
|||||||
Reference in New Issue
Block a user