From 0191facb71a889a8255c553e054cd7b83df339a1 Mon Sep 17 00:00:00 2001 From: TheGamerdk <5618080+TheGamerdk@users.noreply.github.com> Date: Mon, 13 Jun 2022 13:51:35 +0200 Subject: [PATCH] glowshroom cancer --- code/__DEFINES/atmospherics.dm | 2 + code/game/objects/effects/glowshroom.dm | 233 ++++++++++++++++-------- 2 files changed, 158 insertions(+), 77 deletions(-) diff --git a/code/__DEFINES/atmospherics.dm b/code/__DEFINES/atmospherics.dm index 812ff5d9503d..317c0c52051d 100644 --- a/code/__DEFINES/atmospherics.dm +++ b/code/__DEFINES/atmospherics.dm @@ -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)) diff --git a/code/game/objects/effects/glowshroom.dm b/code/game/objects/effects/glowshroom.dm index e9f151fc1748..c1e5fbb34288 100644 --- a/code/game/objects/effects/glowshroom.dm +++ b/code/game/objects/effects/glowshroom.dm @@ -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)) @@ -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 @@ -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) @@ -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