mirror of
https://github.com/vgstation-coders/vgstation13.git
synced 2025-12-10 02:16:05 +00:00
WHOOPS
Signed-off-by: unknown <Colm@Blue.(none)>
This commit is contained in:
587
code/ZAS/Airflow.dm
Normal file
587
code/ZAS/Airflow.dm
Normal file
@@ -0,0 +1,587 @@
|
||||
/*
|
||||
|
||||
CONTAINS:
|
||||
All AirflowX() procs, all Variable Setting Controls for airflow, save/load variable tweaks for airflow.
|
||||
|
||||
VARIABLES:
|
||||
|
||||
atom/movable/airflow_dest
|
||||
The destination turf of a flying object.
|
||||
|
||||
atom/movable/airflow_speed
|
||||
The speed (1-15) at which a flying object is traveling to airflow_dest. Decays over time.
|
||||
|
||||
|
||||
CALLABLE PROCS:
|
||||
|
||||
AirflowRepel(turf/T, n, per)
|
||||
Causes objects to fly away from a point within a single zone.
|
||||
Called manually by air releasers. T is the location of the expanding gas.
|
||||
n is the pressure released. per indicates that n is a percent value if nonzero.
|
||||
RETURNS: Null
|
||||
|
||||
AirflowAttract(turf/T, n, per)
|
||||
Causes objects to fly to a point within a single zone.
|
||||
Called manually by air consumers. T is the location of the attractor.
|
||||
n is the pressure consumed. per indicates that n is a percent value if nonzero.
|
||||
RETURNS: Null
|
||||
|
||||
|
||||
OVERLOADABLE PROCS:
|
||||
|
||||
mob/airflow_stun()
|
||||
Contains checks for and results of being stunned by airflow.
|
||||
Called when airflow quantities exceed AF_HUMAN_STUN_THRESHOLD.
|
||||
RETURNS: Null
|
||||
|
||||
atom/movable/check_airflow_movable(n)
|
||||
Contains checks for moving any object due to airflow.
|
||||
n is the percent of 1 Atmosphere that is flowing.
|
||||
RETURNS: 1 if the object moves under the air conditions, 0 if it stays put.
|
||||
|
||||
atom/movable/airflow_hit(atom/A)
|
||||
Contains results of hitting a solid object (A) due to airflow.
|
||||
A is the dense object hit.
|
||||
Use airflow_speed to determine how fast the projectile was going.
|
||||
|
||||
|
||||
AUTOMATIC PROCS:
|
||||
|
||||
Airflow(zone/A, zone/B, n)
|
||||
Causes objects to fly along a pressure gradient.
|
||||
Called by zone updates. A and B are two connected zones.
|
||||
n is the pressure difference between them.
|
||||
|
||||
AirflowSpace(zone/A)
|
||||
Causes objects to fly into space.
|
||||
Called by zone updates. A is a zone connected to space.
|
||||
|
||||
atom/movable/GotoAirflowDest(n)
|
||||
atom/movable/RepelAirflowDest(n)
|
||||
Called by main airflow procs to cause the object to fly to or away from destination at speed n.
|
||||
Probably shouldn't call this directly unless you know what you're
|
||||
doing and have set airflow_dest. airflow_hit() will be called if the object collides with an obstacle.
|
||||
|
||||
*/
|
||||
|
||||
var/tick_multiplier = 2
|
||||
vs_control/var
|
||||
|
||||
zone_update_delay = 10
|
||||
zone_update_delay_NAME = "Zone Update Delay"
|
||||
zone_update_delay_DESC = "The delay in ticks between updates of zones. Increase if lag is bad seemingly because of air."
|
||||
|
||||
zone_share_percent = 2
|
||||
zone_share_percent_NAME = "Zone Connection Transfer %"
|
||||
zone_share_percent_DESC = "Percent of gas per connected tile that is shared between zones."
|
||||
|
||||
//Used in /mob/carbon/human/life
|
||||
OXYGEN_LOSS = 2
|
||||
OXYGEN_LOSS_NAME = "Damage - Oxygen Loss"
|
||||
OXYGEN_LOSS_DESC = "A multiplier for damage due to lack of air, CO2 poisoning, and vacuum. Does not affect oxyloss\
|
||||
from being incapacitated or dying."
|
||||
TEMP_DMG = 2
|
||||
TEMP_DMG_NAME = "Damage - Temperature"
|
||||
TEMP_DMG_DESC = "A multiplier for damage due to body temperature irregularities."
|
||||
BURN_DMG = 6
|
||||
BURN_DMG_NAME = "Damage - Fire"
|
||||
BURN_DMG_DESC = "A multiplier for damage due to direct fire exposure."
|
||||
|
||||
AF_TINY_MOVEMENT_THRESHOLD = 50 //% difference to move tiny items.
|
||||
AF_TINY_MOVEMENT_THRESHOLD_NAME = "Airflow - Tiny Movement Threshold %"
|
||||
AF_TINY_MOVEMENT_THRESHOLD_DESC = "Percent of 1 Atm. at which items with the tiny weight class will move."
|
||||
AF_SMALL_MOVEMENT_THRESHOLD = 70 //% difference to move small items.
|
||||
AF_SMALL_MOVEMENT_THRESHOLD_NAME = "Airflow - Small Movement Threshold %"
|
||||
AF_SMALL_MOVEMENT_THRESHOLD_DESC = "Percent of 1 Atm. at which items with the small weight class will move."
|
||||
AF_NORMAL_MOVEMENT_THRESHOLD = 90 //% difference to move normal items.
|
||||
AF_NORMAL_MOVEMENT_THRESHOLD_NAME = "Airflow - Normal Movement Threshold %"
|
||||
AF_NORMAL_MOVEMENT_THRESHOLD_DESC = "Percent of 1 Atm. at which items with the normal weight class will move."
|
||||
AF_LARGE_MOVEMENT_THRESHOLD = 100 //% difference to move large and huge items.
|
||||
AF_LARGE_MOVEMENT_THRESHOLD_NAME = "Airflow - Large Movement Threshold %"
|
||||
AF_LARGE_MOVEMENT_THRESHOLD_DESC = "Percent of 1 Atm. at which items with the large or huge weight class will move."
|
||||
AF_DENSE_MOVEMENT_THRESHOLD = 120 //% difference to move dense crap and mobs.
|
||||
AF_DENSE_MOVEMENT_THRESHOLD_NAME = "Airflow - Dense Movement Threshold %"
|
||||
AF_DENSE_MOVEMENT_THRESHOLD_DESC = "Percent of 1 Atm. at which dense objects (canisters, etc.) will be shifted by airflow."
|
||||
AF_MOB_MOVEMENT_THRESHOLD = 175
|
||||
AF_MOB_MOVEMENT_THRESHOLD_NAME = "Airflow - Human Movement Threshold %"
|
||||
AF_MOB_MOVEMENT_THRESHOLD_DESC = "Percent of 1 Atm. at which mobs will be shifted by airflow."
|
||||
|
||||
AF_HUMAN_STUN_THRESHOLD = 130
|
||||
AF_HUMAN_STUN_THRESHOLD_NAME = "Airflow - Human Stun Threshold %"
|
||||
AF_HUMAN_STUN_THRESHOLD_DESC = "Percent of 1 Atm. at which living things are stunned or knocked over."
|
||||
|
||||
AF_PERCENT_OF = ONE_ATMOSPHERE
|
||||
AF_PERCENT_OF_NAME = "Airflow - 100% Pressure"
|
||||
AF_PERCENT_OF_DESC = "Normally set to 1 Atm. in kPa, this indicates what pressure is considered 100% by the system."
|
||||
|
||||
AF_SPEED_MULTIPLIER = 4 //airspeed per movement threshold value crossed.
|
||||
AF_SPEED_MULTIPLIER_NAME = "Airflow - Speed Increase per 10%"
|
||||
AF_SPEED_MULTIPLIER_DESC = "Velocity increase of shifted items per 10% of airflow."
|
||||
AF_DAMAGE_MULTIPLIER = 5 //Amount of damage applied per airflow_speed.
|
||||
AF_DAMAGE_MULTIPLIER_NAME = "Airflow - Damage Per Velocity"
|
||||
AF_DAMAGE_MULTIPLIER_DESC = "Amount of damage applied per unit of speed (1-15 units) at which mobs are thrown."
|
||||
AF_STUN_MULTIPLIER = 1.5 //Seconds of stun applied per airflow_speed.
|
||||
AF_STUN_MULTIPLIER_NAME = "Airflow - Stun Per Velocity"
|
||||
AF_STUN_MULTIPLIER_DESC = "Amount of stun effect applied per unit of speed (1-15 units) at which mobs are thrown."
|
||||
AF_SPEED_DECAY = 0.5 //Amount that flow speed will decay with time.
|
||||
AF_SPEED_DECAY_NAME = "Airflow - Velocity Lost per Tick"
|
||||
AF_SPEED_DECAY_DESC = "Amount of airflow speed lost per tick on a moving object."
|
||||
AF_SPACE_MULTIPLIER = 2 //Increasing this will make space connections more DRAMATIC!
|
||||
AF_SPACE_MULTIPLIER_NAME = "Airflow - Space Airflow Multiplier"
|
||||
AF_SPACE_MULTIPLIER_DESC = "Increasing this multiplier will cause more powerful airflow to space."
|
||||
AF_CANISTER_MULTIPLIER = 0.25
|
||||
AF_CANISTER_MULTIPLIER_NAME = "Airflow - Canister Airflow Multiplier"
|
||||
AF_CANISTER_MULTIPLIER_DESC = "Increasing this multiplier will cause more powerful airflow from single-tile sources like canisters."
|
||||
|
||||
mob/proc
|
||||
Change_Airflow_Constants()
|
||||
set category = "Debug"
|
||||
|
||||
var/choice = input("Which constant will you modify?","Change Airflow Constants")\
|
||||
as null|anything in list("Movement Threshold","Speed Multiplier","Damage Multiplier","Stun Multiplier","Speed Decay")
|
||||
|
||||
var/n
|
||||
|
||||
switch(choice)
|
||||
if("Movement Threshold")
|
||||
n = input("What will you change it to","Change Airflow Constants",vsc.AF_DENSE_MOVEMENT_THRESHOLD) as num
|
||||
n = max(1,n)
|
||||
vsc.AF_DENSE_MOVEMENT_THRESHOLD = n
|
||||
world.log << "vsc.AF_DENSE_MOVEMENT_THRESHOLD set to [n]."
|
||||
if("Speed Multiplier")
|
||||
n = input("What will you change it to","Change Airflow Constants",vsc.AF_SPEED_MULTIPLIER) as num
|
||||
n = max(1,n)
|
||||
vsc.AF_SPEED_MULTIPLIER = n
|
||||
world.log << "vsc.AF_SPEED_MULTIPLIER set to [n]."
|
||||
if("Damage Multiplier")
|
||||
n = input("What will you change it to","Change Airflow Constants",vsc.AF_DAMAGE_MULTIPLIER) as num
|
||||
vsc.AF_DAMAGE_MULTIPLIER = n
|
||||
world.log << "AF_DAMAGE_MULTIPLIER set to [n]."
|
||||
if("Stun Multiplier")
|
||||
n = input("What will you change it to","Change Airflow Constants",vsc.AF_STUN_MULTIPLIER) as num
|
||||
vsc.AF_STUN_MULTIPLIER = n
|
||||
world.log << "AF_STUN_MULTIPLIER set to [n]."
|
||||
if("Speed Decay")
|
||||
n = input("What will you change it to","Change Airflow Constants",vsc.AF_SPEED_DECAY) as num
|
||||
vsc.AF_SPEED_DECAY = n
|
||||
world.log << "AF_SPEED_DECAY set to [n]."
|
||||
if("Space Flow Multiplier")
|
||||
n = input("What will you change it to","Change Airflow Constants",vsc.AF_SPEED_DECAY) as num
|
||||
vsc.AF_SPEED_DECAY = n
|
||||
world.log << "AF_SPEED_DECAY set to [n]."
|
||||
|
||||
|
||||
//The main airflow code. Called by zone updates.
|
||||
//Zones A and B are air zones. n represents the amount of air moved.
|
||||
|
||||
mob/proc/airflow_stun()
|
||||
if(weakened <= 0) src << "\red The sudden rush of air knocks you over!"
|
||||
weakened = max(weakened,5)
|
||||
|
||||
mob/living/silicon/airflow_stun()
|
||||
return
|
||||
|
||||
mob/living/carbon/metroid/airflow_stun()
|
||||
return
|
||||
|
||||
mob/living/carbon/human/airflow_stun()
|
||||
if(buckled) return 0
|
||||
if(wear_suit)
|
||||
if(wear_suit.flags & SUITSPACE) return 0
|
||||
if(shoes)
|
||||
if(shoes.flags & NOSLIP) return 0
|
||||
if(weakened <= 0) src << "\red The sudden rush of air knocks you over!"
|
||||
weakened = max(weakened,2)
|
||||
|
||||
atom/movable/proc/check_airflow_movable(n)
|
||||
|
||||
if(anchored && !ismob(src)) return 0
|
||||
|
||||
if(!istype(src,/obj/item) && n < vsc.AF_DENSE_MOVEMENT_THRESHOLD) return 0
|
||||
if(ismob(src) && n < vsc.AF_MOB_MOVEMENT_THRESHOLD) return 0
|
||||
|
||||
return 1
|
||||
|
||||
mob/dead/observer/check_airflow_movable()
|
||||
return 0
|
||||
|
||||
mob/living/silicon/check_airflow_movable()
|
||||
return 0
|
||||
|
||||
|
||||
obj/item/check_airflow_movable(n)
|
||||
. = ..()
|
||||
switch(w_class)
|
||||
if(2)
|
||||
if(n < vsc.AF_SMALL_MOVEMENT_THRESHOLD) return 0
|
||||
if(3)
|
||||
if(n < vsc.AF_NORMAL_MOVEMENT_THRESHOLD) return 0
|
||||
if(4,5)
|
||||
if(n < vsc.AF_LARGE_MOVEMENT_THRESHOLD) return 0
|
||||
|
||||
proc/Airflow(zone/A,zone/B,n)
|
||||
|
||||
//Now n is a percent of one atm.
|
||||
n = round((n/vsc.AF_PERCENT_OF)*100,0.1)
|
||||
|
||||
//Don't go any further if n is lower than the lowest value needed for airflow.
|
||||
if(abs(n) < vsc.AF_TINY_MOVEMENT_THRESHOLD) return
|
||||
|
||||
//These turfs are the midway point between A and B, and will be the destination point for thrown objects.
|
||||
var/list/connected_turfs = A.connections[B]
|
||||
|
||||
//Get lists of things that can be thrown across the room for each zone.
|
||||
var/list/pplz = A.movables()
|
||||
var/list/otherpplz = B.movables()
|
||||
|
||||
for(var/atom/movable/M in pplz)
|
||||
|
||||
//Check for knocking people over
|
||||
if(ismob(M) && n > vsc.AF_HUMAN_STUN_THRESHOLD)
|
||||
if(M:nodamage) continue
|
||||
M:airflow_stun()
|
||||
|
||||
if(M.check_airflow_movable(n))
|
||||
|
||||
//Check for things that are in range of the midpoint turfs.
|
||||
var/fail = 1
|
||||
for(var/turf/U in connected_turfs)
|
||||
if(M in range(U)) fail = 0
|
||||
if(fail) continue
|
||||
|
||||
//If they're already being tossed, don't do it again.
|
||||
if(!M.airflow_speed)
|
||||
|
||||
M.airflow_dest = pick(connected_turfs) //Pick a random midpoint to fly towards.
|
||||
|
||||
spawn M.GotoAirflowDest(abs(n) * (vsc.AF_SPEED_MULTIPLIER/10))
|
||||
//Send the object flying at a speed determined by n and AF_SPEED_MULTIPLIER.
|
||||
|
||||
//Do it again for the stuff in the other zone, making it fly away.
|
||||
for(var/atom/movable/M in otherpplz)
|
||||
|
||||
if(ismob(M) && abs(n) > vsc.AF_HUMAN_STUN_THRESHOLD)
|
||||
if(M:nodamage) continue
|
||||
M:airflow_stun()
|
||||
|
||||
if(M.check_airflow_movable(abs(n)))
|
||||
|
||||
var/fail = 1
|
||||
for(var/turf/U in connected_turfs)
|
||||
if(M in range(U)) fail = 0
|
||||
if(fail) continue
|
||||
|
||||
if(M && !M.airflow_speed)
|
||||
|
||||
M.airflow_dest = pick(connected_turfs)
|
||||
|
||||
spawn M.RepelAirflowDest(abs(n) * (vsc.AF_SPEED_MULTIPLIER/10))
|
||||
|
||||
proc/AirflowSpace(zone/A)
|
||||
|
||||
//The space version of the Airflow(A,B,n) proc.
|
||||
|
||||
var/n = (A.air.oxygen + A.air.nitrogen + A.air.carbon_dioxide)*vsc.AF_SPACE_MULTIPLIER
|
||||
//Here, n is determined by the space multiplier constant and the zone's air.
|
||||
|
||||
n = round((n/vsc.AF_PERCENT_OF)*100,0.1)
|
||||
|
||||
if(n < vsc.AF_TINY_MOVEMENT_THRESHOLD) return
|
||||
|
||||
var/list/connected_turfs = A.space_tiles //The midpoints are now all the space connections.
|
||||
var/list/pplz = A.movables() //We only need to worry about things in the zone, not things in space.
|
||||
|
||||
for(var/atom/movable/M in pplz)
|
||||
|
||||
if(ismob(M) && n > vsc.AF_HUMAN_STUN_THRESHOLD)
|
||||
if(M:nodamage) continue
|
||||
M:airflow_stun()
|
||||
|
||||
if(M.check_airflow_movable(n))
|
||||
|
||||
var/fail = 1
|
||||
for(var/turf/U in connected_turfs)
|
||||
if(M in range(U)) fail = 0
|
||||
if(fail) continue
|
||||
|
||||
if(!M.airflow_speed)
|
||||
M.airflow_dest = pick(connected_turfs)
|
||||
spawn
|
||||
if(M) M.GotoAirflowDest(n * (vsc.AF_SPEED_MULTIPLIER/10))
|
||||
//Sometimes shit breaks, and M isn't there after the spawn.
|
||||
|
||||
proc/AirflowRepel(turf/T,n,per = 0)
|
||||
|
||||
//This one is used for air escaping from canisters.
|
||||
var/zone/A = T.zone
|
||||
if(!A) return
|
||||
|
||||
n *= vsc.AF_CANISTER_MULTIPLIER
|
||||
|
||||
if(!per)
|
||||
n = round((n/vsc.AF_PERCENT_OF) * 100,0.1)
|
||||
|
||||
if(n < 0) return
|
||||
if(abs(n) > vsc.AF_TINY_MOVEMENT_THRESHOLD)
|
||||
|
||||
var/list/pplz = A.movables()
|
||||
|
||||
for(var/atom/movable/M in pplz)
|
||||
var/relative_n = n / max(1,get_dist(T,M)/2)
|
||||
if(ismob(M) && relative_n > vsc.AF_HUMAN_STUN_THRESHOLD)
|
||||
if(M:nodamage) continue
|
||||
M:airflow_stun()
|
||||
|
||||
if(M.check_airflow_movable(relative_n))
|
||||
|
||||
if(!(M in range(T))) continue //Recall that T is the center of the repelling force.
|
||||
|
||||
if(!M.airflow_speed)
|
||||
M.airflow_dest = T
|
||||
spawn M.RepelAirflowDest(relative_n * (vsc.AF_SPEED_MULTIPLIER/10))
|
||||
|
||||
proc/AirflowAttract(turf/T,n,per=0)
|
||||
|
||||
//Same as above, but attracts objects to the target.
|
||||
|
||||
var/zone/A = T.zone
|
||||
if(!A) return
|
||||
|
||||
n *= vsc.AF_CANISTER_MULTIPLIER
|
||||
|
||||
if(!per)
|
||||
n = round((n/vsc.AF_PERCENT_OF) * 100,0.1)
|
||||
|
||||
if(n < 0) return
|
||||
if(abs(n) > vsc.AF_TINY_MOVEMENT_THRESHOLD)
|
||||
//world << "Airflow!"
|
||||
var/list/pplz = A.movables()
|
||||
for(var/atom/movable/M in pplz)
|
||||
//world << "[M] / \..."
|
||||
|
||||
var/relative_n = n / max(1,get_dist(T,M)/2)
|
||||
|
||||
if(ismob(M) && relative_n > vsc.AF_HUMAN_STUN_THRESHOLD)
|
||||
if(M:nodamage) continue
|
||||
M:airflow_stun()
|
||||
|
||||
if(M.check_airflow_movable(relative_n))
|
||||
|
||||
if(!(M in range(T))) continue
|
||||
|
||||
if(!M.airflow_speed)
|
||||
M.airflow_dest = T
|
||||
spawn M.GotoAirflowDest(relative_n * (vsc.AF_SPEED_MULTIPLIER/10))
|
||||
|
||||
atom/movable
|
||||
var/turf/airflow_dest
|
||||
var/airflow_speed = 0
|
||||
var/airflow_time = 0
|
||||
|
||||
proc/GotoAirflowDest(n)
|
||||
if(!airflow_dest) return
|
||||
if(airflow_speed < 0) return
|
||||
if(airflow_speed)
|
||||
airflow_speed = n
|
||||
return
|
||||
if(airflow_dest == loc)
|
||||
step_away(src,loc)
|
||||
if(ismob(src))
|
||||
if(src:nodamage) return
|
||||
if(istype(src, /mob/living/carbon/human))
|
||||
if(istype(src, /mob/living/carbon/human))
|
||||
if(src:buckled) return
|
||||
if(src:wear_suit)
|
||||
if(src:wear_suit.flags & SUITSPACE) return
|
||||
if(src:shoes)
|
||||
if(src:shoes.type == /obj/item/clothing/shoes/magboots) return
|
||||
src << "\red You are sucked away by airflow!"
|
||||
airflow_speed = min(round(n),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.AF_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
|
||||
step_towards(src, src.airflow_dest)
|
||||
if(ismob(src) && src:client) src:client:move_delay = world.time + 10
|
||||
airflow_dest = null
|
||||
airflow_speed = -1
|
||||
spawn(150 * tick_multiplier) airflow_speed = 0
|
||||
if(od)
|
||||
density = 0
|
||||
|
||||
proc/RepelAirflowDest(n)
|
||||
if(!airflow_dest) return
|
||||
if(airflow_speed < 0) return
|
||||
if(airflow_speed)
|
||||
airflow_speed = n
|
||||
return
|
||||
if(airflow_dest == loc)
|
||||
step_away(src,loc)
|
||||
if(ismob(src))
|
||||
if(src:nodamage) return
|
||||
if(istype(src, /mob/living/carbon/human))
|
||||
if(istype(src, /mob/living/carbon/human))
|
||||
if(src:buckled) return
|
||||
if(src:wear_suit)
|
||||
if(src:wear_suit.flags & SUITSPACE) return
|
||||
if(src:shoes)
|
||||
if(src:shoes.type == /obj/item/clothing/shoes/magboots) return
|
||||
src << "\red You are pushed away by airflow!"
|
||||
airflow_speed = min(round(n),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.AF_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
|
||||
step_towards(src, src.airflow_dest)
|
||||
if(ismob(src) && src:client) src:client:move_delay = world.time + 10
|
||||
airflow_dest = null
|
||||
airflow_speed = -1
|
||||
spawn(150 * tick_multiplier) airflow_speed = 0
|
||||
if(od)
|
||||
density = 0
|
||||
|
||||
Bump(atom/A)
|
||||
if(airflow_speed > 0 && airflow_dest)
|
||||
airflow_hit(A)
|
||||
else
|
||||
airflow_speed = 0
|
||||
. = ..()
|
||||
|
||||
atom/movable/proc/airflow_hit(atom/A)
|
||||
airflow_speed = -1
|
||||
spawn(50 * tick_multiplier) airflow_speed = 0
|
||||
airflow_dest = null
|
||||
|
||||
mob/airflow_hit(atom/A)
|
||||
for(var/mob/M in hearers(src))
|
||||
M.show_message("\red <B>[src] slams into [A]!</B>",1,"\red You hear a loud slam!",2)
|
||||
playsound(src.loc, "smash.ogg", 25, 1, -1)
|
||||
. = ..()
|
||||
|
||||
obj/airflow_hit(atom/A)
|
||||
for(var/mob/M in hearers(src))
|
||||
M.show_message("\red <B>[src] slams into [A]!</B>",1,"\red You hear a loud slam!",2)
|
||||
playsound(src.loc, "smash.ogg", 25, 1, -1)
|
||||
. = ..()
|
||||
|
||||
obj/item/airflow_hit(atom/A)
|
||||
airflow_speed = -1
|
||||
spawn(50 * tick_multiplier) airflow_speed = 0
|
||||
airflow_dest = null
|
||||
|
||||
mob/living/carbon/human/airflow_hit(atom/A)
|
||||
for(var/mob/M in hearers(src))
|
||||
M.show_message("\red <B>[src] slams into [A]!</B>",1,"\red You hear a loud slam!",2)
|
||||
playsound(src.loc, "punch", 25, 1, -1)
|
||||
loc:add_blood(src)
|
||||
if (src.wear_suit)
|
||||
src.wear_suit.add_blood(src)
|
||||
if (src.w_uniform)
|
||||
src.w_uniform.add_blood(src)
|
||||
var/b_loss = airflow_speed * vsc.AF_DAMAGE_MULTIPLIER
|
||||
for(var/organ in src:organs)
|
||||
var/datum/organ/external/temp = src:organs["[organ]"]
|
||||
if (istype(temp, /datum/organ/external))
|
||||
switch(temp.name)
|
||||
if("head")
|
||||
temp.take_damage(b_loss * 0.2, 0)
|
||||
if("chest")
|
||||
temp.take_damage(b_loss * 0.4, 0)
|
||||
if("diaper")
|
||||
temp.take_damage(b_loss * 0.1, 0)
|
||||
spawn UpdateDamageIcon()
|
||||
if(airflow_speed > 10)
|
||||
paralysis += round(airflow_speed * vsc.AF_STUN_MULTIPLIER)
|
||||
stunned = max(stunned,paralysis + 3)
|
||||
else
|
||||
stunned += round(airflow_speed * vsc.AF_STUN_MULTIPLIER/2)
|
||||
. = ..()
|
||||
|
||||
zone/proc/movables()
|
||||
. = list()
|
||||
for(var/turf/T in contents)
|
||||
for(var/atom/A in T)
|
||||
. += A
|
||||
|
||||
proc/Get_Dir(atom/S,atom/T) //Shamelessly stolen from AJX.AdvancedGetDir
|
||||
var/GDist=get_dist(S,T)
|
||||
var/GDir=get_dir(S,T)
|
||||
if(GDist<=3)
|
||||
if(GDist==0) return 0
|
||||
if(GDist==1)
|
||||
return GDir
|
||||
|
||||
|
||||
var/X1=S.x*10
|
||||
var/X2=T.x*10
|
||||
var/Y1=S.y*10
|
||||
var/Y2=T.y*10
|
||||
var/Ref
|
||||
if(GDir==NORTHEAST)
|
||||
Ref=(X2/X1)*Y1
|
||||
if(Ref-1>Y2) .=EAST
|
||||
else if(Ref+1<Y2) .=NORTH
|
||||
else .=NORTHEAST
|
||||
else if(GDir==NORTHWEST)
|
||||
Ref=(1+((1-(X2/X1))))*Y1
|
||||
if(Ref-1>Y2) .=WEST
|
||||
else if(Ref+1<Y2) .=NORTH
|
||||
else .=NORTHWEST
|
||||
else if(GDir==SOUTHEAST)
|
||||
Ref=(1-((X2/X1)-1))*Y1
|
||||
if(Ref-1>Y2) .=SOUTH
|
||||
else if(Ref+1<Y2) .=EAST
|
||||
else .=SOUTHEAST
|
||||
else if(GDir==SOUTHWEST)
|
||||
Ref=(X2/X1)*Y1
|
||||
if(Ref-1>Y2) .=SOUTH
|
||||
else if(Ref+1<Y2) .=WEST
|
||||
else .=SOUTHWEST
|
||||
else
|
||||
return GDir
|
||||
|
||||
proc/SaveTweaks()
|
||||
var/savefile/F = new("data/game_settings.sav")
|
||||
F << vsc
|
||||
del F
|
||||
world.log << "TWEAKS: Airflow, Plasma and Damage settings saved."
|
||||
proc/LoadTweaks()
|
||||
if(fexists("data/game_settings.sav"))
|
||||
var/savefile/F = new("data/game_settings.sav")
|
||||
F >> vsc
|
||||
del F
|
||||
world.log << "TWEAKS: Airflow, Plasma and Damage settings loaded."
|
||||
61
code/ZAS/Connection.dm
Normal file
61
code/ZAS/Connection.dm
Normal file
@@ -0,0 +1,61 @@
|
||||
connection
|
||||
var
|
||||
turf //The turfs involved in the connection.
|
||||
A
|
||||
B
|
||||
indirect = 0 //If the connection is purely indirect, the zones should not join.
|
||||
last_updated //The tick at which this was last updated.
|
||||
New(turf/T,turf/O)
|
||||
A = T
|
||||
B = O
|
||||
if(A.zone)
|
||||
if(!A.zone.connections) A.zone.connections = new()
|
||||
A.zone.connections += src
|
||||
if(B.zone)
|
||||
if(!B.zone.connections) B.zone.connections = new()
|
||||
B.zone.connections += src
|
||||
if(A.zone && B.zone)
|
||||
if(!A.zone.connected_zones)
|
||||
A.zone.connected_zones = list()
|
||||
if(!B.zone.connected_zones)
|
||||
B.zone.connected_zones = list()
|
||||
|
||||
if(!(B.zone in A.zone.connected_zones))
|
||||
A.zone.connected_zones += B.zone
|
||||
A.zone.connected_zones[B.zone] = 1
|
||||
else
|
||||
A.zone.connected_zones[B.zone]++
|
||||
|
||||
if(!(A.zone in B.zone.connected_zones))
|
||||
B.zone.connected_zones += A.zone
|
||||
B.zone.connected_zones[A.zone] = 1
|
||||
else
|
||||
B.zone.connected_zones[A.zone]++
|
||||
Del()
|
||||
if(A.zone && A.zone.connections)
|
||||
A.zone.connections -= src
|
||||
if(B.zone && B.zone.connections)
|
||||
B.zone.connections -= src
|
||||
|
||||
if(A.zone && B.zone)
|
||||
|
||||
if(B.zone in A.zone.connected_zones)
|
||||
if(A.zone.connected_zones[B.zone] > 1)
|
||||
A.zone.connected_zones[B.zone]--
|
||||
else
|
||||
A.zone.connected_zones -= B.zone
|
||||
|
||||
if(A.zone in B.zone.connected_zones)
|
||||
if(B.zone.connected_zones[A.zone] > 1)
|
||||
B.zone.connected_zones[A.zone]--
|
||||
else
|
||||
B.zone.connected_zones -= A.zone
|
||||
if(A.zone.connected_zones && !A.zone.connected_zones.len)
|
||||
A.zone.connected_zones = null
|
||||
if(B.zone.connected_zones && !B.zone.connected_zones.len)
|
||||
B.zone.connected_zones = null
|
||||
. = ..()
|
||||
|
||||
proc/Cleanup()
|
||||
if(A.zone == B.zone) del src
|
||||
if(!A.zone || !B.zone) del src
|
||||
60
code/ZAS/Creation.dm
Normal file
60
code/ZAS/Creation.dm
Normal file
@@ -0,0 +1,60 @@
|
||||
zone
|
||||
New(turf/start)
|
||||
if(istype(start,/list))
|
||||
contents = start
|
||||
else
|
||||
contents = FloodFill(start)
|
||||
for(var/turf/T in contents)
|
||||
T.zone = src
|
||||
if(istype(T,/turf/space))
|
||||
AddSpace(T)
|
||||
air = new
|
||||
var/members = contents.len
|
||||
for(var/turf/simulated/T in contents)
|
||||
air.oxygen += T.oxygen / members
|
||||
air.nitrogen += T.nitrogen / members
|
||||
air.carbon_dioxide += T.carbon_dioxide / members
|
||||
air.toxins += T.toxins / members
|
||||
air.temperature += T.temperature / members
|
||||
air.group_multiplier = contents.len
|
||||
zones += src
|
||||
Del()
|
||||
zones -= src
|
||||
. = ..()
|
||||
|
||||
proc/FloodFill(turf/start)
|
||||
var
|
||||
list
|
||||
open = list(start)
|
||||
closed = list()
|
||||
|
||||
while(open.len)
|
||||
for(var/turf/T in open)
|
||||
if(!T.HasDoor())
|
||||
for(var/d in cardinal)
|
||||
var/turf/O = get_step(T,d)
|
||||
if(O.ZCanPass(T) && !(O in open) && !(O in closed))
|
||||
open += O
|
||||
open -= T
|
||||
closed += T
|
||||
|
||||
return closed
|
||||
|
||||
turf/proc/ZCanPass(turf/T)
|
||||
if(istype(T,/turf/space)) return 0
|
||||
else
|
||||
if(T.blocks_air||blocks_air)
|
||||
return 0
|
||||
|
||||
for(var/obj/obstacle in src)
|
||||
if(istype(obstacle,/obj/machinery/door) && !istype(obstacle,/obj/machinery/door/window))
|
||||
continue
|
||||
if(!obstacle.CanPass(0, T, 0, 1))
|
||||
return 0
|
||||
for(var/obj/obstacle in T)
|
||||
if(istype(obstacle,/obj/machinery/door) && !istype(obstacle,/obj/machinery/door/window))
|
||||
continue
|
||||
if(!obstacle.CanPass(0, src, 0, 1))
|
||||
return 0
|
||||
|
||||
return 1
|
||||
56
code/ZAS/Debug.dm
Normal file
56
code/ZAS/Debug.dm
Normal file
@@ -0,0 +1,56 @@
|
||||
|
||||
client/proc/Zone_Info(turf/T as null|turf)
|
||||
set category = "Debug"
|
||||
if(T)
|
||||
if(T.zone)
|
||||
T.zone.DebugDisplay(mob)
|
||||
else
|
||||
mob << "No zone here."
|
||||
else
|
||||
for(T in world)
|
||||
T.overlays -= 'debug_space.dmi'
|
||||
T.overlays -= 'debug_group.dmi'
|
||||
T.overlays -= 'debug_connect.dmi'
|
||||
|
||||
zone/proc
|
||||
DebugDisplay(mob/M)
|
||||
if(!dbg_output)
|
||||
dbg_output = 1 //Don't want to be spammed when someone investigates a zone...
|
||||
for(var/turf/T in contents)
|
||||
T.overlays += 'debug_group.dmi'
|
||||
|
||||
for(var/turf/space/S in space_tiles)
|
||||
S.overlays += 'debug_space.dmi'
|
||||
|
||||
M << "<u>Zone Air Contents</u>"
|
||||
M << "Oxygen: [air.oxygen]"
|
||||
M << "Nitrogen: [air.nitrogen]"
|
||||
M << "Plasma: [air.toxins]"
|
||||
M << "Carbon Dioxide: [air.carbon_dioxide]"
|
||||
M << "Temperature: [air.temperature]"
|
||||
M << "Heat Energy: [air.thermal_energy()]"
|
||||
M << "Pressure: [air.return_pressure()]"
|
||||
M << ""
|
||||
M << "<u>Connections: [length(connections)]</u>"
|
||||
|
||||
for(var/connection/C in connections)
|
||||
M << "[C.A] --> [C.B] [(C.indirect?"Indirect":"Direct")]"
|
||||
C.A.overlays += 'debug_connect.dmi'
|
||||
C.B.overlays += 'debug_connect.dmi'
|
||||
spawn(50)
|
||||
C.A.overlays -= 'debug_connect.dmi'
|
||||
C.B.overlays -= 'debug_connect.dmi'
|
||||
|
||||
else
|
||||
dbg_output = 0
|
||||
|
||||
for(var/turf/T in contents)
|
||||
T.overlays -= 'debug_group.dmi'
|
||||
|
||||
for(var/turf/space/S in space_tiles)
|
||||
S.overlays -= 'debug_space.dmi'
|
||||
for(var/zone/Z in zones)
|
||||
if(Z.air == air && Z != src)
|
||||
var/turf/zloc = pick(Z.contents)
|
||||
M << "\red Illegal air datum shared by: [zloc.loc.name]"
|
||||
|
||||
34
code/ZAS/Definition.dm
Normal file
34
code/ZAS/Definition.dm
Normal file
@@ -0,0 +1,34 @@
|
||||
turf/var/zone/zone
|
||||
|
||||
var/list/zones = list()
|
||||
var/zone_controller/zone_master = new
|
||||
|
||||
zone_controller
|
||||
var
|
||||
current_tick = 0
|
||||
proc
|
||||
start()
|
||||
set background = 1
|
||||
while(1)
|
||||
current_tick++
|
||||
for(var/zone/Z in zones)
|
||||
if(Z.last_update < current_tick)
|
||||
Z.process()
|
||||
if(Z) Z.last_update = current_tick
|
||||
for(var/obj/fire/F)
|
||||
F.process()
|
||||
//for(var/obj/z_hotspot/H in z_hotspots)
|
||||
// H.process()
|
||||
sleep(max(5,vsc.zone_update_delay*tick_multiplier))
|
||||
|
||||
zone
|
||||
var
|
||||
dbg_output = 0 //Enables debug output.
|
||||
rebuild = 0 //If 1, zone will be rebuilt on next process.
|
||||
datum/gas_mixture/air //The air contents of the zone.
|
||||
list/contents //All the tiles that are contained in this zone.
|
||||
list/connections // /connection objects which refer to connections with other zones, e.g. through a door.
|
||||
list/connected_zones //Parallels connections, but lists zones to which this one is connected and the number
|
||||
//of points they're connected at.
|
||||
list/space_tiles // Any space tiles in this list will cause air to flow out.
|
||||
last_update = 0
|
||||
338
code/ZAS/Fire.dm
Normal file
338
code/ZAS/Fire.dm
Normal file
@@ -0,0 +1,338 @@
|
||||
vs_control/var/IgnitionLevel = 10 //Moles of oxygen+plasma - co2 needed to burn.
|
||||
|
||||
#define OXYGEN
|
||||
atom/proc/temperature_expose(datum/gas_mixture/air, exposed_temperature, exposed_volume)
|
||||
return null
|
||||
|
||||
turf/proc/hotspot_expose(exposed_temperature, exposed_volume, soh = 0)
|
||||
|
||||
turf/simulated/hotspot_expose(exposed_temperature, exposed_volume, soh)
|
||||
if(fire_protection) return
|
||||
var/datum/gas_mixture/air_contents = return_air(1)
|
||||
if(!air_contents)
|
||||
return 0
|
||||
|
||||
/*if(active_hotspot)
|
||||
if(soh)
|
||||
if(air_contents.toxins > 0.5 && air_contents.oxygen > 0.5)
|
||||
if(active_hotspot.temperature < exposed_temperature)
|
||||
active_hotspot.temperature = exposed_temperature
|
||||
if(active_hotspot.volume < exposed_volume)
|
||||
active_hotspot.volume = exposed_volume
|
||||
return 1*/
|
||||
var/igniting = 0
|
||||
if(locate(/obj/fire) in src)
|
||||
return 1
|
||||
var/datum/gas/volatile_fuel/fuel = locate() in air_contents.trace_gases
|
||||
var/obj/liquid_fuel/liquid = locate() in src
|
||||
var/fuel_level = 0
|
||||
var/liquid_level = 0
|
||||
if(fuel) fuel_level = fuel.moles
|
||||
if(liquid) liquid_level = liquid.amount
|
||||
var/total_fuel = air_contents.toxins + fuel_level + liquid_level
|
||||
if((air_contents.oxygen + air_contents.toxins + fuel_level*1.5 + liquid_level*1.5) - (air_contents.carbon_dioxide*0.25) > vsc.IgnitionLevel && total_fuel > 0.5)
|
||||
igniting = 1
|
||||
if(air_contents.oxygen < 0.5)
|
||||
return 0
|
||||
|
||||
if(parent&&parent.group_processing)
|
||||
parent.suspend_group_processing()
|
||||
|
||||
if(! (locate(/obj/fire) in src))
|
||||
var/obj/fire/F = new(src,1000)
|
||||
F.temperature = exposed_temperature
|
||||
F.volume = CELL_VOLUME
|
||||
|
||||
//active_hotspot.just_spawned = (current_cycle < air_master.current_cycle)
|
||||
//remove just_spawned protection if no longer processing this cell
|
||||
|
||||
return igniting
|
||||
|
||||
obj/effect/hotspot
|
||||
//Icon for fire on turfs, also helps for nurturing small fires until they are full tile
|
||||
|
||||
anchored = 1
|
||||
|
||||
mouse_opacity = 0
|
||||
|
||||
//luminosity = 3
|
||||
|
||||
icon = 'fire.dmi'
|
||||
icon_state = "1"
|
||||
|
||||
layer = TURF_LAYER
|
||||
|
||||
var
|
||||
volume = 125
|
||||
temperature = FIRE_MINIMUM_TEMPERATURE_TO_EXIST
|
||||
|
||||
just_spawned = 1
|
||||
|
||||
bypassing = 0
|
||||
|
||||
obj/effect/hotspot/proc/perform_exposure()
|
||||
var/turf/simulated/floor/location = loc
|
||||
if(!istype(location))
|
||||
return 0
|
||||
|
||||
if(volume > CELL_VOLUME*0.95)
|
||||
bypassing = 1
|
||||
else bypassing = 0
|
||||
|
||||
if(bypassing)
|
||||
if(!just_spawned)
|
||||
volume = location.air.fuel_burnt*FIRE_GROWTH_RATE
|
||||
temperature = location.air.temperature
|
||||
else
|
||||
var/datum/gas_mixture/affected = location.air.remove_ratio(volume/location.air.volume)
|
||||
|
||||
affected.temperature = temperature
|
||||
|
||||
affected.react()
|
||||
|
||||
temperature = affected.temperature
|
||||
volume = affected.fuel_burnt*FIRE_GROWTH_RATE
|
||||
|
||||
location.assume_air(affected)
|
||||
|
||||
for(var/atom/item in loc)
|
||||
item.temperature_expose(null, temperature, volume)
|
||||
|
||||
obj/effect/hotspot/process(turf/simulated/list/possible_spread)
|
||||
if(just_spawned)
|
||||
just_spawned = 0
|
||||
return 0
|
||||
|
||||
var/turf/simulated/floor/location = loc
|
||||
if(!istype(location))
|
||||
del(src)
|
||||
|
||||
if((temperature < FIRE_MINIMUM_TEMPERATURE_TO_EXIST) || (volume <= 1))
|
||||
del(src)
|
||||
|
||||
if(location.air.toxins < 0.5 || location.air.oxygen < 0.5)
|
||||
del(src)
|
||||
|
||||
|
||||
perform_exposure()
|
||||
|
||||
if(location.wet) location.wet = 0
|
||||
|
||||
if(bypassing)
|
||||
icon_state = "3"
|
||||
location.burn_tile()
|
||||
|
||||
//Possible spread due to radiated heat
|
||||
if(location.air.temperature > FIRE_MINIMUM_TEMPERATURE_TO_SPREAD)
|
||||
var/radiated_temperature = location.air.temperature*FIRE_SPREAD_RADIOSITY_SCALE
|
||||
|
||||
for(var/turf/simulated/possible_target in possible_spread)
|
||||
if(!locate(/obj/effect/hotspot) in possible_target)
|
||||
possible_target.hotspot_expose(radiated_temperature, CELL_VOLUME/4)
|
||||
|
||||
else
|
||||
if(volume > CELL_VOLUME*0.4)
|
||||
icon_state = "2"
|
||||
else
|
||||
icon_state = "1"
|
||||
|
||||
return 1
|
||||
|
||||
obj/effect/hotspot/New()
|
||||
..()
|
||||
dir = pick(cardinal)
|
||||
sd_SetLuminosity(3)
|
||||
|
||||
obj/effect/hotspot/Del()
|
||||
src.sd_SetLuminosity(0)
|
||||
loc = null
|
||||
..()
|
||||
|
||||
var
|
||||
fire_ratio_1 = 0.05
|
||||
|
||||
obj
|
||||
fire
|
||||
//Icon for fire on turfs, also helps for nurturing small fires until they are full tile
|
||||
|
||||
anchored = 1
|
||||
mouse_opacity = 0
|
||||
|
||||
//luminosity = 3
|
||||
|
||||
icon = 'fire.dmi'
|
||||
icon_state = "1"
|
||||
|
||||
layer = TURF_LAYER
|
||||
|
||||
var
|
||||
volume = CELL_VOLUME
|
||||
temperature = FIRE_MINIMUM_TEMPERATURE_TO_EXIST
|
||||
firelevel = 10000
|
||||
archived_firelevel = 0
|
||||
|
||||
process()
|
||||
if(firelevel > vsc.IgnitionLevel)
|
||||
var/turf/simulated/floor/S = loc
|
||||
if(!S.zone) del src
|
||||
//src.temperature += (src.firelevel/FireTempDivider+FireOffset - src.temperature) / FireRate
|
||||
if(istype(S,/turf/simulated/floor))
|
||||
var
|
||||
datum/gas_mixture/air_contents = S.return_air()
|
||||
datum/gas/volatile_fuel/fuel = locate(/datum/gas/volatile_fuel/) in air_contents.trace_gases
|
||||
fuel_level = 0
|
||||
obj/liquid_fuel/liquid = locate() in S
|
||||
liquid_level = 0
|
||||
|
||||
if(fuel) fuel_level = fuel.moles
|
||||
if(liquid)
|
||||
liquid_level = liquid.amount
|
||||
if(liquid.amount <= 0)
|
||||
del liquid
|
||||
liquid_level = 0
|
||||
|
||||
firelevel = (air_contents.oxygen + air_contents.toxins + fuel_level*1.5 + liquid_level*1.5) - (air_contents.carbon_dioxide*0.25)
|
||||
|
||||
firelevel = min(firelevel,vsc.IgnitionLevel*5)
|
||||
|
||||
if(firelevel > vsc.IgnitionLevel * 1.5 && (air_contents.toxins || fuel_level || liquid_level))
|
||||
for(var/direction in cardinal)
|
||||
if(S.air_check_directions&direction) //Grab all valid bordering tiles
|
||||
var/turf/simulated/enemy_tile = get_step(S, direction)
|
||||
if(istype(enemy_tile))
|
||||
if(enemy_tile.fire_protection)
|
||||
firelevel -= vsc.IgnitionLevel
|
||||
continue
|
||||
if(!(locate(/obj/fire) in enemy_tile))
|
||||
if( prob( firelevel/(vsc.IgnitionLevel*0.1) ) )
|
||||
new/obj/fire(enemy_tile,firelevel)
|
||||
// else
|
||||
// world << "Spread Probability: [firelevel/(vsc.IgnitionLevel*0.1)]%."
|
||||
// else
|
||||
// world << "There's a fire there bitch."
|
||||
// else
|
||||
// world << "[enemy_tile] cannot be spread to."
|
||||
//else
|
||||
// world << "Not enough firelevel to spread: [firelevel]/[vsc.IgnitionLevel*1.5]"
|
||||
|
||||
var/datum/gas_mixture/flow = air_contents.remove_ratio(0.5)
|
||||
//n = PV/RT, taking the volume of a single tile from the gas.
|
||||
|
||||
if(flow)
|
||||
|
||||
if(flow.oxygen > 0.3 && (flow.toxins || fuel_level || liquid))
|
||||
|
||||
icon_state = "1"
|
||||
if(firelevel > vsc.IgnitionLevel * 2)
|
||||
icon_state = "2"
|
||||
if(firelevel > vsc.IgnitionLevel * 3.5)
|
||||
icon_state = "3"
|
||||
flow.temperature = max(PLASMA_MINIMUM_BURN_TEMPERATURE+0.1,flow.temperature)
|
||||
flow.zburn(liquid)
|
||||
|
||||
else
|
||||
del src
|
||||
|
||||
|
||||
S.assume_air(flow)
|
||||
else
|
||||
//world << "No air at all."
|
||||
del src
|
||||
else
|
||||
del src
|
||||
else
|
||||
//world << "Insufficient fire level for ignition: [firelevel]/[IgnitionLevel]"
|
||||
del src
|
||||
|
||||
for(var/mob/living/carbon/human/M in loc)
|
||||
M.FireBurn(firelevel/(vsc.IgnitionLevel*10))
|
||||
|
||||
|
||||
New(newLoc,fl)
|
||||
..()
|
||||
dir = pick(cardinal)
|
||||
sd_SetLuminosity(3)
|
||||
firelevel = fl
|
||||
for(var/mob/living/carbon/human/M in loc)
|
||||
M.FireBurn(firelevel/(vsc.IgnitionLevel*10))
|
||||
|
||||
Del()
|
||||
if (istype(loc, /turf/simulated))
|
||||
src.sd_SetLuminosity(0)
|
||||
|
||||
loc = null
|
||||
|
||||
..()
|
||||
|
||||
obj/liquid_fuel
|
||||
icon = 'effects.dmi'
|
||||
icon_state = "slube"
|
||||
layer = TURF_LAYER+0.2
|
||||
anchored = 1
|
||||
var/amount = 1
|
||||
|
||||
New(newLoc)
|
||||
for(var/obj/liquid_fuel/other in newLoc)
|
||||
if(other != src)
|
||||
other.amount += src.amount
|
||||
del src
|
||||
. = ..()
|
||||
|
||||
vs_control/var/switch_fire = 1
|
||||
|
||||
turf/simulated/var/fire_protection = 0
|
||||
|
||||
datum/gas_mixture/proc/zburn(obj/liquid_fuel/liquid)
|
||||
if(vsc.switch_fire)
|
||||
. = fire()
|
||||
if(liquid && liquid.amount > 0)
|
||||
oxygen -= fire_ratio_1
|
||||
liquid.amount = max(liquid.amount-fire_ratio_1,0)
|
||||
carbon_dioxide += fire_ratio_1
|
||||
if(liquid.amount <= 0)
|
||||
del liquid
|
||||
return
|
||||
if(temperature > PLASMA_MINIMUM_BURN_TEMPERATURE)
|
||||
var
|
||||
fuel_level = 0
|
||||
datum/gas/volatile_fuel/fuel = locate() in trace_gases
|
||||
liquid_level = 0
|
||||
if(fuel) fuel_level = fuel.moles
|
||||
if(liquid) liquid_level = liquid.amount
|
||||
if(liquid && liquid_level <= 0)
|
||||
del liquid
|
||||
liquid_level = 0
|
||||
if(oxygen > 0.3 && (toxins || fuel_level || liquid_level))
|
||||
if(toxins && temperature < PLASMA_UPPER_TEMPERATURE)
|
||||
temperature += (FIRE_PLASMA_ENERGY_RELEASED*fire_ratio_1) / heat_capacity()
|
||||
|
||||
if((fuel_level || liquid_level) && temperature < PLASMA_UPPER_TEMPERATURE)
|
||||
temperature += (FIRE_CARBON_ENERGY_RELEASED*fire_ratio_1) / heat_capacity()
|
||||
|
||||
if(toxins > fire_ratio_1)
|
||||
oxygen -= vsc.plc.OXY_TO_PLASMA*fire_ratio_1
|
||||
toxins -= fire_ratio_1
|
||||
carbon_dioxide += fire_ratio_1
|
||||
else if(toxins)
|
||||
oxygen -= toxins * vsc.plc.OXY_TO_PLASMA
|
||||
carbon_dioxide += toxins
|
||||
toxins = 0
|
||||
|
||||
if(fuel_level > fire_ratio_1/1.5)
|
||||
oxygen -= vsc.plc.OXY_TO_PLASMA*fire_ratio_1
|
||||
fuel.moles -= fire_ratio_1
|
||||
carbon_dioxide += fire_ratio_1
|
||||
|
||||
else if(fuel_level)
|
||||
oxygen -= fuel.moles * vsc.plc.OXY_TO_PLASMA
|
||||
carbon_dioxide += fuel.moles
|
||||
fuel.moles = 0
|
||||
|
||||
if(liquid_level > 0)
|
||||
oxygen -= fire_ratio_1
|
||||
liquid.amount = max(liquid.amount-fire_ratio_1,0)
|
||||
carbon_dioxide += fire_ratio_1
|
||||
if(liquid.amount <= 0)
|
||||
del liquid
|
||||
return 1
|
||||
return 0
|
||||
159
code/ZAS/Functions.dm
Normal file
159
code/ZAS/Functions.dm
Normal file
@@ -0,0 +1,159 @@
|
||||
zone
|
||||
proc
|
||||
AddTurf(turf/T)
|
||||
if(T in contents) return
|
||||
contents += T
|
||||
air.group_multiplier++
|
||||
T.zone = src
|
||||
RemoveTurf(turf/T)
|
||||
if(!(T in contents)) return
|
||||
contents -= T
|
||||
air.group_multiplier--
|
||||
T.zone = null
|
||||
|
||||
DivideAir(ratio)
|
||||
ratio = min(1,max(0,ratio))
|
||||
air.oxygen *= ratio
|
||||
air.oxygen = QUANTIZE(air.oxygen)
|
||||
air.nitrogen *= ratio
|
||||
air.nitrogen = QUANTIZE(air.nitrogen)
|
||||
air.toxins *= ratio
|
||||
air.toxins = QUANTIZE(air.toxins)
|
||||
air.carbon_dioxide *= ratio
|
||||
air.carbon_dioxide = QUANTIZE(air.carbon_dioxide)
|
||||
if(air.trace_gases.len)
|
||||
for(var/datum/gas/trace_gas in air.trace_gases)
|
||||
trace_gas.moles *= ratio
|
||||
trace_gas.moles = QUANTIZE(trace_gas.moles)
|
||||
air.temperature = air.temperature*ratio + TCMB*(1-ratio)
|
||||
air.temperature = QUANTIZE(air.temperature)
|
||||
|
||||
AddSpace(turf/space/S)
|
||||
if(istype(S,/turf/space))
|
||||
if(!space_tiles) space_tiles = list()
|
||||
space_tiles += S
|
||||
RemoveSpace(turf/space/S)
|
||||
if(space_tiles)
|
||||
space_tiles -= S
|
||||
if(!space_tiles.len) space_tiles = null
|
||||
|
||||
turf/proc/HasDoor(turf/O)
|
||||
for(var/obj/machinery/door/D in src)
|
||||
if(isnum(O) && O)
|
||||
if(!D.density) continue
|
||||
if(istype(D,/obj/machinery/door/window))
|
||||
if(!O) continue
|
||||
if(D.dir == get_dir(D,O)) return 1
|
||||
else
|
||||
return 1
|
||||
|
||||
turf/proc/find_zone()
|
||||
for(var/d in cardinal)
|
||||
var/turf/T = get_step(src,d)
|
||||
if(!T || !T.zone) continue
|
||||
if(!zone)
|
||||
zone = T.zone
|
||||
zone.AddTurf(src)
|
||||
else if(T.zone != zone)
|
||||
ZConnect(src,T)
|
||||
|
||||
proc
|
||||
ZMerge(zone/A,zone/B)
|
||||
//world << "Merge occured."
|
||||
var
|
||||
a_size = A.air.group_multiplier
|
||||
b_size = B.air.group_multiplier
|
||||
c_size = a_size + b_size
|
||||
new_contents = A.contents + B.contents
|
||||
|
||||
A.air.group_multiplier = 1
|
||||
B.air.group_multiplier = 1
|
||||
|
||||
A.air.remove_ratio(a_size/c_size)
|
||||
B.air.remove_ratio(b_size/c_size)
|
||||
A.air.merge(B.air)
|
||||
A.air.group_multiplier = c_size
|
||||
|
||||
for(var/connection/C in B.connections)
|
||||
if((C.A in new_contents) && (C.B in new_contents))
|
||||
del C
|
||||
continue
|
||||
A.connections += C
|
||||
A.space_tiles += B.space_tiles
|
||||
A.contents = new_contents
|
||||
for(var/turf/T in B.contents)
|
||||
T.zone = A
|
||||
del B
|
||||
|
||||
ZConnect(turf/A,turf/B)
|
||||
if(istype(B,/turf/space))
|
||||
if(A.zone)
|
||||
A.zone.AddSpace(B)
|
||||
//world << "Space added."
|
||||
return
|
||||
if(istype(A,/turf/space))
|
||||
if(B.zone)
|
||||
B.zone.AddSpace(B)
|
||||
//world << "Space added."
|
||||
return
|
||||
if(!A.zone || !B.zone) return
|
||||
if(A.zone == B.zone) return
|
||||
if(!A.CanPass(0,B,0,0)) return
|
||||
for(var/connection/C in A.zone.connections)
|
||||
if((C.A == A && C.B == B) || (C.A == B && C.B == A))
|
||||
return
|
||||
var/connection/C = new(A,B)
|
||||
if(A.HasDoor(B) || B.HasDoor(A)) C.indirect = 1
|
||||
//world << "Connection Formed: [A] --> [B] [(C.indirect?"Indirect":"Direct")]"
|
||||
//A.overlays += 'zone_connection_A.dmi'
|
||||
//B.overlays += 'zone_connection_B.dmi'
|
||||
//spawn(10)
|
||||
// A.overlays -= 'zone_connection_A.dmi'
|
||||
// B.overlays -= 'zone_connection_B.dmi'
|
||||
|
||||
|
||||
ZDisconnect(turf/A,turf/B)
|
||||
if(A.zone && B.zone)
|
||||
if(A.zone != B.zone)
|
||||
for(var/connection/C in A.zone.connections)
|
||||
if((C.A == A && C.B == B) || (C.A == B && C.B == A))
|
||||
//world << "Connection Dissolved: [A] -/-> [B] [(C.indirect?"Indirect":"Direct")]"
|
||||
/*A.overlays += 'zone_connection_A.dmi'
|
||||
B.overlays += 'zone_connection_B.dmi'
|
||||
spawn(10)
|
||||
A.overlays -= 'zone_connection_A.dmi'
|
||||
B.overlays -= 'zone_connection_B.dmi'*/
|
||||
del C
|
||||
/*else
|
||||
if(A == B) return
|
||||
if(A.CanPass(0,B,0,0)) return
|
||||
if(A.HasDoor(B) || B.HasDoor(A)) return
|
||||
var/zone/oldzone = A.zone
|
||||
var/list/test = FloodFill(A)
|
||||
if(B in test) return
|
||||
else
|
||||
var/zone/Z = new(test,oldzone.air)
|
||||
for(var/connection/C in oldzone.connections)
|
||||
if((A in Z.contents) || (B in Z.contents))
|
||||
if(!Z.connections) Z.connections = list()
|
||||
Z.connections += C
|
||||
var/datum/gas_mixture/Y_Air = new
|
||||
Y_Air.copy_from(oldzone.air)
|
||||
var/zone/Y = new(B,Y_Air)
|
||||
for(var/connection/C in oldzone.connections)
|
||||
if((A in Y.contents) || (B in Y.contents))
|
||||
if(!Y.connections) Y.connections = list()
|
||||
Y.connections += C
|
||||
oldzone.air = null
|
||||
del oldzone
|
||||
world << "Zone Split: [A] / [B]"
|
||||
A.overlays += 'zone_connection_A.dmi'
|
||||
B.overlays += 'zone_connection_B.dmi'
|
||||
spawn(10)
|
||||
A.overlays -= 'zone_connection_A.dmi'
|
||||
B.overlays -= 'zone_connection_B.dmi'*/
|
||||
else
|
||||
if(istype(A,/turf/space) && B.zone)
|
||||
B.zone.RemoveSpace(A)
|
||||
else if(istype(B,/turf/space) && A.zone)
|
||||
A.zone.RemoveSpace(B)
|
||||
252
code/ZAS/Plasma.dm
Normal file
252
code/ZAS/Plasma.dm
Normal file
@@ -0,0 +1,252 @@
|
||||
pl_control/var
|
||||
PLASMA_DMG = 3
|
||||
PLASMA_DMG_NAME = "Plasma Damage Multiplier"
|
||||
PLASMA_DMG_DESC = "Multiplier on how much damage inhaling plasma can do."
|
||||
|
||||
OXY_TO_PLASMA = 1
|
||||
OXY_TO_PLASMA_NAME = "O2/Plasma Ratio"
|
||||
OXY_TO_PLASMA_DESC = "Multiplier for the ratio of oxygen to plasma required in fires."
|
||||
|
||||
CLOTH_CONTAMINATION = 1 //If this is on, plasma does damage by getting into cloth.
|
||||
CLOTH_CONTAMINATION_NAME = "Plasma - Cloth Contamination"
|
||||
CLOTH_CONTAMINATION_RANDOM = 60
|
||||
CLOTH_CONTAMINATION_METHOD = "Toggle"
|
||||
CLOTH_CONTAMINATION_DESC = "If set to nonzero, plasma will contaminate cloth items (uniforms, backpacks, etc.)\
|
||||
and cause a small amount of damage over time to anyone carrying or wearing them. Contamination can be detected\
|
||||
with a Health Analyzer, and washed off in the washer."
|
||||
|
||||
ALL_ITEM_CONTAMINATION = 0 //If this is on, any item can be contaminated, so suits and tools must be discarded or
|
||||
//decontaminated.
|
||||
ALL_ITEM_CONTAMINATION_NAME = "Plasma - Full Contamination"
|
||||
ALL_ITEM_CONTAMINATION_RANDOM = 10
|
||||
ALL_ITEM_CONTAMINATION_METHOD = "Toggle"
|
||||
ALL_ITEM_CONTAMINATION_DESC = "Like Cloth Contamination, but all item types are susceptible."
|
||||
|
||||
PLASMAGUARD_ONLY = 0
|
||||
PLASMAGUARD_ONLY_NAME = "Plasma - Biosuits/Spacesuits Only"
|
||||
PLASMAGUARD_ONLY_RANDOM = 20
|
||||
PLASMAGUARD_ONLY_METHOD = "Toggle"
|
||||
PLASMAGUARD_ONLY_DESC = "If on, any suits that are not biosuits or space suits will not protect against contamination."
|
||||
|
||||
//CANISTER_CORROSION = 0 //If this is on, plasma must be stored in orange tanks and canisters,
|
||||
//CANISTER_CORROSION_RANDOM = 20 //or it will corrode the tank.
|
||||
//CANISTER_CORROSION_METHOD = "Toggle"
|
||||
|
||||
GENETIC_CORRUPTION = 0 //Chance of genetic corruption as well as toxic damage, X in 10,000.
|
||||
GENETIC_CORRUPTION_NAME = "Plasma - Genetic Corruption"
|
||||
GENETIC_CORRUPTION_RANDOM = "PROB10/3d6"
|
||||
GENETIC_CORRUPTION_METHOD = "Numeric"
|
||||
GENETIC_CORRUPTION_DESC = "When set to a probability in 1000, any humans in plasma will have this chance to develop a random mutation."
|
||||
|
||||
SKIN_BURNS = 1 //Plasma has an effect similar to mustard gas on the un-suited.
|
||||
SKIN_BURNS_NAME = "Plasma - Skin Burns"
|
||||
SKIN_BURNS_RANDOM = 10
|
||||
SKIN_BURNS_METHOD = "Toggle"
|
||||
SKIN_BURNS_DESC = "When toggled, humans with exposed skin will suffer burns (similar to mustard gas) in plasma."
|
||||
|
||||
//PLASMA_INJECTS_TOXINS = 0 //Plasma damage injects the toxins chemical to do damage over time.
|
||||
//PLASMA_INJECTS_TOXINS_RANDOM = 30
|
||||
//PLASMA_INJECTS_TOXINS_METHOD = "Toggle"
|
||||
|
||||
EYE_BURNS = 0 //Plasma burns the eyes of anyone not wearing eye protection.
|
||||
EYE_BURNS_NAME = "Plasma - Eye Burns"
|
||||
EYE_BURNS_RANDOM = 30
|
||||
EYE_BURNS_METHOD = "Toggle"
|
||||
EYE_BURNS_DESC = "When toggled, humans without masks that cover the eyes will suffer temporary blurriness and sight loss,\
|
||||
and may need glasses to see again if exposed for long durations."
|
||||
|
||||
//N2O_REACTION = 0 //Plasma can react with N2O, making sparks and starting a fire if levels are high.
|
||||
//N2O_REACTION_RANDOM = 5
|
||||
|
||||
//PLASMA_COLOR = "onturf" //Plasma can change colors yaaaay!
|
||||
//PLASMA_COLOR_RANDOM = "PICKonturf,onturf"
|
||||
|
||||
//PLASMA_DMG_OFFSET = 1
|
||||
//PLASMA_DMG_OFFSET_RANDOM = "1d5"
|
||||
//PLASMA_DMG_QUOTIENT = 10
|
||||
//PLASMA_DMG_QUOTIENT_RANDOM = "1d10+4"
|
||||
|
||||
CONTAMINATION_LOSS = 0.1
|
||||
_NAME = "Plasma - Contamination Damage"
|
||||
CONTAMINATION_LOSS_DESC = "A number representing the damage done per life cycle by contaminated items."
|
||||
|
||||
PLASMA_HALLUCINATION = 1
|
||||
PLASMA_HALLUCINATION_NAME = "Plasma - Hallucination"
|
||||
PLASMA_HALLUCINATION_METHOD = "Toggle"
|
||||
PLASMA_HALLUCINATION_DESC = "If toggled, uses the remnants of the hallucination code to induce visions in those\
|
||||
who breathe plasma."
|
||||
N2O_HALLUCINATION = 1
|
||||
N2O_HALLUCINATION_NAME = "Nitrous Oxide - Hallucination"
|
||||
N2O_HALLUCINATION_METHOD = "Toggle"
|
||||
N2O_HALLUCINATION_DESC = "If toggled, uses the remnants of the hallucination code to induce visions in those\
|
||||
who breathe N2O."
|
||||
//CONTAMINATION_LOSS_RANDOM = "5d5"
|
||||
//Plasma has a chance to be a different color.
|
||||
|
||||
obj/var/contaminated = 0
|
||||
|
||||
obj/item/proc
|
||||
can_contaminate()
|
||||
if(flags & PLASMAGUARD) return 0
|
||||
if((flags & SUITSPACE) && !vsc.plc.PLASMAGUARD_ONLY) return 1
|
||||
if(vsc.plc.ALL_ITEM_CONTAMINATION) return 1
|
||||
else if(istype(src,/obj/item/clothing)) return 1
|
||||
else if(istype(src,/obj/item/weapon/storage/backpack)) return 1
|
||||
|
||||
/mob/living/carbon/human/proc/contaminate()
|
||||
if(!pl_suit_protected())
|
||||
suit_contamination()
|
||||
else if(vsc.plc.PLASMAGUARD_ONLY)
|
||||
if(!wear_suit.flags & PLASMAGUARD) wear_suit.contaminated = 1
|
||||
|
||||
|
||||
|
||||
if(!pl_head_protected())
|
||||
if(wear_mask) wear_mask.contaminated = 1
|
||||
if(prob(1)) suit_contamination() //Plasma can sometimes get through such an open suit.
|
||||
else if(vsc.plc.PLASMAGUARD_ONLY)
|
||||
if(!head.flags & PLASMAGUARD) head.contaminated = 1
|
||||
|
||||
if(istype(back,/obj/item/weapon/storage/backpack) || vsc.plc.ALL_ITEM_CONTAMINATION)
|
||||
back.contaminated = 1
|
||||
|
||||
if(l_hand)
|
||||
if(l_hand.can_contaminate()) l_hand.contaminated = 1
|
||||
if(r_hand)
|
||||
if(r_hand.can_contaminate()) r_hand.contaminated = 1
|
||||
if(belt)
|
||||
if(belt.can_contaminate()) belt.contaminated = 1
|
||||
if(wear_id && !pl_suit_protected())
|
||||
if(wear_id.can_contaminate()) wear_id.contaminated = 1
|
||||
if(l_ear && !pl_head_protected())
|
||||
if(l_ear.can_contaminate()) l_ear.contaminated = 1
|
||||
if(r_ear && !pl_head_protected())
|
||||
if(r_ear.can_contaminate()) r_ear.contaminated = 1
|
||||
|
||||
/mob/living/carbon/human/proc/pl_effects()
|
||||
if(stat >= 2)
|
||||
return
|
||||
if(vsc.plc.SKIN_BURNS)
|
||||
if(!pl_head_protected() || !pl_suit_protected())
|
||||
burn_skin(0.75)
|
||||
if (coughedtime != 1)
|
||||
coughedtime = 1
|
||||
emote("gasp")
|
||||
spawn (20)
|
||||
coughedtime = 0
|
||||
updatehealth()
|
||||
if(vsc.plc.EYE_BURNS && !pl_head_protected())
|
||||
if(!wear_mask)
|
||||
if(prob(20)) usr << "\red Your eyes burn!"
|
||||
eye_stat += 2.5
|
||||
eye_blurry += 1.5
|
||||
if (eye_stat >= 20 && !(disabilities & 1))
|
||||
src << "\red Your eyes start to burn badly!"
|
||||
disabilities |= 1
|
||||
if (prob(max(0,eye_stat - 20) + 1))
|
||||
src << "\red You are blinded!"
|
||||
eye_blind += 20
|
||||
eye_stat = max(eye_stat-25,0)
|
||||
else
|
||||
if(!(wear_mask.flags & MASKCOVERSEYES))
|
||||
if(prob(20)) usr << "\red Your eyes burn!"
|
||||
eye_stat += 2.5
|
||||
eye_blurry = min(eye_blurry+1.5,50)
|
||||
if (eye_stat >= 20 && !(disabilities & 1))
|
||||
src << "\red Your eyes start to burn badly!"
|
||||
disabilities |= 1
|
||||
if (prob(max(0,eye_stat - 20) + 1) &&!eye_blind)
|
||||
src << "\red You are blinded!"
|
||||
eye_blind += 20
|
||||
eye_stat = 0
|
||||
if(vsc.plc.GENETIC_CORRUPTION)
|
||||
if(rand(1,1000) < vsc.plc.GENETIC_CORRUPTION)
|
||||
randmutb(src)
|
||||
src << "\red High levels of toxins cause you to spontaneously mutate."
|
||||
domutcheck(src,null)
|
||||
|
||||
/mob/living/carbon/human/proc/FireBurn(mx as num)
|
||||
//NO! NOT INTO THE PIT! IT BURRRRRNS!
|
||||
mx *= vsc.BURN_DMG
|
||||
|
||||
var
|
||||
head_exposure = 1
|
||||
chest_exposure = 1
|
||||
groin_exposure = 1
|
||||
legs_exposure = 1
|
||||
feet_exposure = 1
|
||||
arms_exposure = 1
|
||||
hands_exposure = 1
|
||||
for(var/obj/item/clothing/C in src)
|
||||
if(l_hand == C || r_hand == C) continue
|
||||
if(C.body_parts_covered & HEAD)
|
||||
head_exposure *= C.heat_transfer_coefficient
|
||||
if(C.body_parts_covered & UPPER_TORSO)
|
||||
chest_exposure *= C.heat_transfer_coefficient
|
||||
if(C.body_parts_covered & LOWER_TORSO)
|
||||
groin_exposure *= C.heat_transfer_coefficient
|
||||
if(C.body_parts_covered & LEGS)
|
||||
legs_exposure *= C.heat_transfer_coefficient
|
||||
if(C.body_parts_covered & FEET)
|
||||
feet_exposure *= C.heat_transfer_coefficient
|
||||
if(C.body_parts_covered & ARMS)
|
||||
arms_exposure *= C.heat_transfer_coefficient
|
||||
if(C.body_parts_covered & HANDS)
|
||||
arms_exposure *= C.heat_transfer_coefficient
|
||||
|
||||
mx *= 10
|
||||
|
||||
apply_damage("head", 0, 2.5*mx*head_exposure)
|
||||
apply_damage("chest", 0, 2.5*mx*chest_exposure)
|
||||
apply_damage("groin", 0, 2.0*mx*groin_exposure)
|
||||
apply_damage("l_leg", 0, 0.6*mx*legs_exposure)
|
||||
apply_damage("r_leg", 0, 0.6*mx*legs_exposure)
|
||||
apply_damage("l_arm", 0, 0.4*mx*arms_exposure)
|
||||
apply_damage("r_arm", 0, 0.4*mx*arms_exposure)
|
||||
apply_damage("l_foot", 0, 0.25*mx*feet_exposure)
|
||||
apply_damage("r_foot", 0, 0.25*mx*feet_exposure)
|
||||
apply_damage("l_hand", 0, 0.25*mx*hands_exposure)
|
||||
apply_damage("r_hand", 0, 0.25*mx*hands_exposure)
|
||||
|
||||
/mob/living/carbon/human/proc/suit_interior()
|
||||
. = list()
|
||||
if(!pl_suit_protected())
|
||||
for(var/obj/item/I in src)
|
||||
. += I
|
||||
return .
|
||||
. += wear_mask
|
||||
. += w_uniform
|
||||
. += shoes
|
||||
. += gloves
|
||||
if(!pl_head_protected())
|
||||
. += head
|
||||
|
||||
/mob/living/carbon/human/proc/pl_head_protected()
|
||||
if(head)
|
||||
if(head.flags & PLASMAGUARD || head.flags & HEADSPACE) return 1
|
||||
return 0
|
||||
|
||||
/mob/living/carbon/human/proc/pl_suit_protected()
|
||||
if(wear_suit)
|
||||
if(wear_suit.flags & PLASMAGUARD || wear_suit.flags & SUITSPACE) return 1
|
||||
return 0
|
||||
|
||||
/mob/living/carbon/human/proc/suit_contamination()
|
||||
if(vsc.plc.ALL_ITEM_CONTAMINATION)
|
||||
for(var/obj/item/I in src)
|
||||
I.contaminated = 1
|
||||
else
|
||||
if(wear_suit) wear_suit.contaminated = 1
|
||||
if(w_uniform) w_uniform.contaminated = 1
|
||||
if(shoes) shoes.contaminated = 1
|
||||
if(gloves) gloves.contaminated = 1
|
||||
if(wear_mask) wear_mask.contaminated = 1
|
||||
|
||||
|
||||
turf/Entered(obj/item/I)
|
||||
. = ..()
|
||||
if(istype(I))
|
||||
var/datum/gas_mixture/env = return_air(1)
|
||||
if(env.toxins > 0.35)
|
||||
if(I.can_contaminate())
|
||||
I.contaminated = 1
|
||||
103
code/ZAS/Processing.dm
Normal file
103
code/ZAS/Processing.dm
Normal file
@@ -0,0 +1,103 @@
|
||||
#define QUANTIZE(variable) (round(variable,0.0001))
|
||||
var/explosion_halt = 0
|
||||
zone
|
||||
proc/process()
|
||||
if(rebuild)
|
||||
if(!contents) del src
|
||||
var
|
||||
turf/sample = pick(contents)
|
||||
list/new_contents = FloodFill(sample)
|
||||
problem = 0
|
||||
for(var/turf/T in contents)
|
||||
if(!(T in new_contents))
|
||||
problem = 1
|
||||
|
||||
if(problem)
|
||||
var/list/rebuild_turfs = list()
|
||||
for(var/turf/T in contents - new_contents)
|
||||
contents -= T
|
||||
rebuild_turfs += T
|
||||
T.zone = null
|
||||
for(var/turf/T in rebuild_turfs)
|
||||
if(!T.zone)
|
||||
var/zone/Z = new/zone(T)
|
||||
Z.air.copy_from(air)
|
||||
rebuild = 0
|
||||
|
||||
var/total_space = 0
|
||||
var/turf/space/space
|
||||
|
||||
if(length(connected_zones))
|
||||
for(var/zone/Z in connected_zones)
|
||||
total_space += length(Z.space_tiles)
|
||||
if(length(Z.space_tiles))
|
||||
space = Z.space_tiles[1]
|
||||
|
||||
if(space_tiles)
|
||||
for(var/T in space_tiles)
|
||||
if(!istype(T,/turf/space)) space_tiles -= T
|
||||
total_space += length(space_tiles)
|
||||
if(length(space_tiles))
|
||||
space = space_tiles[1]
|
||||
|
||||
if(total_space && space)
|
||||
var/old_pressure = air.return_pressure()
|
||||
air.temperature_mimic(space,OPEN_HEAT_TRANSFER_COEFFICIENT,total_space)
|
||||
air.remove(MOLES_CELLSTANDARD * (air.group_multiplier/40) * total_space)
|
||||
if(dbg_output) world << "Space removed [MOLES_CELLSTANDARD*(air.group_multiplier/40)*total_space] moles of air."
|
||||
var/p_diff = old_pressure - air.return_pressure()
|
||||
if(p_diff > vsc.AF_TINY_MOVEMENT_THRESHOLD) AirflowSpace(src,p_diff)
|
||||
|
||||
air.react(null,0)
|
||||
var/check = air.check_tile_graphic()
|
||||
for(var/turf/T in contents)
|
||||
if(T.zone && T.zone != src)
|
||||
RemoveTurf(T)
|
||||
if(dbg_output) world << "Removed invalid turf."
|
||||
else if(!T.zone)
|
||||
T.zone = src
|
||||
|
||||
if(istype(T,/turf/simulated))
|
||||
var/turf/simulated/S = T
|
||||
if(S.fire_protection) S.fire_protection--
|
||||
if(check)
|
||||
if(S.HasDoor(1))
|
||||
S.update_visuals()
|
||||
else
|
||||
S.update_visuals(air)
|
||||
|
||||
if(air.temperature > FIRE_MINIMUM_TEMPERATURE_TO_EXIST)
|
||||
for(var/atom/movable/item in S)
|
||||
item.temperature_expose(air, air.temperature, CELL_VOLUME)
|
||||
S.temperature_expose(air, air.temperature, CELL_VOLUME)
|
||||
air.graphic_archived = air.graphic
|
||||
|
||||
air.temperature = max(TCMB,air.temperature)
|
||||
|
||||
if(length(connections))
|
||||
for(var/connection/C in connections)
|
||||
C.Cleanup()
|
||||
if(C && !C.indirect)
|
||||
if(C.A.zone.air.compare(C.B.zone.air))
|
||||
ZMerge(C.A.zone,C.B.zone)
|
||||
for(var/zone/Z in connected_zones)
|
||||
var/p_diff = (air.return_pressure()-Z.air.return_pressure())*connected_zones[Z]*(vsc.zone_share_percent/100)
|
||||
if(p_diff > vsc.AF_TINY_MOVEMENT_THRESHOLD) Airflow(src,Z,p_diff)
|
||||
air.share_ratio(Z.air,connected_zones[Z]*(vsc.zone_share_percent/100))
|
||||
|
||||
|
||||
zone/proc
|
||||
connected_zones()
|
||||
. = list()
|
||||
for(var/connection/C in connections)
|
||||
var/zone/Z
|
||||
if(C.A.zone == src)
|
||||
Z = C.B.zone
|
||||
else
|
||||
Z = C.A.zone
|
||||
|
||||
if(Z in .)
|
||||
.[Z]++
|
||||
else
|
||||
. += Z
|
||||
.[Z] = 1
|
||||
285
code/ZAS/Variable Settings.dm
Normal file
285
code/ZAS/Variable Settings.dm
Normal file
@@ -0,0 +1,285 @@
|
||||
var/global/vs_control/vsc = new
|
||||
vs_control
|
||||
var
|
||||
list/settings = list()
|
||||
list/bitflags = list("1","2","4","8","16","32","64","128","256","512","1024")
|
||||
pl_control/plc = new()
|
||||
/*RPREV_REQUIRE_HEADS_ALIVE = 0
|
||||
RPREV_REQUIRE_HEADS_ALIVE_DESC = "Require the heads to be captured alive in RP Rev, rather than either dead or captured."
|
||||
RPREV_REQUIRE_REVS_ALIVE = 0
|
||||
RPREV_REQUIRE_REVS_ALIVE_DESC = "Require the rev leaders to be captured alive in RP Rev, rather than either dead or captured."*/
|
||||
New()
|
||||
. = ..()
|
||||
settings = vars.Copy()
|
||||
|
||||
var/datum/D = new() //Ensure only unique vars are put through by making a datum and removing all common vars.
|
||||
for(var/V in D.vars)
|
||||
settings -= V
|
||||
|
||||
for(var/V in settings)
|
||||
if(findtextEx(V,"_RANDOM") || findtextEx(V,"_DESC") || findtextEx(V,"_METHOD"))
|
||||
settings -= V
|
||||
|
||||
settings -= "settings"
|
||||
settings -= "bitflags"
|
||||
settings -= "plc"
|
||||
|
||||
proc/ChangeSettingsDialog(mob/user,list/L)
|
||||
//var/which = input(user,"Choose a setting:") in L
|
||||
var/dat = ""
|
||||
for(var/ch in L)
|
||||
if(findtextEx(ch,"_RANDOM") || findtextEx(ch,"_DESC") || findtextEx(ch,"_METHOD") || findtextEx(ch,"_NAME")) continue
|
||||
var/vw
|
||||
var/vw_desc = "No Description."
|
||||
var/vw_name = ch
|
||||
if(ch in plc.settings)
|
||||
vw = plc.vars[ch]
|
||||
if("[ch]_DESC" in plc.vars) vw_desc = plc.vars["[ch]_DESC"]
|
||||
if("[ch]_NAME" in plc.vars) vw_name = plc.vars["[ch]_NAME"]
|
||||
else
|
||||
vw = vars[ch]
|
||||
if("[ch]_DESC" in vars) vw_desc = vars["[ch]_DESC"]
|
||||
if("[ch]_NAME" in plc.vars) vw_name = vars["[ch]_NAME"]
|
||||
dat += "<b>[vw_name] = [vw]</b> <A href='?src=\ref[src];changevar=[ch]'>\[Change\]</A><br>"
|
||||
dat += "<i>[vw_desc]</i><br><br>"
|
||||
user << browse(dat,"window=settings")
|
||||
Topic(href,href_list)
|
||||
if("changevar" in href_list)
|
||||
ChangeSetting(usr,href_list["changevar"])
|
||||
proc/ChangeSetting(mob/user,ch)
|
||||
var/vw
|
||||
var/how = "Text"
|
||||
if(ch in plc.settings)
|
||||
vw = plc.vars[ch]
|
||||
if("[ch]_METHOD" in vars)
|
||||
how = plc.vars["[ch]_METHOD"]
|
||||
else
|
||||
if(isnum(vw))
|
||||
how = "Numeric"
|
||||
else
|
||||
how = "Text"
|
||||
else
|
||||
vw = vars[ch]
|
||||
if("[ch]_METHOD" in vars)
|
||||
how = vars["[ch]_METHOD"]
|
||||
else
|
||||
if(isnum(vw))
|
||||
how = "Numeric"
|
||||
else
|
||||
how = "Text"
|
||||
var/newvar = vw
|
||||
switch(how)
|
||||
if("Numeric")
|
||||
newvar = input(user,"Enter a number:","Settings",newvar) as num
|
||||
if("Bit Flag")
|
||||
var/flag = input(user,"Toggle which bit?","Settings") in bitflags
|
||||
flag = text2num(flag)
|
||||
if(newvar & flag)
|
||||
newvar &= ~flag
|
||||
else
|
||||
newvar |= flag
|
||||
if("Toggle")
|
||||
newvar = !newvar
|
||||
if("Text")
|
||||
newvar = input(user,"Enter a string:","Settings",newvar) as text
|
||||
if("Long Text")
|
||||
newvar = input(user,"Enter text:","Settings",newvar) as message
|
||||
vw = newvar
|
||||
if(ch in plc.settings)
|
||||
plc.vars[ch] = vw
|
||||
else
|
||||
vars[ch] = vw
|
||||
if(how == "Toggle")
|
||||
newvar = (newvar?"ON":"OFF")
|
||||
world << "\blue <b>[key_name(user)] changed the setting [ch] to [newvar].</b>"
|
||||
//user << "[which] has been changed to [newvar]."
|
||||
if(ch in plc.settings)
|
||||
ChangeSettingsDialog(user,plc.settings)
|
||||
else
|
||||
ChangeSettingsDialog(user,settings)
|
||||
proc/RandomizeWithProbability()
|
||||
for(var/V in settings)
|
||||
var/newvalue
|
||||
if("[V]_RANDOM" in vars)
|
||||
if(isnum(vars["[V]_RANDOM"]))
|
||||
newvalue = prob(vars["[V]_RANDOM"])
|
||||
else if(istext(vars["[V]_RANDOM"]))
|
||||
newvalue = roll(vars["[V]_RANDOM"])
|
||||
else
|
||||
newvalue = vars[V]
|
||||
V = newvalue
|
||||
|
||||
proc/ChangePlasma()
|
||||
for(var/V in plc.settings)
|
||||
plc.Randomize(V)
|
||||
////world << "Plasma randomized."
|
||||
|
||||
proc/SetDefault(def)
|
||||
switch(def)
|
||||
if("Original")
|
||||
plc.CLOTH_CONTAMINATION = 0 //If this is on, plasma does damage by getting into cloth.
|
||||
|
||||
plc.ALL_ITEM_CONTAMINATION = 0 //If this is on, any item can be contaminated, so suits and tools must be discarded or
|
||||
|
||||
plc.PLASMAGUARD_ONLY = 0
|
||||
|
||||
//plc.CANISTER_CORROSION = 0 //If this is on, plasma must be stored in orange tanks and canisters,
|
||||
|
||||
plc.GENETIC_CORRUPTION = 0 //Chance of genetic corruption as well as toxic damage, X in 1000.
|
||||
|
||||
plc.SKIN_BURNS = 0 //Plasma has an effect similar to mustard gas on the un-suited.
|
||||
|
||||
//plc.PLASMA_INJECTS_TOXINS = 0 //Plasma damage injects the toxins chemical to do damage over time.
|
||||
|
||||
plc.EYE_BURNS = 0 //Plasma burns the eyes of anyone not wearing eye protection.
|
||||
|
||||
//plc.N2O_REACTION = 0 //Plasma can react with N2O, making sparks and starting a fire if levels are high.
|
||||
|
||||
//plc.PLASMA_COLOR = "onturf" //Plasma can change colors yaaaay!
|
||||
|
||||
//plc.PLASMA_DMG_OFFSET = 1
|
||||
//plc.PLASMA_DMG_QUOTIENT = 10
|
||||
|
||||
plc.CONTAMINATION_LOSS = 0
|
||||
if("Hazard-Low")
|
||||
plc.CLOTH_CONTAMINATION = 1 //If this is on, plasma does damage by getting into cloth.
|
||||
|
||||
plc.ALL_ITEM_CONTAMINATION = 0 //If this is on, any item can be contaminated, so suits and tools must be discarded or
|
||||
|
||||
plc.PLASMAGUARD_ONLY = 0
|
||||
|
||||
// plc.CANISTER_CORROSION = 0 //If this is on, plasma must be stored in orange tanks and canisters,
|
||||
|
||||
plc.GENETIC_CORRUPTION = 0 //Chance of genetic corruption as well as toxic damage, X in 1000.
|
||||
|
||||
plc.SKIN_BURNS = 0 //Plasma has an effect similar to mustard gas on the un-suited.
|
||||
|
||||
// plc.PLASMA_INJECTS_TOXINS = 0 //Plasma damage injects the toxins chemical to do damage over time.
|
||||
|
||||
plc.EYE_BURNS = 0 //Plasma burns the eyes of anyone not wearing eye protection.
|
||||
|
||||
// plc.N2O_REACTION = 0 //Plasma can react with N2O, making sparks and starting a fire if levels are high.
|
||||
|
||||
// plc.PLASMA_COLOR = "onturf" //RBPYB
|
||||
|
||||
//if(prob(20))
|
||||
// plc.PLASMA_COLOR = pick("red","yellow","blue","purple")
|
||||
|
||||
//plc.PLASMA_DMG_OFFSET = 1.5
|
||||
//plc.PLASMA_DMG_QUOTIENT = 8
|
||||
|
||||
plc.CONTAMINATION_LOSS = 0.01
|
||||
|
||||
var/s = pick(plc.settings)
|
||||
plc.Randomize(s)
|
||||
|
||||
if("Hazard-High")
|
||||
plc.CLOTH_CONTAMINATION = 1 //If this is on, plasma does damage by getting into cloth.
|
||||
|
||||
plc.ALL_ITEM_CONTAMINATION = 0 //If this is on, any item can be contaminated, so suits and tools must be discarded or
|
||||
|
||||
plc.PLASMAGUARD_ONLY = 0
|
||||
|
||||
// plc.CANISTER_CORROSION = 1 //If this is on, plasma must be stored in orange tanks and canisters,
|
||||
|
||||
plc.GENETIC_CORRUPTION = 0 //Chance of genetic corruption as well as toxic damage, X in 1000.
|
||||
|
||||
plc.SKIN_BURNS = 0 //Plasma has an effect similar to mustard gas on the un-suited.
|
||||
|
||||
// plc.PLASMA_INJECTS_TOXINS = 0 //Plasma damage injects the toxins chemical to do damage over time.
|
||||
|
||||
plc.EYE_BURNS = 0 //Plasma burns the eyes of anyone not wearing eye protection.
|
||||
|
||||
// plc.N2O_REACTION = 0 //Plasma can react with N2O, making sparks and starting a fire if levels are high.
|
||||
|
||||
// plc.PLASMA_COLOR = "onturf"//pick("red","yellow","blue","purple") //RBPYB
|
||||
|
||||
//plc.PLASMA_DMG_OFFSET = 3
|
||||
//plc.PLASMA_DMG_QUOTIENT = 5
|
||||
|
||||
plc.CONTAMINATION_LOSS = 0.05
|
||||
|
||||
for(var/i = rand(3,5),i>0,i--)
|
||||
var/s = pick(plc.settings)
|
||||
plc.Randomize(s)
|
||||
|
||||
if("Everything")
|
||||
plc.CLOTH_CONTAMINATION = 1 //If this is on, plasma does damage by getting into cloth.
|
||||
|
||||
plc.ALL_ITEM_CONTAMINATION = 1 //If this is on, any item can be contaminated, so suits and tools must be discarded or ELSE
|
||||
|
||||
plc.PLASMAGUARD_ONLY = 1
|
||||
|
||||
// plc.CANISTER_CORROSION = 1 //If this is on, plasma must be stored in orange tanks and canisters,
|
||||
|
||||
plc.GENETIC_CORRUPTION = 5 //Chance of genetic corruption as well as toxic damage, X in 1000.
|
||||
|
||||
plc.SKIN_BURNS = 1 //Plasma has an effect similar to mustard gas on the un-suited.
|
||||
|
||||
// plc.PLASMA_INJECTS_TOXINS = 1 //Plasma damage injects the toxins chemical to do damage over time.
|
||||
|
||||
plc.EYE_BURNS = 1 //Plasma burns the eyes of anyone not wearing eye protection.
|
||||
|
||||
// plc.N2O_REACTION = 1 //Plasma can react with N2O, making sparks and starting a fire if levels are high.
|
||||
|
||||
// plc.PLASMA_COLOR = "onturf" //RBPYB
|
||||
|
||||
//plc.PLASMA_DMG_OFFSET = 3
|
||||
//plc.PLASMA_DMG_QUOTIENT = 5
|
||||
|
||||
plc.CONTAMINATION_LOSS = 0.02
|
||||
/////world << "Plasma color updated."
|
||||
|
||||
pl_control
|
||||
var/list/settings = list()
|
||||
New()
|
||||
. = ..()
|
||||
settings = vars.Copy()
|
||||
|
||||
var/datum/D = new() //Ensure only unique vars are put through by making a datum and removing all common vars.
|
||||
for(var/V in D.vars)
|
||||
settings -= V
|
||||
|
||||
for(var/V in settings)
|
||||
if(findtextEx(V,"_RANDOM") || findtextEx(V,"_DESC"))
|
||||
settings -= V
|
||||
|
||||
settings -= "settings"
|
||||
proc/Randomize(V)
|
||||
//world << "Randomizing [V]"
|
||||
var/newvalue
|
||||
if("[V]_RANDOM" in vars)
|
||||
if(isnum(vars["[V]_RANDOM"]))
|
||||
newvalue = prob(vars["[V]_RANDOM"])
|
||||
if(newvalue)
|
||||
//world << "Probability [vars["[V]_RANDOM"]]%: Success."
|
||||
else
|
||||
//world << "Probability [vars["[V]_RANDOM"]]%: Failure."
|
||||
else if(istext(vars["[V]_RANDOM"]))
|
||||
var/txt = vars["[V]_RANDOM"]
|
||||
if(findtextEx(txt,"PROB"))
|
||||
//world << "Probability/Roll Combo \..."
|
||||
txt = dd_text2list(txt,"/")
|
||||
txt[1] = dd_replacetext(txt[1],"PROB","")
|
||||
var/p = text2num(txt[1])
|
||||
var/r = txt[2]
|
||||
//world << "Prob:[p]% Roll:[r]"
|
||||
if(prob(p))
|
||||
newvalue = roll(r)
|
||||
//world << "Success. New value: [newvalue]"
|
||||
else
|
||||
newvalue = vars[V]
|
||||
//world << "Probability check failed."
|
||||
else if(findtextEx(txt,"PICK"))
|
||||
txt = dd_replacetext(txt,"PICK","")
|
||||
//world << "Pick: [txt]"
|
||||
txt = dd_text2list(txt,",")
|
||||
newvalue = pick(txt)
|
||||
//world << "Picked: [newvalue]"
|
||||
else
|
||||
newvalue = roll(txt)
|
||||
//world << "Roll: [txt] - [newvalue]"
|
||||
else
|
||||
newvalue = vars[V]
|
||||
vars[V] = newvalue
|
||||
////world << "Plasma color updated."
|
||||
BIN
icons/misc/debug_connect.dmi
Normal file
BIN
icons/misc/debug_connect.dmi
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 223 B |
BIN
icons/misc/debug_group.dmi
Normal file
BIN
icons/misc/debug_group.dmi
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 225 B |
BIN
icons/misc/debug_space.dmi
Normal file
BIN
icons/misc/debug_space.dmi
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 222 B |
Reference in New Issue
Block a user