mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-07-12 08:36:00 +01:00
[MIRROR] Slightly optimize shroom spreading code (#867)
* Slightly optimize shroom spreading code (#53652) There were some recent lag events on the servers caused by the timer subsystem jamming up with glowshroom timers. I whined about this but nobody did anything so (Thanos "Fine... I'll do it myself" GIF) There are a few changes here, first we collect the potential turfs for the view call in a single pass, not once per yield run. Second we don't run a second view(1) on every single potential turf, instead we try to randomly pick a turf 3 times during yield phase and check the view then. If we fail to find a potential location then we bail out of that yield phase. This is a tradeoff between processing time spent finding locations and the chance that the glowshroom fails to spread. Finally, we have maximum limit on how many times a glowshroom fails to spread, if it fails to spread at least 5 times over any iteration, it stops processing for spread completely. As a bonus, the timers have been made unique, so we don't accidentally generate multiple timers for a single shroom, other than the two it already needs. This code would benefit from being a separate subsystem and grouping, generations of the plants together as a single ticking entity and just spreading from selected edge plants. However I don't particularly feel like plumbing that together, so this will suit for now. * Slightly optimize shroom spreading code Co-authored-by: oranges <email@oranges.net.nz>
This commit is contained in:
@@ -21,6 +21,9 @@
|
||||
var/spreadIntoAdjacentChance = 75
|
||||
/// Internal seed of the glowshroom, stats are stored here
|
||||
var/obj/item/seeds/myseed = /obj/item/seeds/glowshroom
|
||||
|
||||
/// If we fail to spread this many times we stop trying to spread
|
||||
var/max_failed_spreads = 5
|
||||
/// Turfs where the glowshroom cannot spread to
|
||||
var/static/list/blacklisted_glowshroom_turfs = typecacheof(list(
|
||||
/turf/open/lava,
|
||||
@@ -92,40 +95,60 @@
|
||||
else //if on the floor, glowshroom on-floor sprite
|
||||
icon_state = base_icon_state
|
||||
|
||||
addtimer(CALLBACK(src, .proc/Spread), delay_spread)
|
||||
addtimer(CALLBACK(src, .proc/Decay), delay_decay, FALSE) // Start decaying the plant
|
||||
|
||||
addtimer(CALLBACK(src, .proc/Spread), delay_spread, TIMER_UNIQUE|TIMER_NO_HASH_WAIT)
|
||||
addtimer(CALLBACK(src, .proc/Decay), delay_decay, TIMER_UNIQUE|TIMER_NO_HASH_WAIT)
|
||||
|
||||
/**
|
||||
* Causes glowshroom spreading across the floor/walls.
|
||||
*/
|
||||
|
||||
/obj/structure/glowshroom/proc/Spread()
|
||||
|
||||
//We could be deleted at any point and the timers might not be cleaned up
|
||||
if(QDELETED(src))
|
||||
return
|
||||
|
||||
var/turf/ownturf = get_turf(src)
|
||||
var/shrooms_planted = 0
|
||||
var/list/possibleLocs = list()
|
||||
//Lets collect a list of possible viewable turfs BEFORE we iterate for yield so we don't call view multiple
|
||||
//times when there's no real chance of the viewable range changing, really you could do this once on item
|
||||
//spawn and most people probably would not notice.
|
||||
for(var/turf/open/floor/earth in view(3,src))
|
||||
if(is_type_in_typecache(earth, blacklisted_glowshroom_turfs))
|
||||
continue
|
||||
if(!ownturf.CanAtmosPass(earth))
|
||||
continue
|
||||
possibleLocs += earth
|
||||
|
||||
//Lets not even try to spawn again if somehow we have ZERO possible locations
|
||||
if(!possibleLocs.len)
|
||||
return
|
||||
|
||||
for(var/i in 1 to myseed.yield)
|
||||
var/chance_stats = ((myseed.potency + myseed.endurance * 2) * 0.2) // Chance of generating a new mushroom based on stats
|
||||
var/chance_generation = (100 / (generation * generation)) // This formula gives you diminishing returns based on generation. 100% with 1st gen, decreasing to 25%, 11%, 6, 4, 2...
|
||||
if(prob(max(chance_stats, chance_generation))) // Whatever is the higher chance we use it
|
||||
var/list/possibleLocs = list()
|
||||
var/spreadsIntoAdjacent = FALSE
|
||||
|
||||
if(prob(spreadIntoAdjacentChance))
|
||||
spreadsIntoAdjacent = TRUE
|
||||
// Whatever is the higher chance we use it (this is really stupid as the diminishing returns are effectively pointless???)
|
||||
if(prob(max(chance_stats, chance_generation)))
|
||||
var/spreadsIntoAdjacent = prob(spreadIntoAdjacentChance)
|
||||
var/turf/newLoc = null
|
||||
|
||||
for(var/turf/open/floor/earth in view(3,src))
|
||||
if(is_type_in_typecache(earth, blacklisted_glowshroom_turfs))
|
||||
continue
|
||||
if(!ownturf.CanAtmosPass(earth))
|
||||
continue
|
||||
if(spreadsIntoAdjacent || !locate(/obj/structure/glowshroom) in view(1,earth))
|
||||
possibleLocs += earth
|
||||
CHECK_TICK
|
||||
//Try three random locations to spawn before giving up tradeoff
|
||||
//between running view(1, earth) on every single collected possibleLoc
|
||||
//and failing to spread if we get 3 bad picks, which should only be a problem
|
||||
//if there's a lot of glow shroom clustered about
|
||||
for(var/Potato in 1 to 3)
|
||||
var/turf/possibleLoc = pick(possibleLocs)
|
||||
if(spreadsIntoAdjacent || !locate(/obj/structure/glowshroom) in view(1,possibleLoc))
|
||||
newLoc = possibleLoc
|
||||
break
|
||||
|
||||
if(!possibleLocs.len)
|
||||
//We failed to find any location, skip trying to yield
|
||||
if(newLoc == null)
|
||||
break
|
||||
|
||||
var/turf/newLoc = pick(possibleLocs)
|
||||
|
||||
var/shroomCount = 0 //hacky
|
||||
var/placeCount = 1
|
||||
for(var/obj/structure/glowshroom/shroom in newLoc)
|
||||
@@ -144,10 +167,14 @@
|
||||
child.generation = generation + 1
|
||||
shrooms_planted++
|
||||
|
||||
CHECK_TICK
|
||||
if(shrooms_planted <= myseed.yield) //if we didn't get all possible shrooms planted, try again later
|
||||
if(!shrooms_planted)
|
||||
max_failed_spreads--
|
||||
|
||||
//if we didn't get all possible shrooms planted or we haven't failed to spread at least 5 times then try to spread again later
|
||||
if( (shrooms_planted <= myseed.yield) && (max_failed_spreads >= 0) )
|
||||
myseed.adjust_yield(-shrooms_planted)
|
||||
addtimer(CALLBACK(src, .proc/Spread), delay_spread)
|
||||
//Lets make this a unique hash
|
||||
addtimer(CALLBACK(src, .proc/Spread), delay_spread, TIMER_UNIQUE|TIMER_NO_HASH_WAIT)
|
||||
|
||||
/obj/structure/glowshroom/proc/CalcDir(turf/location = loc)
|
||||
var/direction = 16
|
||||
@@ -194,7 +221,7 @@
|
||||
else // Timed decay
|
||||
myseed.endurance -= 1
|
||||
if (myseed.endurance > 0)
|
||||
addtimer(CALLBACK(src, .proc/Decay), delay_decay, FALSE) // Recall decay timer
|
||||
addtimer(CALLBACK(src, .proc/Decay), delay_decay, TIMER_UNIQUE|TIMER_NO_HASH_WAIT) // Recall decay timer
|
||||
return
|
||||
if (myseed.endurance < 1) // Plant is gone
|
||||
qdel(src)
|
||||
|
||||
Reference in New Issue
Block a user