mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-08-30 00:29:02 +01:00
Slightly optimizes reagent splashing (#70709)
* Slightly optimizes reagent splashing Ok so like, before, splashing a reagent performed a rudimentary floodfill based off atmos connectivity. This was really slow, because it did it using orange(), and repeated orange()s to cut out JUST the rim, because we needed to ensure things were ordered. I've changed this to use floodfill. I've also moved some code that was in a second loop into the first one, and replaced a repeated in check with a single use of & This is still not optimal for large ranges, because we filter by connectivity first and THEN view, but it's faster for smaller ones. BTW I'm also capping the max spread range at 40x40 tiles. If you want more then 1600 you can rot in hell. This takes the (uncapped range) cost of deconstructing a highcap tank from 40 seconds to 0.16. I hate this codebase * god damn it Co-authored-by: san7890 <the@san7890.com> * whoops that's redundant Co-authored-by: san7890 <the@san7890.com>
This commit is contained in:
co-authored by
san7890
parent
b5cbdeb3ea
commit
3582aa77bb
@@ -75,51 +75,40 @@
|
||||
* Arguments:
|
||||
* - [source][/datum/reagents]: The reagents to spread around.
|
||||
* - [epicenter][/atom]: The epicenter/source location of the reagent spread.
|
||||
* - spread_range: The range in which to spread the reagents.
|
||||
* - spread_range: The range in which to spread the reagents. Will not go over 20
|
||||
*/
|
||||
/proc/spread_reagents(datum/reagents/source, atom/epicenter, spread_range)
|
||||
spread_range = min(spread_range, 20) // Fuck off with trying to do more then this
|
||||
var/datum/effect_system/steam_spread/steam = new /datum/effect_system/steam_spread()
|
||||
steam.set_up(10, 0, epicenter)
|
||||
steam.attach(epicenter)
|
||||
steam.start()
|
||||
|
||||
|
||||
var/list/viewable = view(spread_range, epicenter)
|
||||
var/list/accessible = list(epicenter)
|
||||
for(var/i in 1 to spread_range)
|
||||
var/list/turflist = list()
|
||||
for(var/turf/T in (orange(i, epicenter) - orange(i-1, epicenter)))
|
||||
turflist |= T
|
||||
for(var/turf/T in turflist)
|
||||
if(!(get_dir(T,epicenter) in GLOB.cardinals) && (abs(T.x - epicenter.x) == abs(T.y - epicenter.y) ))
|
||||
turflist.Remove(T)
|
||||
turflist.Add(T) // we move the purely diagonal turfs to the end of the list.
|
||||
for(var/turf/T in turflist)
|
||||
if(accessible[T])
|
||||
continue
|
||||
for(var/thing in T.get_atmos_adjacent_turfs(alldir = TRUE))
|
||||
var/turf/NT = thing
|
||||
if(!(NT in accessible))
|
||||
continue
|
||||
if(!(get_dir(T,NT) in GLOB.cardinals))
|
||||
continue
|
||||
accessible[T] = 1
|
||||
break
|
||||
|
||||
// This is a basic floodfill algorithm of atmos connected tiles
|
||||
// Turfs will be stored in the form turf -> TRUE
|
||||
var/chem_temp = source.chem_temp
|
||||
var/list/reactable = accessible
|
||||
for(var/turf/T in accessible)
|
||||
reactable += T
|
||||
for(var/atom/A in T.get_all_contents())
|
||||
if(!(A in viewable))
|
||||
var/hot_chem = chem_temp >= 300
|
||||
var/list/turflist = list()
|
||||
var/list/reactable = list()
|
||||
turflist[epicenter] = TRUE
|
||||
for(var/i = 1; i <= length(turflist); i++)
|
||||
var/turf/valid_step = turflist[i]
|
||||
if(get_dist(valid_step, epicenter) > spread_range) // We are over threshold, don't add anything new and just keep goin
|
||||
turflist.Cut(i, i+1)
|
||||
i--
|
||||
continue
|
||||
|
||||
for(var/turf/lad as anything in valid_step.atmos_adjacent_turfs)
|
||||
if(turflist[lad])
|
||||
continue
|
||||
reactable |= A
|
||||
if(chem_temp >= 300)
|
||||
T.hotspot_expose(chem_temp*2, 5)
|
||||
if(!reactable.len) //Nothing to react with. Probably means we're in nullspace.
|
||||
return
|
||||
for(var/thing in reactable)
|
||||
var/atom/A = thing
|
||||
var/distance = max(1, get_dist(A, epicenter))
|
||||
turflist[lad] = TRUE
|
||||
|
||||
reactable += valid_step.get_all_contents() // Yes this means multitile objects double react. I don't care. skill issue
|
||||
if(hot_chem)
|
||||
valid_step.hotspot_expose(chem_temp*2, 5)
|
||||
|
||||
// Remove anything we can't see
|
||||
for(var/atom/thing as anything in (dview(spread_range, epicenter) & reactable))
|
||||
var/distance = max(1, get_dist(thing, epicenter))
|
||||
var/fraction = 0.5 / (2 ** distance) //50/25/12/6... for a 200u splash, 25/12/6/3... for a 100u, 12/6/3/1 for a 50u
|
||||
source.expose(A, TOUCH, fraction)
|
||||
source.expose(thing, TOUCH, fraction)
|
||||
|
||||
Reference in New Issue
Block a user