diff --git a/code/__DEFINES/flags.dm b/code/__DEFINES/flags.dm index 5c941e3689ab..c9b4aa597b57 100644 --- a/code/__DEFINES/flags.dm +++ b/code/__DEFINES/flags.dm @@ -113,6 +113,9 @@ GLOBAL_LIST_INIT(bitflags, list(1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 204 #define NO_CLEARING (1<<7) #define TURF_WEATHER (1<<8) //monkestation edit +/// This atom is a pseudo-floor that blocks map generation's checkPlaceAtom() from placing things like trees ontop of it. +#define TURF_BLOCKS_POPULATE_TERRAIN_FLORAFEATURES (1<<9) + ////////////////Area flags\\\\\\\\\\\\\\ /// If it's a valid territory for cult summoning or the CRAB-17 phone to spawn #define VALID_TERRITORY (1<<0) diff --git a/code/__DEFINES/icon_smoothing.dm b/code/__DEFINES/icon_smoothing.dm index c96f2b1ac4f6..3a6fb062bb73 100644 --- a/code/__DEFINES/icon_smoothing.dm +++ b/code/__DEFINES/icon_smoothing.dm @@ -114,7 +114,9 @@ DEFINE_BITFIELD(smoothing_flags, list( #define SMOOTH_GROUP_LOWERED_PLASTEEL S_TURF(61) #define SMOOTH_GROUP_FISSURE S_TURF(62) -#define MAX_S_TURF 62 //Always match this value with the one above it. +#define SMOOTH_GROUP_MUSHROOM S_TURF(63) + +#define MAX_S_TURF 63 //Always match this value with the one above it. #define S_OBJ(num) ("-" + #num + ",") /* /obj included */ diff --git a/code/__DEFINES/~monkestation/atmospherics.dm b/code/__DEFINES/~monkestation/atmospherics.dm new file mode 100644 index 000000000000..78184de5902d --- /dev/null +++ b/code/__DEFINES/~monkestation/atmospherics.dm @@ -0,0 +1,2 @@ +//ATMOS MIX IDS +#define FOREST_DEFAULT_ATMOS "FOREST_ATMOS" diff --git a/code/__DEFINES/~monkestation/blackboard.dm b/code/__DEFINES/~monkestation/blackboard.dm new file mode 100644 index 000000000000..16ac4d6ec3c9 --- /dev/null +++ b/code/__DEFINES/~monkestation/blackboard.dm @@ -0,0 +1,27 @@ + +// Hiding AI blackboard keys + +/// Whether or not the mob is currently hiding. +#define BB_HIDING_HIDDEN "BB_hiding_hidden" +/// The typecache (populated on `Initialize()` with the first argument of +/// `/datum/element/can_hide/basic/New()`) of turfs that our mob can hide onto. +#define BB_HIDING_CAN_HIDE_ON "BB_hiding_can_hide_on" +/// The aggro range the mob has when hiding. +#define BB_HIDING_AGGRO_RANGE "BB_hiding_aggro_range" +/// The aggro range the mob has when NOT hiding (set dynamically). +#define BB_HIDING_AGGRO_RANGE_NOT_HIDING "BB_hiding_aggro_range_not_hiding" +/// The cooldown before the mob can hide again (set dynamically). +#define BB_HIDING_COOLDOWN_BEFORE_HIDING "BB_hiding_cooldown_before_hiding" +/// The cooldown before the mob can stop hiding (set dynamically). +#define BB_HIDING_COOLDOWN_BEFORE_STOP_HIDING "BB_hiding_cooldown_before_stop_hiding" +/// The minimum value for the cooldown before the mob can hide / come out of hiding again. +#define BB_HIDING_COOLDOWN_MINIMUM "BB_hiding_cooldown_minimum" +/// The maximum value for the cooldown before the mob can hide / come out of hiding again. +#define BB_HIDING_COOLDOWN_MAXIMUM "BB_hiding_cooldown_maximum" +/// The probability (in %) that the mob will stop hiding randomly every process. +#define BB_HIDING_RANDOM_STOP_HIDING_CHANCE "BB_hiding_random_stop_hiding_chance" + +/// The default vision range when hiding, if none is specified. +#define DEFAULT_HIDING_AGGRO_RANGE 2 +/// The default chance to get out of hiding for every random hiding subtree process. +#define DEFAULT_RANDOM_STOP_HIDING_CHANCE 2 diff --git a/code/__DEFINES/~monkestation/colors.dm b/code/__DEFINES/~monkestation/colors.dm index e47cb8ddfddd..60cd738f7873 100644 --- a/code/__DEFINES/~monkestation/colors.dm +++ b/code/__DEFINES/~monkestation/colors.dm @@ -1 +1,13 @@ #define LIGHT_COLOR_CLOCKWORK "#BE8700" + +//Colors for Bioluminescence plant traits. +#define COLOR_BIOLUMINESCENCE_STANDARD "#C3E381" +#define COLOR_BIOLUMINESCENCE_SHADOW "#AAD84B" +#define COLOR_BIOLUMINESCENCE_YELLOW "#FFFF66" +#define COLOR_BIOLUMINESCENCE_GREEN "#99FF99" +#define COLOR_BIOLUMINESCENCE_BLUE "#6699FF" +#define COLOR_BIOLUMINESCENCE_PURPLE "#D966FF" +#define COLOR_BIOLUMINESCENCE_PINK "#FFB3DA" + +#define LIGHT_RANGE_FIRE_BLOSSOM_HARVESTED 2.7 +#define LIGHT_POWER_FIRE_BLOSSOM_HARVESTED 1.5 diff --git a/code/__DEFINES/~monkestation/dcs/signals/signals_atom.dm b/code/__DEFINES/~monkestation/dcs/signals/signals_atom.dm index 4e3566280e4f..a0a10db279d7 100644 --- a/code/__DEFINES/~monkestation/dcs/signals/signals_atom.dm +++ b/code/__DEFINES/~monkestation/dcs/signals/signals_atom.dm @@ -17,3 +17,10 @@ /// Mob is trying to open the hacking menu of a target [/atom], from /datum/hacking/interactable(): (mob/user) #define COMSIG_TRY_HACKING_INTERACT "try_hacking_interact" #define COMPONENT_CANT_INTERACT_HACKING (1<<0) + + +/// The signal sent when an atom/movable should try to toggle their hiding. +/// Gets called on the target, with (hiding, play_feedback = TRUE) as its args. +/// Used for `/datum/element/can_hide` +#define COMSIG_MOVABLE_TOGGLE_HIDING "movable_toggle_hiding" + diff --git a/code/datums/ai/basic_mobs/basic_ai_behaviors/targeting.dm b/code/datums/ai/basic_mobs/basic_ai_behaviors/targeting.dm index 245bac0eab7b..8ad59ba2bf15 100644 --- a/code/datums/ai/basic_mobs/basic_ai_behaviors/targeting.dm +++ b/code/datums/ai/basic_mobs/basic_ai_behaviors/targeting.dm @@ -76,7 +76,7 @@ GLOBAL_LIST_INIT(target_interested_atoms, typecacheof(list(/mob, /obj/machinery/ /datum/ai_behavior/find_potential_targets/proc/failed_to_find_anyone(datum/ai_controller/controller, target_key, targeting_strategy_key, hiding_location_key) var/aggro_range = controller.blackboard[aggro_range_key] || vision_range // takes the larger between our range() input and our implicit hearers() input (world.view) - aggro_range = max(aggro_range, ROUND_UP(max(getviewsize(world.view)) / 2)) + // aggro_range = max(aggro_range, ROUND_UP(max(getviewsize(world.view)) / 2)) MAPEXPANSION CHANGE: Stillcaps // Alright, here's the interesting bit // We're gonna use this max range to hook into a proximity field so we can just await someone interesting to come along // Rather then trying to check every few seconds diff --git a/code/datums/mapgen/CaveGenerator.dm b/code/datums/mapgen/CaveGenerator.dm index c7420dd8ffa6..ad27001ff7a9 100644 --- a/code/datums/mapgen/CaveGenerator.dm +++ b/code/datums/mapgen/CaveGenerator.dm @@ -54,7 +54,7 @@ ///Base chance of spawning flora var/flora_spawn_chance = 2 ///Base chance of spawning features - var/feature_spawn_chance = 0.15 + var/feature_spawn_chance = 0.25 ///Unique ID for this spawner var/string_gen @@ -83,10 +83,19 @@ weighted_megafauna_spawn_list = GLOB.megafauna_spawn_list megafauna_spawn_list = expand_weights(weighted_megafauna_spawn_list) if(!weighted_flora_spawn_list) - weighted_flora_spawn_list = list(/obj/structure/flora/ash/leaf_shroom = 2 , /obj/structure/flora/ash/cap_shroom = 2 , /obj/structure/flora/ash/stem_shroom = 2 , /obj/structure/flora/ash/cacti = 1, /obj/structure/flora/ash/tall_shroom = 2, /obj/structure/flora/ash/seraka = 2) + weighted_flora_spawn_list = list( + /obj/structure/flora/ash/leaf_shroom = 2, + /obj/structure/flora/ash/cap_shroom = 2, + /obj/structure/flora/ash/stem_shroom = 2, + /obj/structure/flora/ash/cacti = 1, + /obj/structure/flora/ash/tall_shroom = 2, + /obj/structure/flora/ash/seraka = 2, + ) flora_spawn_list = expand_weights(weighted_flora_spawn_list) if(!weighted_feature_spawn_list) - weighted_feature_spawn_list = list(/obj/structure/geyser/random = 1) + weighted_feature_spawn_list = list( + /obj/structure/geyser/random = 1, + ) feature_spawn_list = expand_weights(weighted_feature_spawn_list) open_turf_types = expand_weights(weighted_open_turf_types) closed_turf_types = expand_weights(weighted_closed_turf_types) @@ -103,14 +112,7 @@ var/start_time = REALTIMEOFDAY string_gen = rustg_cnoise_generate("[initial_closed_chance]", "[smoothing_iterations]", "[birth_limit]", "[death_limit]", "[world.maxx]", "[world.maxy]") //Generate the raw CA data - // Area var pullouts to make accessing in the loop faster - var/flora_allowed = (generate_in.area_flags & FLORA_ALLOWED) && length(flora_spawn_list) - var/feature_allowed = (generate_in.area_flags & FLORA_ALLOWED) && length(feature_spawn_list) - var/mobs_allowed = (generate_in.area_flags & MOB_SPAWN_ALLOWED) && length(mob_spawn_list) - var/megas_allowed = (generate_in.area_flags & MEGAFAUNA_SPAWN_ALLOWED) && length(megafauna_spawn_list) - - for(var/i in turfs) //Go through all the turfs and generate them - var/turf/gen_turf = i + for(var/turf/gen_turf as anything in turfs) //Go through all the turfs and generate them var/closed = string_gen[world.maxx * (gen_turf.y - 1) + gen_turf.x] != "0" var/turf/new_turf = pick(closed ? closed_turf_types : open_turf_types) @@ -162,8 +164,8 @@ var/datum/biome/selected_biome // Here comes the meat of the biome code. - var/drift_x = clamp((gen_turf.x + rand(-BIOME_RANDOM_SQUARE_DRIFT, BIOME_RANDOM_SQUARE_DRIFT)), 1, world.maxx) // / perlin_zoom - var/drift_y = clamp((gen_turf.y + rand(-BIOME_RANDOM_SQUARE_DRIFT, BIOME_RANDOM_SQUARE_DRIFT)), 2, world.maxy) // / perlin_zoom + var/drift_x = clamp(((gen_turf.x + rand(-BIOME_RANDOM_SQUARE_DRIFT, BIOME_RANDOM_SQUARE_DRIFT)) / perlin_zoom), 1, world.maxx) + var/drift_y = clamp(((gen_turf.y + rand(-BIOME_RANDOM_SQUARE_DRIFT, BIOME_RANDOM_SQUARE_DRIFT)) / perlin_zoom), 2, world.maxy) // Where we go in the generated string (generated outside of the loop for s p e e d) var/coordinate = world.maxx * (drift_y - 1) + drift_x @@ -223,35 +225,40 @@ // If we've spawned something yet var/spawned_something = FALSE - ///Spawning isn't done in procs to save on overhead on the 60k turfs we're going through. - //FLORA SPAWNING HERE - if(flora_allowed && prob(flora_spawn_chance)) - var/flora_type = pick(flora_spawn_list) - new flora_type(new_turf) - spawned_something = TRUE + if(!(target_turf.turf_flags & TURF_BLOCKS_POPULATE_TERRAIN_FLORAFEATURES)) + ///Spawning isn't done in procs to save on overhead on the 60k turfs we're going through. + //FLORA SPAWNING HERE + if(flora_allowed && prob(flora_spawn_chance)) + var/flora_type = pick(flora_spawn_list) + new flora_type(target_turf) + spawned_something = TRUE - //FEATURE SPAWNING HERE - if(feature_allowed && prob(feature_spawn_chance)) - var/can_spawn = TRUE + //FEATURE SPAWNING HERE + //we may have generated something from the flora list on the target turf, so let's not place + //a feature here if that's the case (because it would look stupid) + if(feature_allowed && !spawned_something && prob(feature_spawn_chance)) + var/can_spawn = TRUE - var/atom/picked_feature = pick(feature_spawn_list) + var/atom/picked_feature = pick(feature_spawn_list) - for(var/obj/structure/existing_feature in range(7, new_turf)) - if(istype(existing_feature, picked_feature)) - can_spawn = FALSE - break + for(var/obj/structure/existing_feature in range(7, target_turf)) + if(istype(existing_feature, picked_feature)) + can_spawn = FALSE + break - if(can_spawn) - new picked_feature(new_turf) - spawned_something = TRUE + if(can_spawn) + new picked_feature(target_turf) + spawned_something = TRUE //MOB SPAWNING HERE if(mobs_allowed && !spawned_something && prob(mob_spawn_chance)) var/atom/picked_mob = pick(mob_spawn_list) + var/is_megafauna = FALSE if(picked_mob == SPAWN_MEGAFAUNA) if(megas_allowed) //this is danger. it's boss time. picked_mob = pick(megafauna_spawn_list) + is_megafauna = TRUE else //this is not danger, don't spawn a boss, spawn something else picked_mob = pick(mob_spawn_no_mega_list) //What if we used 100% of the brain...and did something (slightly) less shit than a while loop? @@ -259,19 +266,22 @@ // prevents tendrils spawning in each other's collapse range if(ispath(picked_mob, /obj/structure/spawner/lavaland)) - for(var/obj/structure/spawner/lavaland/spawn_blocker in range(2, new_turf)) + for(var/obj/structure/spawner/lavaland/spawn_blocker in range(2, target_turf)) can_spawn = FALSE break // if the random is not a tendril (hopefully meaning it is a mob), avoid spawning if there's another one within 12 tiles else - var/list/things_in_range = range(12, new_turf) + var/list/things_in_range = range(12, target_turf) for(var/mob/living/mob_blocker in things_in_range) if(ismining(mob_blocker)) can_spawn = FALSE break + // Also block spawns if there's a random lavaland mob spawner nearby and it's not a mega + if(!is_megafauna) + can_spawn = can_spawn && !(locate(/obj/effect/spawner/random/lavaland_mob) in things_in_range) //if there's a megafauna within standard view don't spawn anything at all (This isn't really consistent, I don't know why we do this. you do you tho) if(can_spawn) - for(var/mob/living/simple_animal/hostile/megafauna/found_fauna in range(7, new_turf)) + for(var/mob/living/simple_animal/hostile/megafauna/found_fauna in range(7, target_turf)) can_spawn = FALSE break @@ -280,11 +290,11 @@ weighted_megafauna_spawn_list.Remove(picked_mob) megafauna_spawn_list = expand_weights(weighted_megafauna_spawn_list) megas_allowed = megas_allowed && length(megafauna_spawn_list) - new picked_mob(new_turf) + new picked_mob(target_turf) spawned_something = TRUE CHECK_TICK - var/message = "[name] finished in [(REALTIMEOFDAY - start_time)/10]s!" + var/message = "[name] terrain population finished in [(REALTIMEOFDAY - start_time)/10]s!" to_chat(world, span_boldannounce("[message]")) log_world(message) diff --git a/code/game/objects/structures/flora.dm b/code/game/objects/structures/flora.dm index 0ddfcf235eee..0ed9d046ecde 100644 --- a/code/game/objects/structures/flora.dm +++ b/code/game/objects/structures/flora.dm @@ -299,7 +299,7 @@ . = ..() var/turf/my_turf = get_turf(src) playsound(my_turf, 'sound/effects/meteorimpact.ogg', 100 , FALSE, FALSE) - var/obj/structure/flora/tree/stump/new_stump = new(my_turf) + var/obj/structure/flora/tree/stump/new_stump = new stump_type(my_turf) new_stump.name = "[name] stump" /obj/structure/flora/tree/uproot(mob/living/user) diff --git a/code/modules/procedural_mapping/mapGenerator.dm b/code/modules/procedural_mapping/mapGenerator.dm index 4a79ad4c3059..2adbc8601943 100644 --- a/code/modules/procedural_mapping/mapGenerator.dm +++ b/code/modules/procedural_mapping/mapGenerator.dm @@ -14,6 +14,10 @@ buildmode_name = copytext_char("[type]", 20) // / d a t u m / m a p g e n e r a t o r / = 20 characters. initialiseModules() +/// Populate terrain with flora, fauna, features and basically everything that isn't a turf. +/datum/map_generator/proc/populate_terrain(list/turfs, area/generate_in) + return + //Defines the region the map represents, sets map //Returns the map /datum/map_generator/proc/defineRegion(turf/Start, turf/End, replace = 0) diff --git a/monkestation/code/modules/liquids/ocean_generator.dm b/monkestation/code/modules/liquids/ocean_generator.dm index 46db1b9f09c1..7f6161d78188 100644 --- a/monkestation/code/modules/liquids/ocean_generator.dm +++ b/monkestation/code/modules/liquids/ocean_generator.dm @@ -107,7 +107,7 @@ flora_spawn_list = null ///2D list of all biomes based on heat and humidity combos. - var/list/possible_biomes = list( + possible_biomes = list( BIOME_LOW_HEAT = list( BIOME_LOW_HUMIDITY = /datum/biome/ocean_sand/above, BIOME_LOWMEDIUM_HUMIDITY = /datum/biome/ocean_sand_flora/above, @@ -134,7 +134,7 @@ ) ) ///Used to select "zoom" level into the perlin noise, higher numbers result in slower transitions - var/perlin_zoom = 65 + perlin_zoom = 65 /datum/map_generator/cave_generator/trench/generate_terrain(list/turfs, area/generate_in) diff --git a/monkestation/code/modules/map_gen_expansions/README.md b/monkestation/code/modules/map_gen_expansions/README.md new file mode 100644 index 000000000000..d9def091615f --- /dev/null +++ b/monkestation/code/modules/map_gen_expansions/README.md @@ -0,0 +1,8 @@ +## Title: MapGen Expansions + +MODULE ID: MAPEXPANSIONS + +### Credits: + +Credits to SableSteel (sable.steel on Discord, thlumyn on Github) for the sprites +Credits to GoldenAlpharex for the biome generation and other code diff --git a/monkestation/code/modules/map_gen_expansions/_basemapping.dm b/monkestation/code/modules/map_gen_expansions/_basemapping.dm new file mode 100644 index 000000000000..1ddefd02b734 --- /dev/null +++ b/monkestation/code/modules/map_gen_expansions/_basemapping.dm @@ -0,0 +1,8 @@ +/// Returns true if the map we're playing on is on a planet, but it DOES have space access. +/datum/controller/subsystem/mapping/proc/is_planetary_with_space() + return config.planetary && config.allow_space_when_planetary + + +/datum/map_config + /// Are we allowing space even if we're planetary? + var/allow_space_when_planetary = FALSE diff --git a/monkestation/code/modules/map_gen_expansions/ai/behaviours/hiding.dm b/monkestation/code/modules/map_gen_expansions/ai/behaviours/hiding.dm new file mode 100644 index 000000000000..d4b2150909b5 --- /dev/null +++ b/monkestation/code/modules/map_gen_expansions/ai/behaviours/hiding.dm @@ -0,0 +1,59 @@ +/// This behavior is to run any code that needs to be ran when the mob is going +/// into hiding, or coming out from hiding. +/datum/ai_behavior/toggle_hiding + /// The blackboard cooldown key to check before we can hide. Only here + /// to avoid copy-paste in other subtrees/behaviors, should only be SET, + /// not READ here. + var/cooldown_before_hiding_key = BB_HIDING_COOLDOWN_BEFORE_HIDING + + +/datum/ai_behavior/toggle_hiding/setup(datum/ai_controller/controller, ...) + . = ..() + + if(!controller.blackboard[BB_HIDING_AGGRO_RANGE_NOT_HIDING]) + controller.set_blackboard_key(BB_HIDING_AGGRO_RANGE_NOT_HIDING, controller.blackboard[BB_AGGRO_RANGE]) + + +/datum/ai_behavior/toggle_hiding/perform(seconds_per_tick, datum/ai_controller/controller, now_hiding) + var/mob/living/basic/hiding_pawn = controller.pawn + + if(!istype(hiding_pawn)) + finish_action(controller, FALSE) + return + + var/mob/living/living_pawn = controller.pawn + + // Let's add some checks if we're trying to hide. + if(now_hiding) + // We can't hide if we can't move properly, or if we don't have any valid hiding locations. + if(!(living_pawn.mobility_flags & MOBILITY_MOVE) || !isturf(living_pawn.loc) || living_pawn.pulledby || !islist(controller.blackboard[BB_HIDING_CAN_HIDE_ON])) + finish_action(controller, FALSE) + return + + // We can't hide if we don't match the proper turf type we need to hide onto. + if(!controller.blackboard[BB_HIDING_CAN_HIDE_ON][living_pawn.loc.type]) + finish_action(controller, FALSE) + return + + var/hiding_status_changed = controller.blackboard[BB_HIDING_HIDDEN] != now_hiding + + if(!hiding_status_changed) + finish_action(controller, TRUE) + return + + controller.set_blackboard_key(BB_HIDING_HIDDEN, now_hiding) + SEND_SIGNAL(living_pawn, COMSIG_MOVABLE_TOGGLE_HIDING, now_hiding, TRUE) + + var/new_vision_range = now_hiding ? controller.blackboard[BB_HIDING_AGGRO_RANGE] || DEFAULT_HIDING_AGGRO_RANGE : controller.blackboard[BB_HIDING_AGGRO_RANGE_NOT_HIDING] + + if(!now_hiding) + var/cooldown_minimum = controller.blackboard[BB_HIDING_COOLDOWN_MINIMUM] || 1 MINUTES + var/cooldown_maximum = controller.blackboard[BB_HIDING_COOLDOWN_MAXIMUM] || 3 MINUTES + var/new_cooldown = world.time + rand(cooldown_minimum, cooldown_maximum) + controller.set_blackboard_key(cooldown_before_hiding_key, new_cooldown) + + controller.set_blackboard_key(BB_AGGRO_RANGE, new_vision_range) + + finish_action(controller, TRUE) + return + diff --git a/monkestation/code/modules/map_gen_expansions/ai/idle_behaviours.dm b/monkestation/code/modules/map_gen_expansions/ai/idle_behaviours.dm new file mode 100644 index 000000000000..208ff5458b9a --- /dev/null +++ b/monkestation/code/modules/map_gen_expansions/ai/idle_behaviours.dm @@ -0,0 +1,9 @@ +/datum/idle_behavior/idle_random_walk/hide + + +/datum/idle_behavior/idle_random_walk/hide/perform_idle_behavior(seconds_per_tick, datum/ai_controller/controller) + // You can't move when you're hidden. + if(controller.blackboard[BB_HIDING_HIDDEN]) + return FALSE + + return ..() diff --git a/monkestation/code/modules/map_gen_expansions/ai/subtree/find_target_not_hiding.dm b/monkestation/code/modules/map_gen_expansions/ai/subtree/find_target_not_hiding.dm new file mode 100644 index 000000000000..cc84e61f0424 --- /dev/null +++ b/monkestation/code/modules/map_gen_expansions/ai/subtree/find_target_not_hiding.dm @@ -0,0 +1,9 @@ +// Prevents finding a target if hiding. +/datum/ai_planning_subtree/simple_find_target/not_while_hiding + operational_datums = list(/datum/element/can_hide) + +/datum/ai_planning_subtree/simple_find_target/not_while_hiding/SelectBehaviors(datum/ai_controller/controller, seconds_per_tick) + if(controller.blackboard[BB_HIDING_HIDDEN]) + return + + return ..() diff --git a/monkestation/code/modules/map_gen_expansions/ai/subtree/hiding.dm b/monkestation/code/modules/map_gen_expansions/ai/subtree/hiding.dm new file mode 100644 index 000000000000..7c02f2945932 --- /dev/null +++ b/monkestation/code/modules/map_gen_expansions/ai/subtree/hiding.dm @@ -0,0 +1,57 @@ +/// By how much should the time until they start hiding again be multiplied with. +#define START_HIDING_COOLDOWN_COEFFICIENT 0.1 + +/// This subtree causes the mob to go into hiding after a random duration +/// since the last time they went into hiding. +/datum/ai_planning_subtree/random_hiding + operational_datums = list(/datum/element/can_hide) + /// The blackboard cooldown key to check before we hide. + var/cooldown_before_hiding_key = BB_HIDING_COOLDOWN_BEFORE_HIDING + /// The blackboard cooldown key to check before check if we can should stop hiding. + var/cooldown_before_stop_hiding_key = BB_HIDING_COOLDOWN_BEFORE_STOP_HIDING + /// The blackboard target key to check, that will force a cooldown reset + /// if the cooldown is below the minimum cooldown duration. + var/target_key = BB_BASIC_MOB_CURRENT_TARGET + + +/datum/ai_planning_subtree/random_hiding/SelectBehaviors(datum/ai_controller/controller, seconds_per_tick) + var/cooldown_minimum = controller.blackboard[BB_HIDING_COOLDOWN_MINIMUM] || 1 MINUTES + var/cooldown_maximum = controller.blackboard[BB_HIDING_COOLDOWN_MAXIMUM] || 3 MINUTES + + if(controller.blackboard[BB_HIDING_HIDDEN]) + // We can't stop hiding randomly until this cooldown is over. + if(controller.blackboard[cooldown_before_stop_hiding_key] && controller.blackboard[cooldown_before_stop_hiding_key] > world.time) + return + + var/chance_to_stop_hiding = controller.blackboard[BB_HIDING_RANDOM_STOP_HIDING_CHANCE] || DEFAULT_RANDOM_STOP_HIDING_CHANCE + if(SPT_PROB(chance_to_stop_hiding, seconds_per_tick)) + controller.queue_behavior(/datum/ai_behavior/toggle_hiding, FALSE) + var/new_cooldown = world.time + rand(cooldown_minimum, cooldown_maximum) * START_HIDING_COOLDOWN_COEFFICIENT + controller.set_blackboard_key(cooldown_before_hiding_key, new_cooldown) + + return SUBTREE_RETURN_FINISH_PLANNING + + return // We don't want to do anything else if we're currently hiding. + + // If we have a target, we possibly want to reset the cooldown. + if(controller.blackboard[target_key]) + // If the cooldown we have is more than the minimum cooldown, don't do anything. + if(controller.blackboard[cooldown_before_hiding_key] && controller.blackboard[cooldown_before_hiding_key] - world.time >= cooldown_minimum) + return + + // Let's just reset the cooldown, now, then. + var/new_cooldown = world.time + rand(cooldown_minimum, cooldown_maximum) + controller.set_blackboard_key(cooldown_before_hiding_key, new_cooldown) + + return + + // If we can't hide yet, we do nothing. + if(controller.blackboard[cooldown_before_hiding_key] && controller.blackboard[cooldown_before_hiding_key] > world.time) + return + + // We can hide, so let's do just that! + controller.queue_behavior(/datum/ai_behavior/toggle_hiding, TRUE) + var/new_cooldown = world.time + rand(cooldown_minimum, cooldown_maximum) + controller.set_blackboard_key(cooldown_before_stop_hiding_key, new_cooldown) + + return SUBTREE_RETURN_FINISH_PLANNING diff --git a/monkestation/code/modules/map_gen_expansions/ai/subtree/retaliate_target.dm b/monkestation/code/modules/map_gen_expansions/ai/subtree/retaliate_target.dm new file mode 100644 index 000000000000..d2fc490027b7 --- /dev/null +++ b/monkestation/code/modules/map_gen_expansions/ai/subtree/retaliate_target.dm @@ -0,0 +1,19 @@ +// This is to ensure retaliation breaks the "hiding" state if a target is found. +/datum/ai_planning_subtree/target_retaliate/check_faction/stop_hiding + operational_datums = list(/datum/element/can_hide) + + +/datum/ai_planning_subtree/target_retaliate/check_faction/stop_hiding/SelectBehaviors(datum/ai_controller/controller, seconds_per_tick) + controller.queue_behavior(/datum/ai_behavior/target_from_retaliate_list/stop_hiding, BB_BASIC_MOB_RETALIATE_LIST, target_key, targeting_strategy_key, hiding_place_key, check_faction) + + +// This is to ensure retaliation breaks the "hiding" state if a target is found. +/datum/ai_behavior/target_from_retaliate_list/stop_hiding + + +/datum/ai_behavior/target_from_retaliate_list/stop_hiding/finish_action(datum/ai_controller/controller, succeeded, shitlist_key, target_key, targeting_strategy_key, hiding_location_key, check_faction) + . = ..() + if(!controller.blackboard[BB_HIDING_HIDDEN] || !succeeded) + return + + controller.queue_behavior(/datum/ai_behavior/toggle_hiding, FALSE) diff --git a/monkestation/code/modules/map_gen_expansions/ai/subtree/stop_hiding_if_target.dm b/monkestation/code/modules/map_gen_expansions/ai/subtree/stop_hiding_if_target.dm new file mode 100644 index 000000000000..afc5d566418c --- /dev/null +++ b/monkestation/code/modules/map_gen_expansions/ai/subtree/stop_hiding_if_target.dm @@ -0,0 +1,12 @@ + +/// This subtree ensures that the mob gets out from hiding if they have a target. +/datum/ai_planning_subtree/stop_hiding_if_target + operational_datums = list(/datum/element/can_hide, /datum/element/can_hide/basic) + /// Blackboard key where we check if there's currently a target. + var/target_key = BB_BASIC_MOB_CURRENT_TARGET + + +/datum/ai_planning_subtree/stop_hiding_if_target/SelectBehaviors(datum/ai_controller/controller, seconds_per_tick) + if(controller.blackboard[BB_BASIC_MOB_CURRENT_TARGET] && controller.blackboard[BB_HIDING_HIDDEN]) + controller.queue_behavior(/datum/ai_behavior/toggle_hiding, FALSE) + diff --git a/monkestation/code/modules/map_gen_expansions/areas.dm b/monkestation/code/modules/map_gen_expansions/areas.dm new file mode 100644 index 000000000000..e47fd6402022 --- /dev/null +++ b/monkestation/code/modules/map_gen_expansions/areas.dm @@ -0,0 +1,34 @@ +/area/forestplanet + icon = 'icons/area/areas_station.dmi' + icon_state = "mining" + has_gravity = STANDARD_GRAVITY + flags_1 = NONE + area_flags = UNIQUE_AREA | FLORA_ALLOWED + //ambience_index = AMBIENCE_ICEMOON + sound_environment = SOUND_AREA_ICEMOON + ambient_buzz = 'sound/ambience/magma.ogg' + name = "Forest Planet" + icon_state = "explored" + always_unpowered = TRUE + power_environ = FALSE + power_equip = FALSE + power_light = FALSE + requires_power = TRUE + min_ambience_cooldown = 70 SECONDS + max_ambience_cooldown = 220 SECONDS + +/area/forestplanet/outdoors // parent that defines if something is on the exterior of the station. + name = "Woodlands" + outdoors = TRUE + +/area/forestplanet/outdoors/nospawn + +/area/forestplanet/outdoors/unexplored + icon_state = "unexplored" + area_flags = UNIQUE_AREA | FLORA_ALLOWED | MOB_SPAWN_ALLOWED | CAVES_ALLOWED + map_generator = /datum/map_generator/cave_generator/forest + +/area/forestplanet/outdoors/unexplored/deep + name = "Mushroom Caves" + map_generator = /datum/map_generator/cave_generator/forest/mushroom + diff --git a/monkestation/code/modules/map_gen_expansions/elements/can_hide.dm b/monkestation/code/modules/map_gen_expansions/elements/can_hide.dm new file mode 100644 index 000000000000..8187378a15ba --- /dev/null +++ b/monkestation/code/modules/map_gen_expansions/elements/can_hide.dm @@ -0,0 +1,56 @@ +/// This element serves to allow movables to hide when they receive the +/// `COMSIG_MOVABLE_TOGGLE_HIDING` signal. Does NOT do any form of checking, +/// it's on the caller to check if they should be calling this or not. +/datum/element/can_hide + element_flags = ELEMENT_DETACH_ON_HOST_DESTROY + + +/datum/element/can_hide/Attach(atom/movable/target) + . = ..() + + if(!istype(target)) + return ELEMENT_INCOMPATIBLE + + RegisterSignal(target, COMSIG_MOVABLE_TOGGLE_HIDING, PROC_REF(on_toggle_hiding)) + ADD_TRAIT(target, TRAIT_SUBTREE_REQUIRED_OPERATIONAL_DATUM, type) + + +/datum/element/can_hide/Detach(datum/source, ...) + . = ..() + + UnregisterSignal(source, COMSIG_MOVABLE_TOGGLE_HIDING) + + +/** + * Handles toggling whatever needs to be toggled on the target in when they + * hide or come back from hiding. Does NOT check if they were already in the same + * state, so check that yourself. + */ +/datum/element/can_hide/proc/on_toggle_hiding(atom/movable/target, hiding, play_feedback = TRUE) + SIGNAL_HANDLER + + target.pass_flags_self = hiding ? PASSSTRUCTURE : initial(target.pass_flags_self) + target.icon_state = "[target.base_icon_state][hiding ? "_hidden" : ""]" + + if(play_feedback) + playsound(target, 'sound/effects/bodyfall1.ogg', 50, TRUE) + new /obj/effect/temp_visual/mook_dust(get_turf(target)) + + target.update_appearance() + +/// Like datum/element/can_hide, but for basic mobs. +/datum/element/can_hide/basic + +// Contains an additional parameter, can_hide_types, to tell the basic mob AI subroutine what types of turfs it can hide onto. +/datum/element/can_hide/basic/Attach(datum/target, list/turf/can_hide_types) + var/mob/living/basic/basic_target = target + if(!istype(basic_target)) + return ELEMENT_INCOMPATIBLE + + . = ..() + + if(. == ELEMENT_INCOMPATIBLE) + return + + basic_target.ai_controller?.set_blackboard_key(BB_HIDING_CAN_HIDE_ON, typecacheof(can_hide_types)) + diff --git a/monkestation/code/modules/map_gen_expansions/forest/atmosphere.dm b/monkestation/code/modules/map_gen_expansions/forest/atmosphere.dm new file mode 100644 index 000000000000..79ae14fc521f --- /dev/null +++ b/monkestation/code/modules/map_gen_expansions/forest/atmosphere.dm @@ -0,0 +1,23 @@ + +/datum/atmosphere/forest + id = FOREST_DEFAULT_ATMOS + + base_gases = list( + /datum/gas/oxygen=5, + /datum/gas/nitrogen=10, + ) + normal_gases = list( + /datum/gas/oxygen=10, + /datum/gas/nitrogen=10, + /datum/gas/bz=1.2, + ) + restricted_gases = list( + /datum/gas/water_vapor=0.1, + ) + restricted_chance = 20 + + minimum_pressure = HAZARD_LOW_PRESSURE + 10 + maximum_pressure = LAVALAND_EQUIPMENT_EFFECT_PRESSURE - 1 + + minimum_temp = BODYTEMP_COLD_DAMAGE_LIMIT + 4 + maximum_temp = 350 diff --git a/monkestation/code/modules/map_gen_expansions/forest/generator.dm b/monkestation/code/modules/map_gen_expansions/forest/generator.dm new file mode 100644 index 000000000000..a78e735e211f --- /dev/null +++ b/monkestation/code/modules/map_gen_expansions/forest/generator.dm @@ -0,0 +1,36 @@ + +/datum/map_generator/cave_generator/forest + weighted_open_turf_types = list(/turf/open/misc/asteroid/forest = 1) + weighted_closed_turf_types = list(/turf/closed/mineral/random/forest = 1) + flora_spawn_chance = 35 + initial_closed_chance = 53 + birth_limit = 5 + death_limit = 4 + smoothing_iterations = 10 + + weighted_mob_spawn_list = list( + /mob/living/basic/deer/mining = 50, + /mob/living/basic/mining/megadeer = 15, + /mob/living/basic/mining/goldgrub = 1, + ) + + weighted_flora_spawn_list = list( + /obj/structure/flora/ash/fireblossom = 2, + /obj/structure/flora/grass/jungle/a/style_random = 15, + /obj/structure/flora/grass/jungle/b/style_random = 30, + /obj/structure/flora/bush/jungle/a/style_random = 5, + /obj/structure/flora/bush/jungle/b/style_random = 5, + /obj/structure/flora/bush/jungle/c/style_random = 5, + /obj/structure/flora/rock/pile/jungle/style_random = 3, + /obj/structure/flora/rock/pile/jungle/large/style_random = 1, + /obj/structure/flora/tree/jungle/style_random = 7, + /obj/structure/flora/tree/jungle/small/style_random = 3, + ) + ///Note that this spawn list is also in the lavaland generator + weighted_feature_spawn_list = list( + /obj/structure/geyser/hollowwater = 10, + /obj/structure/geyser/plasma_oxide = 10, + /obj/structure/geyser/protozine = 10, + /obj/structure/geyser/random = 2, + /obj/structure/geyser/wittel = 10, + ) diff --git a/monkestation/code/modules/map_gen_expansions/forest/mobs/deer.dm b/monkestation/code/modules/map_gen_expansions/forest/mobs/deer.dm new file mode 100644 index 000000000000..6db0ecda7f92 --- /dev/null +++ b/monkestation/code/modules/map_gen_expansions/forest/mobs/deer.dm @@ -0,0 +1,3 @@ +/mob/living/basic/deer/mining + desc = "A common deer, used to living alongside monsters after generations on this planet." + faction = list("mining") diff --git a/monkestation/code/modules/map_gen_expansions/forest/mobs/megadeer.dm b/monkestation/code/modules/map_gen_expansions/forest/mobs/megadeer.dm new file mode 100644 index 000000000000..1108128bef4d --- /dev/null +++ b/monkestation/code/modules/map_gen_expansions/forest/mobs/megadeer.dm @@ -0,0 +1,91 @@ +/mob/living/basic/mining/megadeer + name = "megadeer" + desc = "The descendants of the common deer, turned into angry beasts by the harshness of the land." + icon = 'monkestation/code/modules/map_gen_expansions/icons/newfauna_wide.dmi' + icon_state = "megadeer" + icon_living = "megadeer" + icon_dead = "megadeer_dead" + pixel_x = -12 + base_pixel_x = -12 + mob_biotypes = MOB_ORGANIC|MOB_BEAST + mouse_opacity = MOUSE_OPACITY_ICON + speak_emote = list("flutes") + + butcher_results = list( + /obj/item/food/meat/slab = 2, + /obj/item/stack/sheet/sinew/deer = 2, + /obj/item/stack/sheet/bone = 2 + ) + crusher_loot = /obj/item/crusher_trophy/deer_fur + + maxHealth = 180 + health = 180 + obj_damage = 15 + melee_damage_lower = 15 + melee_damage_upper = 15 + attack_vis_effect = ATTACK_EFFECT_BITE + melee_attack_cooldown = 1.2 SECONDS + + attack_verb_continuous = "bites" + attack_verb_simple = "bite" + death_message = "lets out a fluting cry and collapses." + + attack_sound = 'sound/weapons/bite.ogg' + move_force = MOVE_FORCE_WEAK + move_resist = MOVE_FORCE_WEAK + pull_force = MOVE_FORCE_WEAK + + ai_controller = /datum/ai_controller/basic_controller/megadeer + + var/can_tame = FALSE + +/mob/living/basic/mining/megadeer/Initialize(mapload) + . = ..() + + AddElement(/datum/element/footstep, FOOTSTEP_MOB_CLAW) + AddElement(/datum/element/ai_flee_while_injured) + AddElement(/datum/element/ai_retaliate) + AddComponent(/datum/component/basic_mob_ability_telegraph) + AddComponent(/datum/component/basic_mob_attack_telegraph, telegraph_duration = 0.6 SECONDS) + +/obj/item/crusher_trophy/deer_fur + name = "deer fur" + desc = "It's fur from a mega deer." + icon = 'monkestation/code/modules/map_gen_expansions/icons/misc.dmi' + icon_state = "deer_fur" + denied_type = /obj/item/crusher_trophy/deer_fur + +/obj/item/crusher_trophy/deer_fur/effect_desc() + return "mark detonation to gain a slight speed boost temporarily" + +/obj/item/crusher_trophy/deer_fur/on_mark_detonation(mob/living/target, mob/living/user) + user.apply_status_effect(/datum/status_effect/speed_boost, 1 SECONDS) + +//sinew re-flavor for megadeers +/obj/item/stack/sheet/sinew/deer + name = "deer sinew" + singular_name = "deer sinew" + merge_type = /obj/item/stack/sheet/sinew/deer + + +/datum/ai_controller/basic_controller/megadeer + blackboard = list( + BB_TARGETING_STRATEGY = /datum/targeting_strategy/basic/allow_items, + BB_PET_TARGETING_STRATEGY = /datum/targeting_strategy/basic/not_friends, + BB_BASIC_MOB_FLEE_DISTANCE = 25, + BB_VISION_RANGE = 9, + BB_TARGET_MINIMUM_STAT = HARD_CRIT, + ) + + ai_movement = /datum/ai_movement/basic_avoidance + idle_behavior = /datum/idle_behavior/idle_random_walk + + planning_subtrees = list( + /datum/ai_planning_subtree/pet_planning, + /datum/ai_planning_subtree/simple_find_nearest_target_to_flee, + /datum/ai_planning_subtree/flee_target, + /datum/ai_planning_subtree/target_retaliate/check_faction, + /datum/ai_planning_subtree/simple_find_target, + /datum/ai_planning_subtree/attack_obstacle_in_path, + /datum/ai_planning_subtree/basic_melee_attack_subtree, + ) diff --git a/monkestation/code/modules/map_gen_expansions/icons/floors.dmi b/monkestation/code/modules/map_gen_expansions/icons/floors.dmi new file mode 100644 index 000000000000..286374d2ecb6 Binary files /dev/null and b/monkestation/code/modules/map_gen_expansions/icons/floors.dmi differ diff --git a/monkestation/code/modules/map_gen_expansions/icons/misc.dmi b/monkestation/code/modules/map_gen_expansions/icons/misc.dmi new file mode 100644 index 000000000000..24b3ac3a8d5c Binary files /dev/null and b/monkestation/code/modules/map_gen_expansions/icons/misc.dmi differ diff --git a/monkestation/code/modules/map_gen_expansions/icons/mushroom_flora.dmi b/monkestation/code/modules/map_gen_expansions/icons/mushroom_flora.dmi new file mode 100644 index 000000000000..be6aa52584a6 Binary files /dev/null and b/monkestation/code/modules/map_gen_expansions/icons/mushroom_flora.dmi differ diff --git a/monkestation/code/modules/map_gen_expansions/icons/mushroomtrees.dmi b/monkestation/code/modules/map_gen_expansions/icons/mushroomtrees.dmi new file mode 100644 index 000000000000..d59250a58378 Binary files /dev/null and b/monkestation/code/modules/map_gen_expansions/icons/mushroomtrees.dmi differ diff --git a/monkestation/code/modules/map_gen_expansions/icons/newfauna_wide.dmi b/monkestation/code/modules/map_gen_expansions/icons/newfauna_wide.dmi new file mode 100644 index 000000000000..7aec3a722c25 Binary files /dev/null and b/monkestation/code/modules/map_gen_expansions/icons/newfauna_wide.dmi differ diff --git a/monkestation/code/modules/map_gen_expansions/icons/turfs/floors/mushroom.dmi b/monkestation/code/modules/map_gen_expansions/icons/turfs/floors/mushroom.dmi new file mode 100644 index 000000000000..b67fe036d1a9 Binary files /dev/null and b/monkestation/code/modules/map_gen_expansions/icons/turfs/floors/mushroom.dmi differ diff --git a/monkestation/code/modules/map_gen_expansions/icons/turfs/floors/mushroom_blue.dmi b/monkestation/code/modules/map_gen_expansions/icons/turfs/floors/mushroom_blue.dmi new file mode 100644 index 000000000000..d2c46a2e2d68 Binary files /dev/null and b/monkestation/code/modules/map_gen_expansions/icons/turfs/floors/mushroom_blue.dmi differ diff --git a/monkestation/code/modules/map_gen_expansions/icons/turfs/floors/mushroom_green.dmi b/monkestation/code/modules/map_gen_expansions/icons/turfs/floors/mushroom_green.dmi new file mode 100644 index 000000000000..c963322f4ead Binary files /dev/null and b/monkestation/code/modules/map_gen_expansions/icons/turfs/floors/mushroom_green.dmi differ diff --git a/monkestation/code/modules/map_gen_expansions/icons/turfs/floors/plasma_forest.dmi b/monkestation/code/modules/map_gen_expansions/icons/turfs/floors/plasma_forest.dmi new file mode 100644 index 000000000000..38a62425429c Binary files /dev/null and b/monkestation/code/modules/map_gen_expansions/icons/turfs/floors/plasma_forest.dmi differ diff --git a/monkestation/code/modules/map_gen_expansions/icons/turfs/floors/plasma_forest_mask.dmi b/monkestation/code/modules/map_gen_expansions/icons/turfs/floors/plasma_forest_mask.dmi new file mode 100644 index 000000000000..b8fa24c78c87 Binary files /dev/null and b/monkestation/code/modules/map_gen_expansions/icons/turfs/floors/plasma_forest_mask.dmi differ diff --git a/monkestation/code/modules/map_gen_expansions/mushroom/flora.dm b/monkestation/code/modules/map_gen_expansions/mushroom/flora.dm new file mode 100644 index 000000000000..01c9a845eb79 --- /dev/null +++ b/monkestation/code/modules/map_gen_expansions/mushroom/flora.dm @@ -0,0 +1,213 @@ + +#define LIGHT_FIRE_BLOSSOM 2.1 + +/obj/structure/flora/tree + /// The type of stump to spawn when harvested. + var/stump_type = /obj/structure/flora/tree/stump + +/obj/structure/flora/tree/mushroom + name = "mushroom tree" + desc = "A large branching mushroom that seems to thrive under the planet's surface." + icon = 'monkestation/code/modules/map_gen_expansions/icons/mushroomtrees.dmi' + icon_state = "tree1" + base_icon_state = "tree_dead1" + pixel_x = -48 + pixel_y = -20 + stump_type = /obj/structure/flora/tree/stump/mushroom + +/obj/structure/flora/tree/mushroom/reverse + icon_state = "tree2" + stump_type = /obj/structure/flora/tree/stump/mushroom/reverse + +/obj/structure/flora/tree/mushroom/blue + icon_state = "tree_blue1" + +/obj/structure/flora/tree/mushroom/blue/reverse + icon_state = "tree_blue2" + stump_type = /obj/structure/flora/tree/stump/mushroom/reverse + +/obj/structure/flora/tree/mushroom/green + icon_state = "tree_green1" + +/obj/structure/flora/tree/mushroom/green/reverse + icon_state = "tree_green2" + stump_type = /obj/structure/flora/tree/stump/mushroom/reverse + +/obj/structure/flora/tree/stump/mushroom + icon = 'monkestation/code/modules/map_gen_expansions/icons/mushroomtrees.dmi' + icon_state = "tree1_dead" + pixel_x = -48 + pixel_y = -20 + +/obj/structure/flora/tree/stump/mushroom/reverse + icon_state = "tree2_dead" + +/obj/structure/flora/ash/tall_shroom/colored + desc = "A number of large mushrooms, covered in a faint layer of what can only be spores." + icon = 'monkestation/code/modules/map_gen_expansions/icons/mushroom_flora.dmi' + icon_state = "l_mushroom_red1" + base_icon_state = "l_mushroom_red" + number_of_variants = 1 + +/obj/structure/flora/ash/tall_shroom/colored/blue + icon_state = "l_mushroom_blue1" + base_icon_state = "l_mushroom_blue" + +/obj/structure/flora/ash/tall_shroom/colored/green + icon_state = "l_mushroom_green1" + base_icon_state = "l_mushroom_green" + +/obj/structure/flora/ash/leaf_shroom/colored + desc = "A number of mushrooms, each of which surrounds a colorful sporangium with a number of leaf-like structures." + icon = 'monkestation/code/modules/map_gen_expansions/icons/mushroom_flora.dmi' + icon_state = "s_mushroom_red1" + base_icon_state = "s_mushroom_red" + number_of_variants = 1 + +/obj/structure/flora/ash/leaf_shroom/colored/blue + icon_state = "s_mushroom_blue1" + base_icon_state = "s_mushroom_blue" + +/obj/structure/flora/ash/leaf_shroom/colored/green + icon_state = "s_mushroom_green1" + base_icon_state = "s_mushroom_green" + +/obj/structure/flora/ash/cap_shroom/colored + icon = 'monkestation/code/modules/map_gen_expansions/icons/mushroom_flora.dmi' + icon_state = "r_mushroom_red1" + base_icon_state = "r_mushroom_red" + number_of_variants = 1 + +/obj/structure/flora/ash/cap_shroom/colored/blue + icon_state = "r_mushroom_blue1" + base_icon_state = "r_mushroom_blue" + +/obj/structure/flora/ash/cap_shroom/colored/green + icon_state = "r_mushroom_green1" + base_icon_state = "r_mushroom_green" + +/obj/structure/flora/ash/stem_shroom/colored + icon = 'monkestation/code/modules/map_gen_expansions/icons/mushroom_flora.dmi' + icon_state = "t_mushroom_red1" + base_icon_state = "t_mushroom_red" + +/obj/structure/flora/ash/stem_shroom/colored/blue + icon_state = "t_mushroom_blue1" + base_icon_state = "t_mushroom_blue" + +/obj/structure/flora/ash/stem_shroom/colored/green + icon_state = "t_mushroom_green1" + base_icon_state = "t_mushroom_green" + +/obj/structure/flora/mushroom + name = "mushroom" + desc = "Some type of large mushroom... It looks suspicious." + icon = 'monkestation/code/modules/map_gen_expansions/icons/mushroom_flora.dmi' + icon_state = "fake_stillcap_red" + flora_flags = FLORA_HERBAL + +/obj/structure/flora/mushroom/blue + icon_state = "fake_stillcap_blue" + +/obj/structure/flora/mushroom/green + icon_state = "fake_stillcap_green" + +/obj/structure/flora/ash/lightshroom + name = "lightshroom" + desc = "An odd glowing mushroom that grows in areas with underground liquid plasma springs." + icon = 'monkestation/code/modules/map_gen_expansions/icons/mushroom_flora.dmi' + icon_state = "red_mushroom1" + base_icon_state = "red_mushroom" + light_outer_range = LIGHT_FIRE_BLOSSOM + light_power = LIGHT_FIRE_BLOSSOM + light_color = COLOR_RED_LIGHT + product_types = list(/obj/item/food/grown/ash_flora/lightshroom = 1) + harvested_name = "lightshroom stems" + harvested_desc = "A few lightshroom stems, missing their caps." + harvest_amount_high = 3 + harvest_message_low = "You pluck a single, suitable mushroom." + harvest_message_med = "You pluck a number of mushrooms, leaving a few unsuitable ones." + harvest_message_high = "You pluck quite a lot of suitable mushrooms." + regrowth_time_low = 2500 + regrowth_time_high = 4000 + number_of_variants = 1 + +/obj/structure/flora/ash/lightshroom/after_harvest() + set_light_power(LIGHT_RANGE_FIRE_BLOSSOM_HARVESTED) + set_light_range(LIGHT_POWER_FIRE_BLOSSOM_HARVESTED) + update_light() + return ..() + +/obj/structure/flora/ash/lightshroom/regrow() + set_light_power(initial(light_power)) + set_light_range(initial(light_outer_range)) + update_light() + return ..() + +/obj/structure/flora/ash/lightshroom/blue + icon_state = "blue_mushroom1" + base_icon_state = "blue_mushroom" + light_color = COLOR_BIOLUMINESCENCE_BLUE + product_types = list(/obj/item/food/grown/ash_flora/lightshroom/blue = 1) + +/obj/structure/flora/ash/lightshroom/green + icon_state = "green_mushroom1" + base_icon_state = "green_mushroom" + light_color = COLOR_BIOLUMINESCENCE_GREEN + product_types = list(/obj/item/food/grown/ash_flora/lightshroom/green = 1) + +/obj/item/food/grown/ash_flora/lightshroom + name = "red lightshroom" + desc = "A glowing mushroom." + icon = 'monkestation/code/modules/map_gen_expansions/icons/mushroom_flora.dmi' + icon_state = "red_mushroom_grown" + seed = /obj/item/seeds/lavaland/lightshroom + wine_power = 40 + special_desc_requirement = EXAMINE_CHECK_JOB + special_desc_jobs = list("Botanist") + special_desc = "This flora contains some healing properties, if you can filter out the radioactive toxins." + +/obj/item/food/grown/ash_flora/lightshroom/blue + name = "blue lightshroom" + icon_state = "blue_mushroom_grown" + seed = /obj/item/seeds/lavaland/lightshroom/blue + +/obj/item/food/grown/ash_flora/lightshroom/green + name = "green lightshroom" + icon_state = "green_mushroom_grown" + seed = /obj/item/seeds/lavaland/lightshroom/green + +/obj/item/seeds/lavaland/lightshroom + name = "pack of red lightshroom mycelium" + desc = "These seeds grow into colorful lightshrooms." + plantname = "Red Lightshroom" + icon = 'monkestation/code/modules/map_gen_expansions/icons/mushroom_flora.dmi' + icon_state = "mycelium_red_mushroom" + species = "red_mushroom" + growthstages = 3 + growing_icon = 'monkestation/code/modules/map_gen_expansions/icons/mushroom_flora.dmi' + icon_dead = "red_mushroom_dead" + product = /obj/item/food/grown/ash_flora/lightshroom + genes = list(/datum/plant_gene/trait/plant_type/fungal_metabolism, /datum/plant_gene/trait/glow/red) + reagents_add = list(/datum/reagent/consumable/nutriment = 0.04, /datum/reagent/consumable/vitfro = 0.04, /datum/reagent/uranium/radium = 0.04) + graft_gene = /datum/plant_gene/trait/plant_type/fungal_metabolism + +/obj/item/seeds/lavaland/lightshroom/blue + name = "pack of blue lightshroom mycelium" + plantname = "Blue Lightshroom" + icon_state = "mycelium_blue_mushroom" + species = "blue_mushroom" + icon_dead = "blue_mushroom_dead" + product = /obj/item/food/grown/ash_flora/lightshroom/blue + genes = list(/datum/plant_gene/trait/plant_type/fungal_metabolism, /datum/plant_gene/trait/glow/blue) + +/obj/item/seeds/lavaland/lightshroom/green + name = "pack of green lightshroom mycelium" + plantname = "Green Lightshroom" + icon_state = "mycelium_green_mushroom" + species = "green_mushroom" + icon_dead = "green_mushroom_dead" + product = /obj/item/food/grown/ash_flora/lightshroom/green + genes = list(/datum/plant_gene/trait/plant_type/fungal_metabolism, /datum/plant_gene/trait/glow/green) + +#undef LIGHT_FIRE_BLOSSOM diff --git a/monkestation/code/modules/map_gen_expansions/mushroom/generator.dm b/monkestation/code/modules/map_gen_expansions/mushroom/generator.dm new file mode 100644 index 000000000000..c276d76dea0a --- /dev/null +++ b/monkestation/code/modules/map_gen_expansions/mushroom/generator.dm @@ -0,0 +1,109 @@ + +/datum/map_generator/cave_generator/forest/mushroom + name = "Mushroom Cave Biome Generator" + weighted_open_turf_types = list(/turf/open/misc/dirt/forest = 3, /turf/open/misc/asteroid/forest/mushroom = 2) + weighted_closed_turf_types = list(/turf/closed/mineral/random/forest = 1) + initial_closed_chance = 53 + birth_limit = 5 + death_limit = 4 + smoothing_iterations = 10 + + mob_spawn_chance = 0.25 //planning to increase this once we have custom mushroom mobs to increase diversity + flora_spawn_chance = 25 + + biome_accepted_turfs = list( + /turf/open/misc/asteroid/forest/mushroom = TRUE, + ) + possible_biomes = list( + BIOME_LOW_HEAT = list( + BIOME_LOW_HUMIDITY = /datum/biome/mushroom_cave/blue, + BIOME_MEDIUM_HUMIDITY = /datum/biome/mushroom_cave, + BIOME_HIGH_HUMIDITY = /datum/biome/mushroom_cave/green, + ), + BIOME_MEDIUM_HEAT = list( + BIOME_LOW_HUMIDITY = /datum/biome/mushroom_cave/green, + BIOME_MEDIUM_HUMIDITY = /datum/biome/mushroom_cave/blue, + BIOME_HIGH_HUMIDITY = /datum/biome/mushroom_cave, + ), + BIOME_HIGH_HEAT = list( + BIOME_LOW_HUMIDITY = /datum/biome/mushroom_cave, + BIOME_MEDIUM_HUMIDITY = /datum/biome/mushroom_cave/green, + BIOME_HIGH_HUMIDITY = /datum/biome/mushroom_cave/blue, + ) + ) + + weighted_mob_spawn_list = list( + /obj/effect/spawner/random/lavaland_mob/goliath = 1, + ) + weighted_flora_spawn_list = list( + /obj/structure/flora/tree/mushroom = 4, + /obj/structure/flora/tree/mushroom/reverse = 4, + /obj/structure/flora/ash/lightshroom = 2, + /obj/structure/flora/mushroom = 2, + /obj/structure/flora/ash/cap_shroom/colored = 1, + /obj/structure/flora/ash/leaf_shroom/colored = 1, + /obj/structure/flora/ash/stem_shroom/colored = 1, + /obj/structure/flora/ash/tall_shroom/colored = 1, + ) + +/datum/biome/mushroom_cave + turf_type = /turf/open/misc/asteroid/forest/mushroom + flora_density = 25 + feature_density = 0.25 + fauna_density = 1 + flora_types = list( + /obj/structure/flora/tree/mushroom = 4, + /obj/structure/flora/tree/mushroom/reverse = 4, + /obj/structure/flora/ash/lightshroom = 2, + /obj/structure/flora/mushroom = 2, + /obj/structure/flora/ash/cap_shroom/colored = 1, + /obj/structure/flora/ash/leaf_shroom/colored = 1, + /obj/structure/flora/ash/stem_shroom/colored = 1, + /obj/structure/flora/ash/tall_shroom/colored = 1, + ) + fauna_types = list( + /mob/living/basic/mining/stillcap = 3, + ) + feature_types = list( + /obj/structure/geyser/hollowwater = 10, + /obj/structure/geyser/plasma_oxide = 10, + /obj/structure/geyser/protozine = 10, + /obj/structure/geyser/random = 2, + /obj/structure/geyser/wittel = 10, + ) + +/datum/biome/mushroom_cave/blue + turf_type = /turf/open/misc/asteroid/forest/mushroom/blue + flora_density = 25 + feature_density = 0.25 + fauna_types = list( + /mob/living/basic/mining/stillcap/blue = 3, + ) + flora_types = list( + /obj/structure/flora/tree/mushroom/blue = 4, + /obj/structure/flora/tree/mushroom/blue/reverse = 4, + /obj/structure/flora/ash/lightshroom/blue = 2, + /obj/structure/flora/mushroom/blue = 2, + /obj/structure/flora/ash/cap_shroom/colored/blue = 1, + /obj/structure/flora/ash/leaf_shroom/colored/blue = 1, + /obj/structure/flora/ash/stem_shroom/colored/blue = 1, + /obj/structure/flora/ash/tall_shroom/colored/blue = 1, + ) + +/datum/biome/mushroom_cave/green + turf_type = /turf/open/misc/asteroid/forest/mushroom/green + flora_density = 25 + feature_density = 0.25 + fauna_types = list( + /mob/living/basic/mining/stillcap/green = 3, + ) + flora_types = list( + /obj/structure/flora/tree/mushroom/green = 4, + /obj/structure/flora/tree/mushroom/green/reverse = 4, + /obj/structure/flora/ash/lightshroom/green = 2, + /obj/structure/flora/mushroom/green = 2, + /obj/structure/flora/ash/cap_shroom/colored/green = 1, + /obj/structure/flora/ash/leaf_shroom/colored/green = 1, + /obj/structure/flora/ash/stem_shroom/colored/green = 1, + /obj/structure/flora/ash/tall_shroom/colored/green = 1, + ) diff --git a/monkestation/code/modules/map_gen_expansions/mushroom/mobs/stillcaps.dm b/monkestation/code/modules/map_gen_expansions/mushroom/mobs/stillcaps.dm new file mode 100644 index 000000000000..3d24d18a5a12 --- /dev/null +++ b/monkestation/code/modules/map_gen_expansions/mushroom/mobs/stillcaps.dm @@ -0,0 +1,100 @@ + +/mob/living/basic/mining/stillcap + name = "stillcap" + desc = "A strange, elusive creature that always seems to come out of nowhere." + icon = 'monkestation/code/modules/map_gen_expansions/icons/newfauna_wide.dmi' + icon_state = "stillcap_red" + icon_living = "stillcap_red" + base_icon_state = "stillcap_red" + icon_dead = "stillcap_red_dead" + pixel_x = -12 + base_pixel_x = -12 + mob_biotypes = MOB_ORGANIC|MOB_BEAST + + maxHealth = 180 + health = 180 + speed = 5 + obj_damage = 15 + melee_damage_lower = 15 + melee_damage_upper = 15 + attack_vis_effect = ATTACK_EFFECT_BITE + melee_attack_cooldown = 1.2 SECONDS + + attack_verb_continuous = "bites" + attack_verb_simple = "bite" + death_message = "collapses in a muted thud." + pass_flags_self = PASSMOB + + attack_sound = 'sound/weapons/bite.ogg' + move_force = MOVE_FORCE_WEAK + move_resist = MOVE_FORCE_WEAK + pull_force = MOVE_FORCE_WEAK + ai_controller = /datum/ai_controller/basic_controller/stillcap + + +/mob/living/basic/mining/stillcap/Initialize(mapload) + . = ..() + + AddElement(/datum/element/can_hide/basic, list(/turf/open/misc/asteroid/forest/mushroom)) + AddElement(/datum/element/ai_flee_while_injured) + AddElement(/datum/element/ai_retaliate) + AddComponent(/datum/component/basic_mob_ability_telegraph) + AddComponent(/datum/component/basic_mob_attack_telegraph, telegraph_duration = 0.6 SECONDS) + + +/mob/living/basic/mining/stillcap/red + name = "red stillcap" + desc = parent_type::desc + " This one appears to be red." + icon_state = "stillcap_red" + icon_living = "stillcap_red" + base_icon_state = "stillcap_red" + icon_dead = "stillcap_red_dead" + + +/mob/living/basic/mining/stillcap/blue + name = "blue stillcap" + desc = parent_type::desc + " This one appears to be blue." + icon_state = "stillcap_blue" + icon_living = "stillcap_blue" + base_icon_state = "stillcap_blue" + icon_dead = "stillcap_blue_dead" + + +/mob/living/basic/mining/stillcap/green + name = "green stillcap" + desc = parent_type::desc + " This one appears to be green." + icon_state = "stillcap_green" + icon_living = "stillcap_green" + base_icon_state = "stillcap_green" + icon_dead = "stillcap_green_dead" + +/datum/ai_controller/basic_controller/stillcap + blackboard = list( + BB_TARGETING_STRATEGY = /datum/targeting_strategy/basic/allow_items, + BB_PET_TARGETING_STRATEGY = /datum/targeting_strategy/basic/not_friends, + BB_BASIC_MOB_FLEE_DISTANCE = 25, + BB_AGGRO_RANGE = 5, + BB_TARGET_MINIMUM_STAT = HARD_CRIT, + BB_HIDING_HIDDEN = FALSE, + BB_HIDING_AGGRO_RANGE = DEFAULT_HIDING_AGGRO_RANGE, + BB_HIDING_COOLDOWN_MAXIMUM = 3 MINUTES, + BB_HIDING_COOLDOWN_MINIMUM = 1 MINUTES, + BB_HIDING_RANDOM_STOP_HIDING_CHANCE = 2, + ) + + ai_movement = /datum/ai_movement/basic_avoidance + idle_behavior = /datum/idle_behavior/idle_random_walk/hide + + planning_subtrees = list( + /datum/ai_planning_subtree/pet_planning, + /datum/ai_planning_subtree/stop_hiding_if_target, + /datum/ai_planning_subtree/simple_find_nearest_target_to_flee, + /datum/ai_planning_subtree/stop_hiding_if_target, + /datum/ai_planning_subtree/flee_target, + /datum/ai_planning_subtree/random_hiding, + /datum/ai_planning_subtree/target_retaliate/check_faction/stop_hiding, + /datum/ai_planning_subtree/simple_find_target, + /datum/ai_planning_subtree/stop_hiding_if_target, + /datum/ai_planning_subtree/attack_obstacle_in_path, + /datum/ai_planning_subtree/basic_melee_attack_subtree, + ) diff --git a/monkestation/code/modules/map_gen_expansions/new_turfs.dm b/monkestation/code/modules/map_gen_expansions/new_turfs.dm new file mode 100644 index 000000000000..0047f0e2b3a3 --- /dev/null +++ b/monkestation/code/modules/map_gen_expansions/new_turfs.dm @@ -0,0 +1,139 @@ +/turf/open/misc/asteroid/forest + gender = PLURAL + name = "grass" + desc = "A patch of grass." + icon = 'icons/turf/floors.dmi' + icon_state = "grass" + base_icon_state = "grass" + baseturfs = /turf/open/misc/dirt/forest + bullet_bounce_sound = null + footstep = FOOTSTEP_GRASS + barefootstep = FOOTSTEP_GRASS + clawfootstep = FOOTSTEP_GRASS + heavyfootstep = FOOTSTEP_GENERIC_HEAVY + smoothing_flags = SMOOTH_BITMASK | SMOOTH_BORDER + smoothing_groups = SMOOTH_GROUP_TURF_OPEN + SMOOTH_GROUP_FLOOR_GRASS + canSmoothWith = SMOOTH_GROUP_FLOOR_GRASS + SMOOTH_GROUP_CLOSED_TURFS + layer = HIGH_TURF_LAYER + //damaged_dmi = 'icons/turf/damaged.dmi' + initial_gas_mix = FOREST_DEFAULT_ATMOS + flags_1 = NONE + planetary_atmos = TRUE + dig_result = /obj/item/food/grown/grass + /// Which icon file to use for turf specific edge smoothing states. + var/smooth_icon = 'icons/turf/floors/grass.dmi' + +/turf/open/misc/asteroid/forest/Initialize(mapload) + . = ..() + if(smoothing_flags) + var/matrix/translation = new + translation.Translate(-9, -9) + transform = translation + icon = smooth_icon + + if(is_station_level(z)) + GLOB.station_turfs += src + +/turf/open/misc/asteroid/forest/getDug() + . = ..() + AddComponent(/datum/component/simple_farm) + +/turf/open/misc/asteroid/forest/mushroom + name = "mushroom floor" + desc = "A patch of mushrooms." + icon = 'monkestation/code/modules/map_gen_expansions/icons/floors.dmi' + icon_state = "mushroom" + base_icon_state = "mushroom" + smoothing_groups = SMOOTH_GROUP_TURF_OPEN + SMOOTH_GROUP_MUSHROOM + canSmoothWith = SMOOTH_GROUP_CLOSED_TURFS + SMOOTH_GROUP_MUSHROOM + //damaged_dmi = 'icons/turf/damaged.dmi' + smooth_icon = 'monkestation/code/modules/map_gen_expansions/icons/turfs/floors/mushroom.dmi' + dig_result = /obj/item/food/grown/ash_flora + light_outer_range = 2 + light_power = 0.50 + light_color = COLOR_VERY_LIGHT_GRAY + +/turf/open/misc/asteroid/forest/mushroom/blue + icon_state = "mushroom_blue" + base_icon_state = "mushroom_blue" + smooth_icon = 'monkestation/code/modules/map_gen_expansions/icons/turfs/floors/mushroom_blue.dmi' + +/turf/open/misc/asteroid/forest/mushroom/green + icon_state = "mushroom_green" + base_icon_state = "mushroom_green" + smooth_icon = 'monkestation/code/modules/map_gen_expansions/icons/turfs/floors/mushroom_green.dmi' + +/turf/open/openspace/forest + name = "open forest air" + baseturfs = /turf/open/openspace/forest + initial_gas_mix = FOREST_DEFAULT_ATMOS + planetary_atmos = TRUE + +/turf/open/misc/dirt/forest + desc = "Hard-packed dirt - much too hard to plant seeds in." + initial_gas_mix = FOREST_DEFAULT_ATMOS + planetary_atmos = TRUE + +/turf/open/misc/sandy_dirt/forest + initial_gas_mix = FOREST_DEFAULT_ATMOS + planetary_atmos = TRUE + +/turf/closed/mineral/random/forest + name = "forest mountainside" + icon = MAP_SWITCH('icons/turf/walls/mountain_wall.dmi', 'icons/turf/mining.dmi') + icon_state = "mountainrock" + base_icon_state = "mountain_wall" + smoothing_flags = SMOOTH_BITMASK | SMOOTH_BORDER + canSmoothWith = SMOOTH_GROUP_CLOSED_TURFS + defer_change = TRUE + turf_type = /turf/open/misc/dirt/forest + baseturfs = /turf/open/misc/dirt/forest + initial_gas_mix = FOREST_DEFAULT_ATMOS + weak_turf = TRUE + +/turf/closed/mineral/random/forest/Change_Ore(ore_type, random = 0) + . = ..() + if(mineralType) + icon = 'icons/turf/walls/icerock_wall.dmi' + icon_state = "icerock_wall-0" + base_icon_state = "icerock_wall" + smoothing_flags = SMOOTH_BITMASK | SMOOTH_BORDER + +/turf/closed/mineral/random/forest/mineral_chances() + return list( + /obj/item/stack/ore/bluespace_crystal = 1, + /obj/item/stack/ore/diamond = 1, + /obj/item/stack/ore/gold = 10, + /obj/item/stack/ore/iron = 40, + /obj/item/stack/ore/plasma = 20, + /obj/item/stack/ore/silver = 12, + /obj/item/stack/ore/titanium = 11, + /obj/item/stack/ore/uranium = 5, + ) + +/turf/open/floor/engine/hull/reinforced/planetary + desc = "Sturdy exterior hull plating that separates you from the outside world" + initial_gas_mix = FOREST_DEFAULT_ATMOS + +/turf/open/floor/engine/hull/planetary + desc = "Sturdy exterior hull plating that separates you from the outside world." + initial_gas_mix = FOREST_DEFAULT_ATMOS + +/turf/open/lava/plasma/forest + initial_gas_mix = FOREST_DEFAULT_ATMOS + baseturfs = /turf/open/lava/plasma/forest + planetary_atmos = TRUE + + icon = 'monkestation/code/modules/map_gen_expansions/icons/turfs/floors/plasma_forest.dmi' + mask_icon = 'monkestation/code/modules/map_gen_expansions/icons/turfs/floors/plasma_forest_mask.dmi' + icon_state = "plasma_forest-255" + mask_state = "plasma_forest-255" + base_icon_state = "plasma_forest" + smoothing_flags = SMOOTH_BITMASK | SMOOTH_BORDER + smoothing_groups = SMOOTH_GROUP_TURF_OPEN + SMOOTH_GROUP_FLOOR_LAVA + canSmoothWith = SMOOTH_GROUP_FLOOR_LAVA + underfloor_accessibility = 2 //This avoids strangeness when routing pipes / wires along catwalks over lava + +/turf/open/floor/plating/forest + icon_state = "plating" + initial_gas_mix = FOREST_DEFAULT_ATMOS diff --git a/tgstation.dme b/tgstation.dme index 75560fda7457..fb319029ed2d 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -390,7 +390,9 @@ #include "code\__DEFINES\~monkestation\antagonists.dm" #include "code\__DEFINES\~monkestation\artifact.dm" #include "code\__DEFINES\~monkestation\asteroids.dm" +#include "code\__DEFINES\~monkestation\atmospherics.dm" #include "code\__DEFINES\~monkestation\atom_hud.dm" +#include "code\__DEFINES\~monkestation\blackboard.dm" #include "code\__DEFINES\~monkestation\blueshift.dm" #include "code\__DEFINES\~monkestation\botany.dm" #include "code\__DEFINES\~monkestation\chat.dm" @@ -6811,6 +6813,23 @@ #include "monkestation\code\modules\logging\log_category.dm" #include "monkestation\code\modules\logging\log_holder.dm" #include "monkestation\code\modules\logging\categories\log_category_game.dm" +#include "monkestation\code\modules\map_gen_expansions\_basemapping.dm" +#include "monkestation\code\modules\map_gen_expansions\areas.dm" +#include "monkestation\code\modules\map_gen_expansions\new_turfs.dm" +#include "monkestation\code\modules\map_gen_expansions\ai\idle_behaviours.dm" +#include "monkestation\code\modules\map_gen_expansions\ai\behaviours\hiding.dm" +#include "monkestation\code\modules\map_gen_expansions\ai\subtree\find_target_not_hiding.dm" +#include "monkestation\code\modules\map_gen_expansions\ai\subtree\hiding.dm" +#include "monkestation\code\modules\map_gen_expansions\ai\subtree\retaliate_target.dm" +#include "monkestation\code\modules\map_gen_expansions\ai\subtree\stop_hiding_if_target.dm" +#include "monkestation\code\modules\map_gen_expansions\elements\can_hide.dm" +#include "monkestation\code\modules\map_gen_expansions\forest\atmosphere.dm" +#include "monkestation\code\modules\map_gen_expansions\forest\generator.dm" +#include "monkestation\code\modules\map_gen_expansions\forest\mobs\deer.dm" +#include "monkestation\code\modules\map_gen_expansions\forest\mobs\megadeer.dm" +#include "monkestation\code\modules\map_gen_expansions\mushroom\flora.dm" +#include "monkestation\code\modules\map_gen_expansions\mushroom\generator.dm" +#include "monkestation\code\modules\map_gen_expansions\mushroom\mobs\stillcaps.dm" #include "monkestation\code\modules\mapping\access_helpers.dm" #include "monkestation\code\modules\mapping\mapping_helpers.dm" #include "monkestation\code\modules\maptext\maptext_image_helper.dm"