Skip to content
This repository was archived by the owner on May 22, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions code/__DEFINES/atmospherics.dm
Original file line number Diff line number Diff line change
Expand Up @@ -494,3 +494,5 @@ GLOBAL_LIST_INIT(pipe_paint_colors, list(

#define MIASMA_CORPSE_MOLES 0.02
#define MIASMA_GIBS_MOLES 0.005

#define TURF_SHARES(T) (LAZYLEN(T.atmos_adjacent_turfs))
233 changes: 156 additions & 77 deletions code/game/objects/effects/glowshroom.dm
Original file line number Diff line number Diff line change
@@ -1,20 +1,42 @@
//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

GLOBAL_VAR_INIT(glowshrooms, 0)

/obj/structure/glowshroom
name = "glowshroom"
desc = "Mycena Bregprox, a species of mushroom that glows in the dark."
anchored = TRUE
opacity = 0
opacity = FALSE
density = FALSE
icon = 'icons/obj/lighting.dmi'
icon_state = "glowshroom" //replaced in New
layer = ABOVE_NORMAL_TURF_LAYER
max_integrity = 30
var/delay = 1200
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
var/spreadIntoAdjacentChance = 60
/// Chance to spread into adjacent tiles (0-100)
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

/// Turfs where the glowshroom cannot spread to
var/static/list/blacklisted_glowshroom_turfs = typecacheof(list(
/turf/open/lava,
/turf/open/floor/plating/beach/water))
Expand All @@ -38,33 +60,33 @@
. = ..()
. += "This is a [generation]\th generation [name]!"

/obj/structure/glowshroom/Destroy()
if(myseed)
QDEL_NULL(myseed)
return ..()
/**
* Creates a new glowshroom structure.
*
* Arguments:
* * newseed - Seed of the shroom
*/


/obj/structure/glowshroom/New(loc, obj/item/seeds/newseed, mutate_stats)
..()

/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(mutate_stats) //baby mushrooms have different stats :3
myseed.adjust_potency(rand(-3,6))
myseed.adjust_yield(rand(-1,2))
myseed.adjust_production(rand(-3,6))
myseed.adjust_endurance(rand(-3,6))
delay = delay - myseed.production * 100 //So the delay goes DOWN with better stats instead of up. :I
obj_integrity = myseed.endurance
max_integrity = myseed.endurance

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())
var/base_icon_state = initial(icon_state)
if(!floor)
switch(dir) //offset to make it be on the wall rather than on the floor
Expand All @@ -80,62 +102,92 @@
else //if on the floor, glowshroom on-floor sprite
icon_state = base_icon_state

addtimer(CALLBACK(src, .proc/Spread), delay)
COOLDOWN_START(src, spread_cooldown, rand(min_delay_spread, max_delay_spread))

START_PROCESSING(SSobj, src)

/obj/structure/glowshroom/Destroy()
. = ..()
GLOB.glowshrooms--
STOP_PROCESSING(SSobj, src)

/**
* 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()
var/turf/ownturf = get_turf(src)
var/shrooms_planted = 0
if(!TURF_SHARES(ownturf)) //If we are in a 1x1 room
return //Deal with it not now

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 oview(2,src))
if(is_type_in_typecache(earth, blacklisted_glowshroom_turfs))
continue
if(!TURF_SHARES(earth))
continue
possible_locs += earth

//Lets not even try to spawn again if somehow we have ZERO possible locations
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)
if(prob(1/(generation * generation) * 100))//This formula gives you diminishing returns based on generation. 100% with 1st gen, decreasing to 25%, 11%, 6, 4, 2...
var/list/possibleLocs = list()
var/spreadsIntoAdjacent = FALSE

if(prob(spreadIntoAdjacentChance))
spreadsIntoAdjacent = TRUE

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

if(!possibleLocs.len)
if(!prob(chance_generation))
continue
var/spreads_into_adjacent = prob(spread_into_adjacent_chance)
var/turf/new_loc = 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/turf/newLoc = pick(possibleLocs)
//We failed to find any location, skip trying to yield
if(new_loc == null)
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

var/obj/structure/glowshroom/child = new type(newLoc, myseed, TRUE)
child.generation = generation + 1
shrooms_planted++
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

CHECK_TICK
else
shrooms_planted++ //if we failed due to generation, don't try to plant one later
if(shrooms_planted < myseed.yield) //if we didn't get all possible shrooms planted, try again later
myseed.yield -= shrooms_planted
addtimer(CALLBACK(src, .proc/Spread), delay)
var/obj/structure/glowshroom/child = new type(new_loc, 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)
Expand All @@ -145,33 +197,60 @@
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, destroying it when it gets too low.
*
* Arguments:
* * amount - Amount of endurance to be reduced due to spread decay.
*/
/obj/structure/glowshroom/proc/Decay(amount)
myseed.adjust_endurance(-amount * endurance_decay_rate)
take_damage(amount)
if (myseed.endurance <= 10) // Plant is gone
qdel(src)

/obj/structure/glowshroom/play_attack_sound(damage_amount, damage_type = BRUTE, damage_flag = 0)
if(damage_type == BURN && damage_amount)
playsound(src.loc, 'sound/items/welder.ogg', 100, 1)
playsound(src.loc, 'sound/items/welder.ogg', 100, TRUE)

/obj/structure/glowshroom/temperature_expose(datum/gas_mixture/air, exposed_temperature, exposed_volume)
if(exposed_temperature > 300)
take_damage(5, BURN, 0, 0)

/obj/structure/glowshroom/acid_act(acidpwr, acid_volume)
. = 1
visible_message(span_danger("[src] melts away!"))
var/obj/effect/decal/cleanable/molten_object/I = new (get_turf(src))
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