mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-08-22 04:30:44 +01:00
[MIRROR] Completely refactors glowshroom spreading and makes them self-decay faster (#3633)
* Completely refactors glowshroom spreading and makes them self-decay faster (#56981) * Completely refactors glowshroom spreading and makes them self-decay faster Co-authored-by: Qustinnus <Floydje123@hotmail.com>
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
//separate dm since hydro is getting bloated already
|
||||
|
||||
#define GLOWSHROOM_SPREAD_BASE_DIMINISH_FACTOR 10
|
||||
#define GLOWSHROOM_SPREAD_DIMINISH_FACTOR_PER_GLOWSHROOM 0.2
|
||||
#define GLOWSHROOM_BASE_INTEGRITY 60
|
||||
/obj/structure/glowshroom
|
||||
name = "glowshroom"
|
||||
desc = "Mycena Bregprox, a species of mushroom that glows in the dark."
|
||||
@@ -9,21 +10,28 @@
|
||||
icon = 'icons/obj/lighting.dmi'
|
||||
icon_state = "glowshroom" //replaced in New
|
||||
layer = ABOVE_NORMAL_TURF_LAYER
|
||||
/// Time interval between glowshroom "spreads"
|
||||
var/delay_spread = 2 MINUTES
|
||||
/// Time interval between glowshroom decay checks
|
||||
var/delay_decay = 30 SECONDS
|
||||
max_integrity = GLOWSHROOM_BASE_INTEGRITY
|
||||
///Cooldown for when next to try to spread.
|
||||
COOLDOWN_DECLARE(spread_cooldown)
|
||||
/// Min time interval between glowshroom "spreads"
|
||||
var/min_delay_spread = 20 SECONDS
|
||||
/// Max time interval between glowshroom "spreads"
|
||||
var/max_delay_spread = 30 SECONDS
|
||||
/// Boolean to indicate if the shroom is on the floor/wall
|
||||
var/floor = 0
|
||||
/// Mushroom generation number
|
||||
var/generation = 1
|
||||
/// Chance to spread into adjacent tiles (0-100)
|
||||
var/spreadIntoAdjacentChance = 75
|
||||
var/spread_into_adjacent_chance = 75
|
||||
///Amount of decay when decay happens on process.
|
||||
var/idle_decay_min = 1
|
||||
///Amount of decay when decay happens on process
|
||||
var/idle_decay_max = 2
|
||||
///Amount of percentage decay affects endurance.max_integrity =
|
||||
var/endurance_decay_rate = 0.1
|
||||
/// 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,
|
||||
@@ -53,33 +61,28 @@
|
||||
*
|
||||
* Arguments:
|
||||
* * newseed - Seed of the shroom
|
||||
* * mutate_stats - If the plant needs to mutate their stats
|
||||
* * spread - If the plant is a result of spreading, reduce its stats
|
||||
*/
|
||||
|
||||
/obj/structure/glowshroom/Initialize(mapload, obj/item/seeds/newseed, mutate_stats, spread)
|
||||
|
||||
|
||||
/obj/structure/glowshroom/Initialize(mapload, obj/item/seeds/newseed)
|
||||
. = ..()
|
||||
GLOB.glowshrooms++
|
||||
if(newseed)
|
||||
myseed = newseed.Copy()
|
||||
myseed = newseed
|
||||
myseed.forceMove(src)
|
||||
else
|
||||
myseed = new myseed(src)
|
||||
if(spread)
|
||||
myseed.adjust_potency(-round(myseed.potency * 0.25)) // Reduce potency of the little mushie if it's spreading
|
||||
if(mutate_stats) //baby mushrooms have different stats :3
|
||||
myseed.adjust_potency(rand(-4,3))
|
||||
myseed.adjust_yield(rand(-3,2))
|
||||
myseed.adjust_production(rand(-3,3))
|
||||
myseed.adjust_endurance(myseed.endurance + rand(-3,2))
|
||||
if(myseed.production >= 1) //In case production is varedited to -1 or less which would cause unlimited or negative delay.
|
||||
delay_spread = delay_spread - (11 - myseed.production) * 100 //Because lower production speed stat gives faster production speed, which should give faster mushroom spread. Range 200-1100 deciseconds.
|
||||
|
||||
modify_max_integrity(GLOWSHROOM_BASE_INTEGRITY + ((100 - GLOWSHROOM_BASE_INTEGRITY) / 100 * myseed.endurance)) //goes up to 100 with peak endurance
|
||||
|
||||
var/datum/plant_gene/trait/glow/G = myseed.get_gene(/datum/plant_gene/trait/glow)
|
||||
if(ispath(G)) // Seeds were ported to initialize so their genes are still typepaths here, luckily their initializer is smart enough to handle us doing this
|
||||
myseed.genes -= G
|
||||
G = new G
|
||||
myseed.genes += G
|
||||
set_light(G.glow_range(myseed), G.glow_power(myseed), G.glow_color)
|
||||
setDir(CalcDir())
|
||||
setDir(calc_dir())
|
||||
base_icon_state = initial(icon_state)
|
||||
if(!floor)
|
||||
switch(dir) //offset to make it be on the wall rather than on the floor
|
||||
@@ -95,9 +98,14 @@
|
||||
else //if on the floor, glowshroom on-floor sprite
|
||||
icon_state = base_icon_state
|
||||
|
||||
COOLDOWN_START(src, spread_cooldown, rand(min_delay_spread, max_delay_spread))
|
||||
|
||||
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)
|
||||
START_PROCESSING(SSobj, src)
|
||||
|
||||
/obj/structure/glowshroom/Destroy()
|
||||
. = ..()
|
||||
GLOB.glowshrooms--
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
|
||||
/obj/structure/glowshroom/ComponentInitialize()
|
||||
. = ..()
|
||||
@@ -107,90 +115,79 @@
|
||||
* Causes glowshroom spreading across the floor/walls.
|
||||
*/
|
||||
|
||||
/obj/structure/glowshroom/process(delta_time)
|
||||
if(COOLDOWN_FINISHED(src, spread_cooldown))
|
||||
COOLDOWN_START(src, spread_cooldown, rand(min_delay_spread, max_delay_spread))
|
||||
Spread()
|
||||
|
||||
Decay(rand(idle_decay_min, idle_decay_max) * delta_time)
|
||||
|
||||
|
||||
|
||||
/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)
|
||||
if(!TURF_SHARES(ownturf)) //If we are in a 1x1 room
|
||||
addtimer(CALLBACK(src, .proc/Spread), delay_spread, TIMER_UNIQUE|TIMER_NO_HASH_WAIT)
|
||||
return //Deal with it not now
|
||||
|
||||
var/shrooms_planted = 0
|
||||
var/list/possibleLocs = list()
|
||||
var/list/possible_locs = 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))
|
||||
for(var/turf/open/floor/earth in oview(2,src))
|
||||
if(is_type_in_typecache(earth, blacklisted_glowshroom_turfs))
|
||||
continue
|
||||
if(!TURF_SHARES(earth))
|
||||
continue
|
||||
possibleLocs += earth
|
||||
possible_locs += earth
|
||||
|
||||
//Lets not even try to spawn again if somehow we have ZERO possible locations
|
||||
if(!possibleLocs.len)
|
||||
if(!possible_locs.len)
|
||||
return
|
||||
|
||||
var/chance_generation = 100 * (NUM_E ** -((GLOWSHROOM_SPREAD_BASE_DIMINISH_FACTOR + GLOWSHROOM_SPREAD_DIMINISH_FACTOR_PER_GLOWSHROOM * GLOB.glowshrooms) / myseed.potency * (generation - 1))) //https://www.desmos.com/calculator/istvjvcelz
|
||||
|
||||
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(chance_generation))
|
||||
continue
|
||||
var/spreads_into_adjacent = prob(spread_into_adjacent_chance)
|
||||
var/turf/new_loc = null
|
||||
|
||||
// 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
|
||||
|
||||
//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
|
||||
|
||||
//We failed to find any location, skip trying to yield
|
||||
if(newLoc == null)
|
||||
//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/iterator in 1 to 3)
|
||||
var/turf/possibleLoc = pick(possible_locs)
|
||||
if(spreads_into_adjacent || !locate(/obj/structure/glowshroom) in view(1,possibleLoc))
|
||||
new_loc = possibleLoc
|
||||
break
|
||||
|
||||
var/shroomCount = 0 //hacky
|
||||
var/placeCount = 1
|
||||
for(var/obj/structure/glowshroom/shroom in newLoc)
|
||||
shroomCount++
|
||||
for(var/wallDir in GLOB.cardinals)
|
||||
var/turf/isWall = get_step(newLoc,wallDir)
|
||||
if(isWall.density)
|
||||
placeCount++
|
||||
if(shroomCount >= placeCount)
|
||||
continue
|
||||
//We failed to find any location, skip trying to yield
|
||||
if(new_loc == null)
|
||||
break
|
||||
|
||||
Decay(TRUE, GLOWCAP_ENDURANCE_SPREAD_COST) // Decay before spawning new mushrooms to reduce their endurance
|
||||
if(QDELETED(src)) //Decay can end us
|
||||
return
|
||||
var/obj/structure/glowshroom/child = new type(newLoc, myseed, TRUE, TRUE)
|
||||
child.generation = generation + 1
|
||||
shrooms_planted++
|
||||
|
||||
if(!shrooms_planted)
|
||||
max_failed_spreads--
|
||||
var/shroom_count = 0
|
||||
var/place_count = 1
|
||||
for(var/obj/structure/glowshroom/shroom in new_loc)
|
||||
shroom_count++
|
||||
for(var/wall_dir in GLOB.cardinals)
|
||||
var/turf/potential_wall = get_step(new_loc,wall_dir)
|
||||
if(potential_wall.density)
|
||||
place_count++
|
||||
if(shroom_count >= place_count)
|
||||
continue
|
||||
|
||||
//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)
|
||||
//Lets make this a unique hash
|
||||
addtimer(CALLBACK(src, .proc/Spread), delay_spread, TIMER_UNIQUE|TIMER_NO_HASH_WAIT)
|
||||
var/obj/structure/glowshroom/child = new type(new_loc, newseed = myseed.Copy())
|
||||
child.generation = generation + 1
|
||||
|
||||
/obj/structure/glowshroom/proc/CalcDir(turf/location = loc)
|
||||
/obj/structure/glowshroom/proc/calc_dir(turf/location = loc)
|
||||
var/direction = 16
|
||||
|
||||
for(var/wallDir in GLOB.cardinals)
|
||||
var/turf/newTurf = get_step(location,wallDir)
|
||||
if(newTurf.density)
|
||||
direction |= wallDir
|
||||
for(var/wall_dir in GLOB.cardinals)
|
||||
var/turf/new_turf = get_step(location,wall_dir)
|
||||
if(new_turf.density)
|
||||
direction |= wall_dir
|
||||
|
||||
for(var/obj/structure/glowshroom/shroom in location)
|
||||
if(shroom == src)
|
||||
@@ -200,37 +197,31 @@
|
||||
else
|
||||
direction &= ~shroom.dir
|
||||
|
||||
var/list/dirList = list()
|
||||
var/list/dir_list = list()
|
||||
|
||||
for(var/i=1,i<=16,i <<= 1)
|
||||
if(direction & i)
|
||||
dirList += i
|
||||
dir_list += i
|
||||
|
||||
if(dirList.len)
|
||||
var/newDir = pick(dirList)
|
||||
if(newDir == 16)
|
||||
if(dir_list.len)
|
||||
var/new_dir = pick(dir_list)
|
||||
if(new_dir == 16)
|
||||
floor = 1
|
||||
newDir = 1
|
||||
return newDir
|
||||
new_dir = 1
|
||||
return new_dir
|
||||
|
||||
floor = 1
|
||||
return 1
|
||||
|
||||
/**
|
||||
* Causes the glowshroom to decay by decreasing its endurance.
|
||||
* Causes the glowshroom to decay by decreasing its endurance, destroying it when it gets too low.
|
||||
*
|
||||
* Arguments:
|
||||
* * spread - Boolean to indicate if the decay is due to spreading or natural decay.
|
||||
* * amount - Amount of endurance to be reduced due to spread decay.
|
||||
*/
|
||||
/obj/structure/glowshroom/proc/Decay(spread, amount)
|
||||
if (spread) // Decay due to spread
|
||||
myseed.adjust_endurance(-amount)
|
||||
else // Timed decay
|
||||
myseed.adjust_endurance(-1)
|
||||
if (myseed.endurance > MIN_PLANT_ENDURANCE)
|
||||
addtimer(CALLBACK(src, .proc/Decay), delay_decay, TIMER_UNIQUE|TIMER_NO_HASH_WAIT) // Recall decay timer
|
||||
return
|
||||
/obj/structure/glowshroom/proc/Decay(amount)
|
||||
myseed.adjust_endurance(-amount * endurance_decay_rate)
|
||||
take_damage(amount)
|
||||
if (myseed.endurance <= MIN_PLANT_ENDURANCE) // Plant is gone
|
||||
qdel(src)
|
||||
|
||||
@@ -250,3 +241,23 @@
|
||||
I.desc = "Looks like this was \an [src] some time ago."
|
||||
qdel(src)
|
||||
return TRUE
|
||||
|
||||
/obj/structure/glowshroom/extreme/Initialize(mapload, obj/item/seeds/newseed)
|
||||
. = ..()
|
||||
if(generation == 1)
|
||||
myseed.potency = 100
|
||||
myseed.endurance = 100
|
||||
myseed.yield = 10
|
||||
|
||||
/obj/structure/glowshroom/medium/Initialize(mapload, obj/item/seeds/newseed)
|
||||
. = ..()
|
||||
if(generation == 1)
|
||||
myseed.potency = 50
|
||||
myseed.endurance = 50
|
||||
myseed.yield = 5
|
||||
|
||||
|
||||
|
||||
#undef GLOWSHROOM_SPREAD_BASE_DIMINISH_FACTOR
|
||||
#undef GLOWSHROOM_SPREAD_DIMINISH_FACTOR_PER_GLOWSHROOM
|
||||
#undef GLOWSHROOM_BASE_INTEGRITY
|
||||
|
||||
Reference in New Issue
Block a user