mirror of
https://github.com/goonstation/goonstation-2020.git
synced 2026-07-11 07:02:20 +01:00
263 lines
8.7 KiB
Plaintext
263 lines
8.7 KiB
Plaintext
///////////////////
|
|
//Turf Procs/Vars//
|
|
///////////////////
|
|
|
|
/turf/var/obj/fluid/active_liquid
|
|
|
|
//this is messy!
|
|
//this is for turf/space/fluid oceans. Using this in place of turf/canpass() because this one can account for shitt like windows and tables.
|
|
/turf/proc/ocean_canpass()
|
|
if( density )
|
|
return 0
|
|
for( var/A in contents )
|
|
var/atom/thing = A
|
|
if (!A) continue
|
|
if(IS_SOLID_TO_FLUID(thing) && thing.density) return 0 // && !istype(thing,/obj/grille) && !istype(thing,/obj/table) && !istype(thing,/obj/structure/girder)) return 0
|
|
LAGCHECK(LAG_LOW)
|
|
return 1
|
|
|
|
turf/simulated/floor/plating/airless/ocean_canpass()
|
|
.= 0
|
|
|
|
/turf/selftilenotify()
|
|
if (src.active_liquid && src.active_liquid.group && !canpass())
|
|
src.active_liquid.group.displace(src.active_liquid)
|
|
else
|
|
///HEY HEY LOOK AT ME TODO : This is kind of a band-aid. I'm not sure why, but tilenotify() doesn't trigger when it should sometimes. do this to be absolutely sure!
|
|
for (var/dir in cardinal)
|
|
var/turf/T = get_step(src, dir)
|
|
if(T.active_liquid)
|
|
T.active_liquid.blocked_dirs = 0
|
|
if (T.active_liquid.group && !T.active_liquid.group.updating)
|
|
T.active_liquid.group.update_loop()
|
|
break
|
|
if(T.active_airborne_liquid)
|
|
T.active_airborne_liquid.blocked_dirs = 0
|
|
if (T.active_airborne_liquid.group && !T.active_airborne_liquid.group.updating)
|
|
T.active_airborne_liquid.group.update_loop()
|
|
break
|
|
|
|
return ..()
|
|
|
|
/turf/tilenotify()
|
|
if(src.active_liquid)
|
|
src.active_liquid.blocked_dirs = 0
|
|
if (src.active_liquid.group && !src.active_liquid.group.updating)
|
|
src.active_liquid.group.update_loop()
|
|
if(src.active_airborne_liquid)
|
|
src.active_airborne_liquid.blocked_dirs = 0
|
|
if (src.active_airborne_liquid.group && !src.active_airborne_liquid.group.updating)
|
|
src.active_airborne_liquid.group.update_loop()
|
|
return ..()
|
|
|
|
|
|
/turf/proc/fluid_react(var/datum/reagents/R, var/react_volume, var/airborne = 0) //this should happen whenever a liquid reagent hits a simulated tile
|
|
LAGCHECK(LAG_MED)
|
|
if (react_volume <= 0) return
|
|
if (!IS_VALID_FLUIDREACT_TURF(src)) return
|
|
|
|
if (airborne)
|
|
for(var/reagent_id in R.reagent_list)
|
|
if (ban_from_airborne_fluid.Find(reagent_id)) return
|
|
LAGCHECK(LAG_MED)
|
|
else
|
|
for(var/reagent_id in R.reagent_list)
|
|
if (ban_from_fluid.Find(reagent_id)) return
|
|
LAGCHECK(LAG_MED)
|
|
|
|
var/datum/fluid_group/FG
|
|
var/obj/fluid/F
|
|
var/fluid_and_group_already_exist = 0
|
|
|
|
if (airborne)
|
|
if (!src.active_airborne_liquid)
|
|
FG = new /datum/fluid_group/airborne
|
|
F = unpool(/obj/fluid/airborne)
|
|
src.active_airborne_liquid = F
|
|
F.set_up(src)
|
|
if (react_volume == 0)
|
|
react_volume = 1
|
|
else
|
|
F = src.active_airborne_liquid
|
|
if (F.group)
|
|
FG = F.group
|
|
fluid_and_group_already_exist = 1
|
|
else
|
|
FG = new /datum/fluid_group/airborne
|
|
if (react_volume == 0)
|
|
react_volume = 1
|
|
else
|
|
if (!src.active_liquid)
|
|
FG = new
|
|
F = unpool(/obj/fluid)
|
|
src.active_liquid = F
|
|
F.set_up(src)
|
|
if (react_volume == 0)
|
|
react_volume = 1
|
|
else
|
|
F = src.active_liquid
|
|
if (F.group)
|
|
FG = F.group
|
|
fluid_and_group_already_exist = 1
|
|
else
|
|
FG = new
|
|
if (react_volume == 0)
|
|
react_volume = 1
|
|
|
|
R.trans_to_direct(FG.reagents,react_volume)
|
|
FG.add(F, react_volume, guarantee_is_member = fluid_and_group_already_exist)
|
|
|
|
if (!airborne)
|
|
var/turf/simulated/floor/T = src
|
|
if (T.messy <= 0) return
|
|
if (istype(T))
|
|
var/found_cleanable = 0
|
|
for (var/obj/decal/cleanable/C in T)
|
|
if (!T.cleanable_fluid_react(C, 1)) // Some cleanables need special treatment
|
|
found_cleanable = 1 //there exists a cleanable without a special case
|
|
LAGCHECK(LAG_LOW)
|
|
if (found_cleanable)
|
|
T.cleanable_fluid_react(0,1)
|
|
|
|
/turf/proc/fluid_react_single(var/reagent_name, var/react_volume, var/airborne = 0) //same as the above, but using a reagent_id instead of a datum
|
|
LAGCHECK(LAG_MED)
|
|
if (react_volume <= 0) return
|
|
if (!IS_VALID_FLUIDREACT_TURF(src)) return
|
|
|
|
if (airborne)
|
|
if (ban_from_airborne_fluid.Find(reagent_name)) return
|
|
else
|
|
if (ban_from_fluid.Find(reagent_name)) return
|
|
LAGCHECK(LAG_LOW)
|
|
|
|
var/datum/fluid_group/FG
|
|
var/obj/fluid/F
|
|
var/fluid_and_group_already_exist = 0
|
|
|
|
|
|
if (airborne)
|
|
if (!src.active_airborne_liquid)
|
|
FG = new /datum/fluid_group/airborne
|
|
F = unpool(/obj/fluid/airborne)
|
|
src.active_airborne_liquid = F
|
|
F.set_up(src)
|
|
if (react_volume == 0)
|
|
react_volume = 1
|
|
else
|
|
F = src.active_airborne_liquid
|
|
if (F.group)
|
|
FG = F.group
|
|
fluid_and_group_already_exist = 1
|
|
else
|
|
FG = new /datum/fluid_group/airborne
|
|
if (react_volume == 0)
|
|
react_volume = 1
|
|
else
|
|
if (!src.active_liquid)
|
|
FG = new
|
|
F = unpool(/obj/fluid)
|
|
src.active_liquid = F
|
|
F.set_up(src)
|
|
if (react_volume == 0)
|
|
react_volume = 1
|
|
else
|
|
F = src.active_liquid
|
|
if (F.group)
|
|
FG = F.group
|
|
fluid_and_group_already_exist = 1
|
|
else
|
|
FG = new
|
|
if (react_volume == 0)
|
|
react_volume = 1
|
|
|
|
|
|
FG.reagents.add_reagent(reagent_name,react_volume)
|
|
FG.add(F, react_volume, guarantee_is_member = fluid_and_group_already_exist)
|
|
F.done_init()
|
|
.= F
|
|
|
|
if (!airborne)
|
|
var/turf/simulated/floor/T = src
|
|
if (T.messy <= 0) return
|
|
if (istype(T))
|
|
var/found_cleanable = 0
|
|
for (var/obj/decal/cleanable/C in T)
|
|
if (!T.cleanable_fluid_react(C, 1))
|
|
found_cleanable = 1
|
|
LAGCHECK(LAG_LOW)
|
|
if (found_cleanable)
|
|
T.cleanable_fluid_react(0,1)
|
|
|
|
|
|
/turf/proc/react_all_cleanables() //Same procedure called in fluid_react and fluid_react_single. copypasted cause i dont wanna proc call overhead up in hea
|
|
|
|
/turf/simulated/floor/react_all_cleanables() //Same procedure called in fluid_react and fluid_react_single. copypasted cause i dont wanna proc call overhead up in hea
|
|
if (src.messy <= 0) return //hey this is CLEAN so don't even bother looping through contents, thanks!!
|
|
var/found_cleanable = 0
|
|
for (var/obj/decal/cleanable/C in src)
|
|
if (!src.cleanable_fluid_react(C, 1)) // Some cleanables need special treatment
|
|
found_cleanable = 1 //there exists a cleanable without a special case
|
|
LAGCHECK(LAG_LOW)
|
|
if (found_cleanable)
|
|
src.cleanable_fluid_react(0,1)
|
|
|
|
//called whenever a cleanable is spawned. Returns 1 on success
|
|
//grab_any_amount will be True when a fluid spreads onto a tile that may have cleanables on it
|
|
/turf/simulated/proc/cleanable_fluid_react(var/obj/decal/cleanable/possible_cleanable = 0, var/grab_any_amount = 0)
|
|
LAGCHECK(LAG_MED)
|
|
if (!IS_VALID_FLUIDREACT_TURF(src)) return
|
|
//if possible_cleanable has a value, handle exclusively this decal. don't search thru the turf.
|
|
if (possible_cleanable)
|
|
if (possible_cleanable.qdeled || possible_cleanable.pooled) return
|
|
if (istype(possible_cleanable, /obj/decal/cleanable/blood/dynamic))
|
|
var/obj/decal/cleanable/blood/dynamic/blood = possible_cleanable
|
|
var/blood_dna = blood.blood_DNA
|
|
var/blood_type = blood.blood_type
|
|
var/is_tracks = istype(possible_cleanable,/obj/decal/cleanable/blood/dynamic/tracks)
|
|
if (blood.blood_volume >= 13 || src.active_liquid || grab_any_amount)
|
|
if (blood.reagents)
|
|
var/datum/reagents/R = new(blood.reagents.maximum_volume) //Store reagents, delete cleanable, and then fluid react. prevents recursion
|
|
blood.reagents.copy_to(R)
|
|
var/blood_volume = blood.blood_volume
|
|
blood.clean_forensic()
|
|
src.fluid_react(R,is_tracks ? 0 : blood_volume)
|
|
else
|
|
var/reagent = blood.sample_reagent
|
|
var/amt = blood.blood_volume
|
|
blood.clean_forensic()
|
|
src.fluid_react_single(reagent,is_tracks ? 0 : amt)
|
|
|
|
if (src.active_liquid)
|
|
src.active_liquid.blood_DNA = blood_dna
|
|
src.active_liquid.blood_type = blood_type
|
|
return 1
|
|
return 0
|
|
|
|
//all right, tally up the cleanables and attempt to call fluid_reacts on them
|
|
var/list/cleanables = list()
|
|
for (var/obj/decal/cleanable/C in src)
|
|
if (C.qdeled || C.pooled) continue
|
|
//if (C.dry) continue
|
|
if (istype(C,/obj/decal/cleanable/blood/dynamic)) continue // handled above
|
|
if (!C.can_fluid_absorb) continue
|
|
cleanables += C
|
|
|
|
if (!src.active_liquid && (cleanables.len < 3 && !grab_any_amount))
|
|
return 0 //If the tile has an active liquid already, there is no requirement
|
|
|
|
for (var/obj/decal/cleanable/C in cleanables)
|
|
LAGCHECK(LAG_LOW)
|
|
if (C && C.reagents)
|
|
for(var/reagent_id in C.reagents.reagent_list)
|
|
if (ban_stacking_into_fluid.Find(reagent_id)) return
|
|
var/datum/reagents/R = new(C.reagents.maximum_volume) //Store reagents, delete cleanable, and then fluid react. prevents recursion
|
|
C.reagents.copy_to(R)
|
|
C.clean_forensic()
|
|
src.fluid_react(R, R.total_volume)
|
|
else if (C && C.can_sample && C.sample_reagent)
|
|
if ((!grab_any_amount && ban_stacking_into_fluid.Find(C.sample_reagent)) || ban_from_fluid.Find(C.sample_reagent)) return
|
|
var/sample = C.sample_reagent
|
|
var/amt = C.sample_amt
|
|
C.clean_forensic()
|
|
src.fluid_react_single(sample, amt)
|
|
return 1 |