diff --git a/code/_onclick/click.dm b/code/_onclick/click.dm
index ad36d33f34..8184c122e2 100644
--- a/code/_onclick/click.dm
+++ b/code/_onclick/click.dm
@@ -43,7 +43,7 @@
next_click = world.time + 1
- if(client.buildmode)
+ if(client && client.buildmode)
build_click(src, client.buildmode, params, A)
return
diff --git a/code/_onclick/hud/human.dm b/code/_onclick/hud/human.dm
index 1c903700b0..835834cf76 100644
--- a/code/_onclick/hud/human.dm
+++ b/code/_onclick/hud/human.dm
@@ -341,11 +341,13 @@
mymob.radio_use_icon.color = ui_color
mymob.radio_use_icon.alpha = ui_alpha
- mymob.client.screen = list()
+ if(mymob.client)
+ mymob.client.screen = list()
+
+ mymob.client.screen += hud_elements
+ mymob.client.screen += src.adding + src.hotkeybuttons
+ mymob.client.screen += mymob.client.void
- mymob.client.screen += hud_elements
- mymob.client.screen += src.adding + src.hotkeybuttons
- mymob.client.screen += mymob.client.void
inventory_shown = 0
return
diff --git a/code/game/objects/effects/effect_system.dm b/code/game/objects/effects/effect_system.dm
index 7d5275cbcd..00896e7107 100644
--- a/code/game/objects/effects/effect_system.dm
+++ b/code/game/objects/effects/effect_system.dm
@@ -238,6 +238,15 @@ steam.start() -- spawns the effect
if(prob(25))
L.emote("cough")
+/obj/effect/effect/smoke/bad/noxious
+ opacity = 0
+
+/obj/effect/effect/smoke/bad/noxious/affect(var/mob/living/L)
+ if (!..())
+ return 0
+ if(L.needs_to_breathe())
+ L.adjustToxLoss(1)
+
/* Not feasile until a later date
/obj/effect/effect/smoke/bad/Crossed(atom/movable/M as mob|obj)
..()
@@ -369,6 +378,9 @@ steam.start() -- spawns the effect
/datum/effect/effect/system/smoke_spread/bad
smoke_type = /obj/effect/effect/smoke/bad
+/datum/effect/effect/system/smoke_spread/noxious
+ smoke_type = /obj/effect/effect/smoke/bad/noxious
+
/datum/effect/effect/system/smoke_spread/fire
smoke_type = /obj/effect/effect/smoke/elemental/fire
diff --git a/code/modules/ai/ai_holder.dm b/code/modules/ai/ai_holder.dm
index aadcdaa9e2..b5272ea996 100644
--- a/code/modules/ai/ai_holder.dm
+++ b/code/modules/ai/ai_holder.dm
@@ -9,6 +9,10 @@
/mob/living/Initialize()
if(ai_holder_type)
ai_holder = new ai_holder_type(src)
+ if(istype(src, /mob/living/carbon/human))
+ var/mob/living/carbon/human/H = src
+ H.hud_used = new /datum/hud(H)
+ H.instantiate_hud(H.hud_used)
return ..()
/mob/living/Destroy()
@@ -220,7 +224,7 @@
/datum/ai_holder/proc/handle_stance_strategical()
ai_log("++++++++++ Slow Process Beginning ++++++++++", AI_LOG_TRACE)
ai_log("handle_stance_strategical() : Called.", AI_LOG_TRACE)
-
+
//We got left around for some reason. Goodbye cruel world.
if(!holder)
qdel(src)
diff --git a/code/modules/ai/ai_holder_targeting.dm b/code/modules/ai/ai_holder_targeting.dm
index f1f5ff4a3a..f33906c662 100644
--- a/code/modules/ai/ai_holder_targeting.dm
+++ b/code/modules/ai/ai_holder_targeting.dm
@@ -28,7 +28,7 @@
. = hearers(vision_range, holder) - holder // Remove ourselves to prevent suicidal decisions. ~ SRC is the ai_holder.
. -= dview_mob // Not the dview mob either, nerd.
- var/static/hostile_machines = typecacheof(list(/obj/machinery/porta_turret, /obj/mecha))
+ var/static/hostile_machines = typecacheof(list(/obj/machinery/porta_turret, /obj/mecha, /obj/structure/blob))
for(var/HM in typecache_filter_list(range(vision_range, holder), hostile_machines))
if(can_see(holder, HM, vision_range))
@@ -75,7 +75,7 @@
/datum/ai_holder/proc/give_target(new_target, urgent = FALSE)
ai_log("give_target() : Given '[new_target]', urgent=[urgent].", AI_LOG_TRACE)
target = new_target
-
+
if(target != null)
lose_target_time = 0
track_target_position()
@@ -155,6 +155,11 @@
return FALSE // Turrets won't get hurt if they're still in their cover.
return TRUE
+ if(istype(the_target, /obj/structure/blob)) // Blob mobs are always blob faction, but the blob can anger other things.
+ var/obj/structure/blob/Blob = the_target
+ if(holder.faction == Blob.faction)
+ return FALSE
+
return TRUE
// return FALSE
@@ -189,12 +194,12 @@
ai_log("remove_target() : Entering.", AI_LOG_TRACE)
if(target)
target = null
-
+
lose_target_time = 0
give_up_movement()
lose_target_position()
set_stance(STANCE_IDLE)
-
+
// Check if target is visible to us.
/datum/ai_holder/proc/can_see_target(atom/movable/the_target, view_range = vision_range)
ai_log("can_see_target() : Entering.", AI_LOG_TRACE)
@@ -274,7 +279,7 @@
// Sets a few vars so mobs that threaten will react faster to an attacker or someone who attacked them before.
/datum/ai_holder/proc/on_attacked(atom/movable/AM)
last_conflict_time = world.time
- add_attacker(AM)
+ add_attacker(AM)
// Checks to see if an atom attacked us lately
/datum/ai_holder/proc/check_attacker(var/atom/movable/A)
@@ -287,7 +292,7 @@
// Forgive this attacker
/datum/ai_holder/proc/remove_attacker(var/atom/movable/A)
attackers -= A.name
-
+
// Causes targeting to prefer targeting the taunter if possible.
// This generally occurs if more than one option is within striking distance, including the taunter.
// Otherwise the default filter will prefer the closest target.
diff --git a/code/modules/ai/interfaces.dm b/code/modules/ai/interfaces.dm
index 59ffbeea72..d1f7e91c53 100644
--- a/code/modules/ai/interfaces.dm
+++ b/code/modules/ai/interfaces.dm
@@ -11,6 +11,11 @@
return FALSE
return attack_target(A) // This will set click cooldown.
+/mob/living/carbon/human/IAttack(atom/A)
+ if(!canClick()) // Still on cooldown from a "click".
+ return FALSE
+ return ClickOn(A) // Except this is an actual fake "click".
+
/mob/living/proc/IRangedAttack(atom/A)
return FALSE
diff --git a/code/modules/blob2/blobs/base_blob.dm b/code/modules/blob2/blobs/base_blob.dm
index 767cf4c783..527184ebb2 100644
--- a/code/modules/blob2/blobs/base_blob.dm
+++ b/code/modules/blob2/blobs/base_blob.dm
@@ -17,6 +17,7 @@ var/list/blobs = list()
var/heal_timestamp = 0 //we got healed when?
var/mob/observer/blob/overmind = null
var/base_name = "blob" // The name that gets appended along with the blob_type's name.
+ var/faction = "blob"
/obj/structure/blob/New(var/newloc, var/new_overmind)
..(newloc)
@@ -56,6 +57,8 @@ var/list/blobs = list()
return TRUE
else if(istype(mover, /obj/item/projectile))
var/obj/item/projectile/P = mover
+ if(istype(P.firer, /obj/structure/blob))
+ return TRUE
if(istype(P.firer) && P.firer.faction == "blob")
return TRUE
return FALSE
@@ -218,13 +221,97 @@ var/list/blobs = list()
qdel(src)
return B
+/obj/structure/blob/attack_generic(var/mob/user, var/damage, var/attack_verb)
+ visible_message("[user] [attack_verb] the [src]!")
+ playsound(loc, 'sound/effects/attackblob.ogg', 100, 1)
+ user.do_attack_animation(src)
+ if(overmind)
+ damage *= overmind.blob_type.brute_multiplier
+ else
+ damage *= 2
+
+ if(overmind)
+ damage = overmind.blob_type.on_received_damage(src, damage, BRUTE, user)
+
+ adjust_integrity(-damage)
+
+ return
+
+/obj/structure/blob/attack_hand(mob/living/M as mob)
+ if(ishuman(M))
+ var/mob/living/carbon/human/H = M
+ H.setClickCooldown(H.get_attack_speed())
+ var/datum/unarmed_attack/attack = H.get_unarmed_attack(src, BP_TORSO)
+ if(!attack)
+ return FALSE
+
+ if(attack.unarmed_override(H, src, BP_TORSO))
+ return FALSE
+
+ H.do_attack_animation(src)
+ H.visible_message("[H] strikes \the [src]!")
+
+ var/real_damage = rand(3,6)
+ var/hit_dam_type = attack.damage_type
+ real_damage += attack.get_unarmed_damage(H)
+ if(H.gloves)
+ if(istype(H.gloves, /obj/item/clothing/gloves))
+ var/obj/item/clothing/gloves/G = H.gloves
+ real_damage += G.punch_force
+ hit_dam_type = G.punch_damtype
+ if(HULK in H.mutations)
+ real_damage *= 2 // Hulks do twice the damage
+
+ real_damage = max(1, real_damage)
+
+ var/damage_mult_burn = 1
+ var/damage_mult_brute = 1
+
+ if(hit_dam_type == SEARING)
+ damage_mult_burn *= 0.3
+ damage_mult_brute *= 0.6
+
+ else if(hit_dam_type == BIOACID)
+ damage_mult_burn *= 0.6
+ damage_mult_brute = 0
+
+ else if(hit_dam_type in list(ELECTROCUTE, BURN))
+ damage_mult_brute = 0
+
+ else if(hit_dam_type in list(BRUTE, CLONE))
+ damage_mult_burn = 0
+
+ else if(hit_dam_type != HALLOSS) // Tox, Oxy, or something new. Half damage split to the organism.
+ damage_mult_burn = 0.25
+ damage_mult_brute = 0.25
+
+ else
+ damage_mult_brute = 0.25
+ damage_mult_burn = 0
+
+ var/burn_dam = real_damage * damage_mult_burn
+ var/brute_dam = real_damage * damage_mult_brute
+
+ if(overmind)
+ if(brute_dam)
+ brute_dam = overmind.blob_type.on_received_damage(src, brute_dam, BRUTE, M)
+ if(burn_dam)
+ burn_dam = overmind.blob_type.on_received_damage(src, burn_dam, BURN, M)
+
+ real_damage = burn_dam + brute_dam
+
+ adjust_integrity(-real_damage)
+
+ else
+ attack_generic(M, rand(1,10), "bashed")
+
/obj/structure/blob/attackby(var/obj/item/weapon/W, var/mob/user)
user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN)
playsound(loc, 'sound/effects/attackblob.ogg', 50, 1)
visible_message("\The [src] has been attacked with \the [W][(user ? " by [user]." : ".")]")
var/damage = W.force
switch(W.damtype)
- if(BURN)
+ if(BURN, BIOACID, ELECTROCUTE, OXY)
if(overmind)
damage *= overmind.blob_type.burn_multiplier
else
@@ -234,7 +321,7 @@ var/list/blobs = list()
playsound(src.loc, 'sound/items/welder.ogg', 100, 1)
else
playsound(src, 'sound/weapons/tap.ogg', 50, 1)
- if(BRUTE)
+ if(BRUTE, SEARING, TOX, CLONE)
if(overmind)
damage *= overmind.blob_type.brute_multiplier
else
diff --git a/code/modules/blob2/blobs/core.dm b/code/modules/blob2/blobs/core.dm
index f43ec7ad6f..fc2e325ae2 100644
--- a/code/modules/blob2/blobs/core.dm
+++ b/code/modules/blob2/blobs/core.dm
@@ -78,6 +78,15 @@ var/list/blob_cores = list()
/obj/structure/blob/core/volatile_alluvium
desired_blob_type = /datum/blob_type/volatile_alluvium
+/obj/structure/blob/core/ravenous_macrophage
+ desired_blob_type = /datum/blob_type/ravenous_macrophage
+
+/obj/structure/blob/core/roiling_mold
+ desired_blob_type = /datum/blob_type/roiling_mold
+
+/obj/structure/blob/core/ectoplasmic_horror
+ desired_blob_type = /datum/blob_type/ectoplasmic_horror
+
/obj/structure/blob/core/classic
desired_blob_type = /datum/blob_type/classic
diff --git a/code/modules/blob2/blobs/factory.dm b/code/modules/blob2/blobs/factory.dm
index 6ee41ccd53..d574a0cfbc 100644
--- a/code/modules/blob2/blobs/factory.dm
+++ b/code/modules/blob2/blobs/factory.dm
@@ -51,3 +51,8 @@
name = "sluggish factory blob"
max_spores = 4
spore_cooldown = 16 SECONDS
+
+/obj/structure/blob/factory/turret // Produces a single spore slowly, but is intended to be used as a 'mortar' by the blob type.
+ name = "volatile factory blob"
+ max_spores = 1
+ spore_cooldown = 10 SECONDS
diff --git a/code/modules/blob2/overmind/types.dm b/code/modules/blob2/overmind/types.dm
index 24ffbd6b1b..6c453b51e9 100644
--- a/code/modules/blob2/overmind/types.dm
+++ b/code/modules/blob2/overmind/types.dm
@@ -595,6 +595,7 @@
/datum/blob_type/radioactive_ooze/on_pulse(var/obj/structure/blob/B)
SSradiation.radiate(B, 200)
+// A blob that steals your weapon.
/datum/blob_type/volatile_alluvium
name = "volatile alluvium"
desc = "A churning, earthy mass that moves in waves."
@@ -642,3 +643,161 @@
B.adjust_integrity(-(damage))
if(B && prob(damage))
B.visible_message("The [name] begins to crumble!")
+
+// A blob that produces noxious smoke-clouds and recycles its dying parts.
+/datum/blob_type/ravenous_macrophage
+ name = "ravenous macrophage"
+ desc = "A disgusting gel that reeks of death."
+ ai_desc = "resourceful"
+ effect_desc = "Produces noxious fumes, and melts prey with acidic attacks. Weak to brute damage."
+ difficulty = BLOB_DIFFICULTY_MEDIUM
+ color = "#639b3f"
+ complementary_color = "#d1ec3c"
+ damage_type = BIOACID
+ damage_lower = 20
+ damage_upper = 30
+ armor_check = "bio"
+ brute_multiplier = 0.8
+ burn_multiplier = 0.3
+ spread_modifier = 0.8
+ ai_aggressiveness = 70
+ attack_message = "The macrophage splashes you"
+ attack_message_living = ", and you feel a horrible burning"
+ attack_message_synth = ", and your body begins to corrode"
+ attack_verb = "splashes"
+
+/datum/blob_type/ravenous_macrophage/on_pulse(var/obj/structure/blob/B)
+ var/mob/living/L = locate() in range(world.view, B)
+ if(prob(1) && L.mind && !L.stat) // There's some active living thing nearby, produce offgas.
+ var/turf/T = get_turf(B)
+ var/datum/effect/effect/system/smoke_spread/noxious/BS = new /datum/effect/effect/system/smoke_spread/noxious
+ BS.attach(T)
+ BS.set_up(3, 0, T)
+ playsound(T, 'sound/effects/smoke.ogg', 50, 1, -3)
+ BS.start()
+
+/datum/blob_type/ravenous_macrophage/on_death(obj/structure/blob/B)
+ var/obj/structure/blob/other = locate() in oview(2, B)
+ if(other)
+ B.visible_message("The dying mass is rapidly consumed by the nearby [other]!")
+ if(other.overmind)
+ other.overmind.add_points(rand(1,4))
+
+// Blob that fires biological mortar shells from its factories.
+/datum/blob_type/roiling_mold
+ name = "roiling mold"
+ desc = "A bubbling, creeping mold."
+ ai_desc = "bombarding"
+ effect_desc = "Bombards nearby organisms with toxic spores. Weak to all damage."
+ difficulty = BLOB_DIFFICULTY_MEDIUM
+ color = "#571509"
+ complementary_color = "#ec4940"
+ damage_type = BRUTE
+ damage_lower = 5
+ damage_upper = 20
+ armor_check = "melee"
+ brute_multiplier = 1.2
+ burn_multiplier = 1.2
+ spread_modifier = 0.8
+ can_build_factories = TRUE
+ ai_aggressiveness = 50
+ attack_message = "The mold whips you"
+ attack_message_living = ", and you feel a searing pain"
+ attack_message_synth = ", and your shell buckles"
+ attack_verb = "lashes"
+ spore_projectile = /obj/item/projectile/arc/spore
+
+/datum/blob_type/roiling_mold/proc/find_target(var/obj/structure/blob/B, var/tries = 0, var/list/previous_targets = null)
+ if(tries > 3)
+ return
+ var/mob/living/L = locate() in (view(world.view + 3, get_turf(B)) - view(2,get_turf(B)) - previous_targets) // No adjacent mobs.
+
+ if(!check_trajectory(L, B, PASSTABLE))
+ if(!LAZYLEN(previous_targets))
+ previous_targets = list()
+
+ previous_targets |= L
+
+ L = find_target(B, tries + 1, previous_targets)
+
+ return L
+
+/datum/blob_type/roiling_mold/on_pulse(var/obj/structure/blob/B)
+ var/mob/living/L = find_target(B)
+
+ if(!istype(L))
+ return
+
+ if(istype(B, /obj/structure/blob/factory) && L.stat != DEAD && prob(ai_aggressiveness) && L.faction != "blob")
+ var/obj/item/projectile/arc/spore/P = new(get_turf(B))
+ P.launch_projectile(L, BP_TORSO, B)
+
+// A blob that drains energy from nearby mobs in order to fuel itself, and 'negates' some attacks extradimensionally.
+/datum/blob_type/ectoplasmic_horror
+ name = "ectoplasmic horror"
+ desc = "A disgusting translucent slime that feels out of place."
+ ai_desc = "dodging"
+ effect_desc = "Drains energy from nearby life-forms in order to expand itself. Weak to all damage."
+ difficulty = BLOB_DIFFICULTY_MEDIUM
+ color = "#72109eaa"
+ complementary_color = "#1a9de8"
+ damage_type = HALLOSS
+ damage_lower = 10
+ damage_upper = 30
+ armor_check = "energy"
+ brute_multiplier = 1.5
+ burn_multiplier = 1.5
+ spread_modifier = 0.9
+ ai_aggressiveness = 50
+ attack_message = "The horror strikes you"
+ attack_message_living = ", and you feel a wave of exhaustion"
+ attack_message_synth = ", and your systems begin to slow"
+ attack_verb = "strikes"
+ can_build_factories = TRUE
+ factory_type = /obj/structure/blob/factory/sluggish
+ spore_type = /mob/living/simple_mob/blob/spore/weak
+
+ var/list/active_beams = list()
+
+/datum/blob_type/ectoplasmic_horror/on_pulse(var/obj/structure/blob/B)
+ if(B.type == /obj/structure/blob && (locate(/obj/structure/blob/node) in oview(2, get_turf(B))))
+ B.visible_message("The [name] quakes, before hardening.")
+ new/obj/structure/blob/shield(get_turf(B), B.overmind)
+ qdel(B)
+
+ if(istype(B, /obj/structure/blob/factory))
+ listclearnulls(active_beams)
+ var/atom/movable/beam_origin = B
+ for(var/mob/living/L in oview(world.view, B))
+ if(L.stat == DEAD || L.faction == "blob")
+ continue
+ if(prob(5))
+ var/beamtarget_exists = FALSE
+
+ if(active_beams.len)
+ for(var/datum/beam/Beam in active_beams)
+ if(Beam.target == L)
+ beamtarget_exists = TRUE
+ break
+
+ if(!beamtarget_exists && GetAnomalySusceptibility(L) >= 0.5)
+ B.visible_message("\The [B] lashes out at \the [L]!")
+ var/datum/beam/drain_beam = beam_origin.Beam(L, icon_state = "drain_life", time = 10 SECONDS)
+ active_beams |= drain_beam
+ spawn(9 SECONDS)
+ if(B && drain_beam)
+ B.visible_message("\The [B] siphons energy from \the [L]")
+ L.add_modifier(/datum/modifier/berserk_exhaustion, 60 SECONDS)
+ B.overmind.add_points(rand(10,30))
+ if(!QDELETED(drain_beam))
+ qdel(drain_beam)
+
+/datum/blob_type/ectoplasmic_horror/on_received_damage(var/obj/structure/blob/B, damage, damage_type)
+ if(prob(round(damage * 0.5)))
+ B.visible_message("\The [B] shimmers, distorting through some unseen dimension.")
+ var/initial_alpha = B.alpha
+ spawn()
+ animate(B,alpha = initial_alpha, alpha = 10, time = 10)
+ animate(B,alpha = 10, alpha = initial_alpha, time = 10)
+ return 0
+ return ..()
diff --git a/code/modules/mob/living/carbon/human/ai_controlled/ai_controlled.dm b/code/modules/mob/living/carbon/human/ai_controlled/ai_controlled.dm
index 431b7c4456..7b222d8a61 100644
--- a/code/modules/mob/living/carbon/human/ai_controlled/ai_controlled.dm
+++ b/code/modules/mob/living/carbon/human/ai_controlled/ai_controlled.dm
@@ -3,6 +3,8 @@
ai_holder_type = /datum/ai_holder/simple_mob/melee/evasive
+ a_intent = I_HURT
+
var/generate_species = SPECIES_HUMAN
var/generate_dead = FALSE
diff --git a/code/modules/mob/living/living_defense.dm b/code/modules/mob/living/living_defense.dm
index 09e85364ca..b767c66b43 100644
--- a/code/modules/mob/living/living_defense.dm
+++ b/code/modules/mob/living/living_defense.dm
@@ -206,6 +206,9 @@
var/soaked = get_armor_soak(def_zone, armor_check, armor_pen)
var/absorb = run_armor_check(def_zone, armor_check, armor_pen)
+ if(ai_holder)
+ ai_holder.react_to_attack(B)
+
apply_damage(damage, damage_type, def_zone, absorb, soaked)
/mob/living/proc/resolve_item_attack(obj/item/I, mob/living/user, var/target_zone)
diff --git a/code/modules/projectiles/projectile/arc.dm b/code/modules/projectiles/projectile/arc.dm
index 1f19dc0242..5a281029ac 100644
--- a/code/modules/projectiles/projectile/arc.dm
+++ b/code/modules/projectiles/projectile/arc.dm
@@ -49,7 +49,6 @@
on_impact(loc)
return ..()
-
/obj/item/projectile/arc/launch_projectile(atom/target, target_zone, mob/user, params, angle_override, forced_spread = 0)
fired_dir = get_dir(user, target) // Used to determine if the projectile should turn in the air.
distance_to_fly = calculate_initial_pixel_distance(user, target) // Calculates how many pixels to travel before hitting the ground.
@@ -168,3 +167,32 @@
/obj/item/projectile/arc/radioactive/on_impact(turf/T)
SSradiation.radiate(T, rad_power)
+
+// Blob mortar
+/obj/item/projectile/arc/spore
+ name = "spore"
+ icon_state = "declone"
+ damage = 20
+ damage_type = BIOACID
+ armor_penetration = 30
+ fire_sound = 'sound/effects/slime_squish.ogg'
+
+/obj/item/projectile/arc/spore/on_impact(turf/T)
+ for(var/mob/living/L in T)
+ attack_mob(L)
+
+ spawn()
+ T.visible_message("\The [src] covers \the [T] in a corrosive paste!")
+ for(var/turf/simulated/floor/F in view(2, T))
+ spawn()
+ var/obj/effect/effect/water/splash = new(T)
+ splash.create_reagents(15)
+ splash.reagents.add_reagent("stomacid", 5)
+ splash.reagents.add_reagent("blood", 10,list("blood_colour" = "#ec4940"))
+
+ splash.set_up(F, 2, 3)
+
+ var/obj/effect/decal/cleanable/chemcoating/acid = locate() in T
+ if(!istype(acid))
+ acid = new(T)
+ acid.reagents.add_reagent("stomacid", 5)
diff --git a/polaris.dme b/polaris.dme
index 33d64e5d5f..87856f2658 100644
--- a/polaris.dme
+++ b/polaris.dme
@@ -2864,7 +2864,7 @@
#include "code\ZAS\Zone.dm"
#include "interface\interface.dm"
#include "interface\skin.dmf"
-#include "maps\southern_cross\southern_cross.dm"
+#include "maps\example\example.dm"
#include "maps\submaps\space_submaps\space.dm"
#include "maps\submaps\surface_submaps\mountains\mountains.dm"
#include "maps\submaps\surface_submaps\mountains\mountains_areas.dm"