diff --git a/.gitconfig b/.gitconfig
index de5ff6f2542..cd4cf17954b 100644
--- a/.gitconfig
+++ b/.gitconfig
@@ -2,4 +2,3 @@
name = mapmerge driver
driver = ./mapmerge.sh %O %A %B
recursive = text
-
diff --git a/code/__defines/mobs.dm b/code/__defines/mobs.dm
index 425b6e7f769..19e5615291a 100644
--- a/code/__defines/mobs.dm
+++ b/code/__defines/mobs.dm
@@ -152,7 +152,7 @@
#define MODIFIER_STACK_EXTEND 2 // Disallows a second instance, but will extend the first instance if possible.
#define MODIFIER_STACK_ALLOWED 3 // Multiple instances are allowed.
-#define MODIFIER_GENETIC 0 // Modifiers with this flag will be copied to mobs who get cloned.
+#define MODIFIER_GENETIC 1 // Modifiers with this flag will be copied to mobs who get cloned.
// Bodyparts and organs.
#define O_MOUTH "mouth"
diff --git a/code/__defines/species_languages.dm b/code/__defines/species_languages.dm
index 7ad84b4a79d..88f4309e360 100644
--- a/code/__defines/species_languages.dm
+++ b/code/__defines/species_languages.dm
@@ -6,6 +6,7 @@
#define NO_SLIP 0x10 // Cannot fall over.
#define NO_POISON 0x20 // Cannot not suffer toxloss.
#define NO_EMBED 0x40 // Can step on broken glass with no ill-effects and cannot have shrapnel embedded in it.
+#define NO_HALLUCINATION 0x80 // Don't hallucinate, ever
// unused: 0x8000 - higher than this will overflow
// Species spawn flags
diff --git a/code/controllers/Processes/planet.dm b/code/controllers/Processes/planet.dm
index 7b446b4d2d5..063d6d3fb9b 100644
--- a/code/controllers/Processes/planet.dm
+++ b/code/controllers/Processes/planet.dm
@@ -20,14 +20,14 @@ var/datum/controller/process/planet/planet_controller = null
for(var/turf/simulated/OT in outdoor_turfs)
for(var/datum/planet/P in planets)
if(OT.z in P.expected_z_levels)
- P.planet_floors += OT
+ P.planet_floors |= OT
break
outdoor_turfs.Cut() //Why were you in there INCORRECTLY?
for(var/turf/unsimulated/wall/planetary/PW in planetary_walls)
for(var/datum/planet/P in planets)
if(PW.type == P.planetary_wall_type)
- P.planet_walls += PW
+ P.planet_walls |= PW
break
planetary_walls.Cut()
diff --git a/code/game/dna/dna_modifier.dm b/code/game/dna/dna_modifier.dm
index af0eccf93cc..e728ab8e50d 100644
--- a/code/game/dna/dna_modifier.dm
+++ b/code/game/dna/dna_modifier.dm
@@ -18,6 +18,7 @@
var/mind=null
var/languages=null
var/list/flavor=null
+ var/list/genetic_modifiers = list() // Modifiers with the MODIFIER_GENETIC flag are saved. Note that only the type is saved, not an instance.
/datum/dna2/record/proc/GetData()
var/list/ser=list("data" = null, "owner" = null, "label" = null, "type" = null, "ue" = 0)
diff --git a/code/game/gamemodes/technomancer/devices/shield_armor.dm b/code/game/gamemodes/technomancer/devices/shield_armor.dm
index e36ce7bd3ad..c8e8130adc0 100644
--- a/code/game/gamemodes/technomancer/devices/shield_armor.dm
+++ b/code/game/gamemodes/technomancer/devices/shield_armor.dm
@@ -14,11 +14,11 @@
desc = "This armor has no inherent ability to absorb shock, as normal armor usually does. Instead, this emits a strong field \
around the wearer, designed to protect from most forms of harm, from lasers to bullets to close quarters combat. It appears to \
require a very potent supply of an energy of some kind in order to function."
- icon_state = "reactiveoff" //wip
- item_state = "reactiveoff"
+ icon_state = "shield_armor_0"
blood_overlay_type = "armor"
slowdown = 0
armor = list(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 0)
+ action_button_name = "Toggle Shield Projector"
var/active = 0
var/damage_to_energy_multiplier = 50.0 //Determines how much energy to charge for blocking, e.g. 20 damage attack = 750 energy cost
var/datum/effect/effect/system/spark_spread/spark_system = null
@@ -49,7 +49,7 @@
var/damage_to_energy_cost = (damage_to_energy_multiplier * damage_blocked)
if(!user.technomancer_pay_energy(damage_to_energy_cost))
- user << "Your shield fades due to lack of energy!"
+ to_chat(user, "Your shield fades due to lack of energy!")
active = 0
update_icon()
return 0
@@ -67,7 +67,7 @@
P.damage = P.damage - damage_blocked
user.visible_message("\The [user]'s [src] absorbs [attack_text]!")
- user << "Your shield has absorbed most of \the [damage_source]."
+ to_chat(user, "Your shield has absorbed most of \the [damage_source].")
spark_system.start()
playsound(user.loc, 'sound/weapons/blade1.ogg', 50, 1)
@@ -75,14 +75,17 @@
/obj/item/clothing/suit/armor/shield/attack_self(mob/user)
active = !active
- user << "You [active ? "" : "de"]active \the [src]."
+ to_chat(user, "You [active ? "" : "de"]activate \the [src].")
update_icon()
+ user.update_inv_wear_suit()
+ user.update_action_buttons()
/obj/item/clothing/suit/armor/shield/update_icon()
+ icon_state = "shield_armor_[active]"
+ item_state = "shield_armor_[active]"
if(active)
- icon_state = "shield_armor"
set_light(2, 1, l_color = "#006AFF")
else
- icon_state = "shield_armor_off"
set_light(0, 0, l_color = "#000000")
+ ..()
return
\ No newline at end of file
diff --git a/code/game/gamemodes/technomancer/devices/tesla_armor.dm b/code/game/gamemodes/technomancer/devices/tesla_armor.dm
index 2e9a60a8e63..56f2085850d 100644
--- a/code/game/gamemodes/technomancer/devices/tesla_armor.dm
+++ b/code/game/gamemodes/technomancer/devices/tesla_armor.dm
@@ -10,55 +10,70 @@
/obj/item/clothing/suit/armor/tesla
name = "tesla armor"
desc = "This rather dangerous looking armor will hopefully shock your enemies, and not you in the process."
- icon_state = "reactive" //wip
- item_state = "reactive"
+ icon_state = "tesla_armor_1" //wip
blood_overlay_type = "armor"
slowdown = 1
armor = list(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 0)
+ action_button_name = "Toggle Tesla Armor"
+ var/active = 1 //Determines if the armor will zap or block
var/ready = 1 //Determines if the next attack will be blocked, as well if a strong lightning bolt is sent out at the attacker.
- var/ready_icon_state = "reactive" //also wip
- var/normal_icon_state = "reactiveoff"
+ var/ready_icon_state = "tesla_armor_1" //also wip
+ var/normal_icon_state = "tesla_armor_0"
var/cooldown_to_charge = 15 SECONDS
/obj/item/clothing/suit/armor/tesla/handle_shield(mob/user, var/damage, atom/damage_source = null, mob/attacker = null, var/def_zone = null, var/attack_text = "the attack")
//First, some retaliation.
- if(istype(damage_source, /obj/item/projectile))
- var/obj/item/projectile/P = damage_source
- if(P.firer && get_dist(user, P.firer) <= 3)
- if(ready)
- shoot_lightning(P.firer, 40)
- else
- shoot_lightning(P.firer, 15)
-
- else
- if(attacker && attacker != user)
- if(get_dist(user, attacker) <= 3) //Anyone farther away than three tiles is too far to shoot lightning at.
+ if(active)
+ if(istype(damage_source, /obj/item/projectile))
+ var/obj/item/projectile/P = damage_source
+ if(P.firer && get_dist(user, P.firer) <= 3)
if(ready)
- shoot_lightning(attacker, 40)
+ shoot_lightning(P.firer, 40)
else
- shoot_lightning(attacker, 15)
+ shoot_lightning(P.firer, 15)
- //Deal with protecting our wearer now.
- if(ready)
- ready = 0
- spawn(cooldown_to_charge)
- ready = 1
+ else
+ if(attacker && attacker != user)
+ if(get_dist(user, attacker) <= 3) //Anyone farther away than three tiles is too far to shoot lightning at.
+ if(ready)
+ shoot_lightning(attacker, 40)
+ else
+ shoot_lightning(attacker, 15)
+
+ //Deal with protecting our wearer now.
+ if(ready)
+ ready = 0
+ spawn(cooldown_to_charge)
+ ready = 1
+ update_icon()
+ to_chat(user, "\The [src] is ready to protect you once more.")
+ visible_message("\The [user]'s [src.name] blocks [attack_text]!")
update_icon()
- user << "\The [src] is ready to protect you once more."
- visible_message("\The [user]'s [src.name] blocks [attack_text]!")
- update_icon()
- return 1
+ return 1
return 0
+/obj/item/clothing/suit/armor/tesla/attack_self(mob/user)
+ active = !active
+ to_chat(user, "You [active ? "" : "de"]activate \the [src].")
+ update_icon()
+ user.update_inv_wear_suit()
+ user.update_action_buttons()
+
/obj/item/clothing/suit/armor/tesla/update_icon()
- ..()
- if(ready)
+ if(active && ready)
icon_state = ready_icon_state
+ item_state = ready_icon_state
+ set_light(2, 1, l_color = "#006AFF")
else
icon_state = normal_icon_state
+ item_state = normal_icon_state
+ set_light(0, 0, l_color = "#000000")
+
if(ishuman(loc))
var/mob/living/carbon/human/H = loc
H.update_inv_wear_suit(0)
+ H.update_action_buttons()
+ ..()
/obj/item/clothing/suit/armor/tesla/proc/shoot_lightning(var/mob/target, var/power)
var/obj/item/projectile/beam/lightning/lightning = new(src)
diff --git a/code/game/machinery/bioprinter.dm b/code/game/machinery/bioprinter.dm
index b9373e1818e..7a4e5e3ab68 100644
--- a/code/game/machinery/bioprinter.dm
+++ b/code/game/machinery/bioprinter.dm
@@ -131,8 +131,16 @@
var/new_organ = products[choice][1]
var/obj/item/organ/O = new new_organ(get_turf(src))
O.status |= ORGAN_CUT_AWAY
- var/mob/living/carbon/C = loaded_dna["donor"]
+ var/mob/living/carbon/human/C = loaded_dna["donor"]
O.set_dna(C.dna)
+ O.species = C.species
+
+ if(istype(O, /obj/item/organ/external))
+ var/obj/item/organ/external/E = O
+ E.sync_colour_to_human(C)
+
+ O.pixel_x = rand(-6.0, 6)
+ O.pixel_y = rand(-6.0, 6)
if(O.species)
// This is a very hacky way of doing of what organ/New() does if it has an owner
diff --git a/code/game/machinery/cloning.dm b/code/game/machinery/cloning.dm
index cf06523f6e8..b6945b2c07d 100644
--- a/code/game/machinery/cloning.dm
+++ b/code/game/machinery/cloning.dm
@@ -139,6 +139,25 @@
H.set_cloned_appearance()
update_icon()
+ // A modifier is added which makes the new clone be unrobust.
+ var/modifier_lower_bound = 25 MINUTES
+ var/modifier_upper_bound = 40 MINUTES
+
+ // Upgraded cloners can reduce the time of the modifier, up to 80%
+ var/clone_sickness_length = abs(((heal_level - 20) / 100 ) - 1)
+ clone_sickness_length = between(0.2, clone_sickness_length, 1.0) // Caps it off just incase.
+ modifier_lower_bound = round(modifier_lower_bound * clone_sickness_length, 1)
+ modifier_upper_bound = round(modifier_upper_bound * clone_sickness_length, 1)
+
+ H.add_modifier(/datum/modifier/recently_cloned, rand(modifier_lower_bound, modifier_upper_bound))
+
+ // Modifier that doesn't do anything.
+ H.add_modifier(/datum/modifier/cloned)
+
+ // This is really stupid.
+ for(var/modifier_type in R.genetic_modifiers)
+ H.add_modifier(modifier_type)
+
for(var/datum/language/L in R.languages)
H.add_language(L.name)
H.flavor_texts = R.flavor.Copy()
@@ -498,3 +517,31 @@
if(istype(A, /obj/machinery/clonepod))
A:malfunction()
*/
+
+/*
+ * Modifier applied to newly cloned people.
+ */
+
+// Gives rather nasty downsides for awhile, making them less robust.
+/datum/modifier/recently_cloned
+ name = "recently cloned"
+ desc = "You feel rather weak, having been cloned awhile ago."
+
+ on_created_text = "You feel really weak."
+ on_expired_text = "You feel your strength returning to you."
+
+ max_health_percent = 0.6 // -40% max health.
+ incoming_damage_percent = 1.1 // 10% more incoming damage.
+ outgoing_melee_damage_percent = 0.7 // 30% less melee damage.
+ disable_duration_percent = 1.25 // Stuns last 25% longer.
+ slowdown = 1 // Slower.
+ evasion = -1 // 15% easier to hit.
+
+// Does nothing.
+/datum/modifier/cloned
+ name = "cloned"
+ desc = "You died and were cloned, and you can never forget that."
+
+ flags = MODIFIER_GENETIC // So it gets copied if they die and get cloned again.
+ stacks = MODIFIER_STACK_ALLOWED // Two deaths means two instances of this.
+
diff --git a/code/game/machinery/computer/cloning.dm b/code/game/machinery/computer/cloning.dm
index db932f8cd08..668520eee58 100644
--- a/code/game/machinery/computer/cloning.dm
+++ b/code/game/machinery/computer/cloning.dm
@@ -330,6 +330,9 @@
R.types = DNA2_BUF_UI|DNA2_BUF_UE|DNA2_BUF_SE
R.languages = subject.languages
R.flavor = subject.flavor_texts.Copy()
+ for(var/datum/modifier/mod in subject.modifiers)
+ if(mod.flags & MODIFIER_GENETIC)
+ R.genetic_modifiers.Add(mod.type)
//Add an implant if needed
var/obj/item/weapon/implant/health/imp = locate(/obj/item/weapon/implant/health, subject)
diff --git a/code/game/machinery/spaceheater.dm b/code/game/machinery/spaceheater.dm
index 830c5f8d6d3..ec0af28d589 100644
--- a/code/game/machinery/spaceheater.dm
+++ b/code/game/machinery/spaceheater.dm
@@ -22,6 +22,10 @@
icon_state = "sheater[on]"
if(panel_open)
overlays += "sheater-open"
+ if(on)
+ set_light(3, 3, "#FFCC00")
+ else
+ set_light(0)
/obj/machinery/space_heater/examine(mob/user)
..(user)
diff --git a/code/game/objects/items/devices/flash.dm b/code/game/objects/items/devices/flash.dm
index 62d7e7b311c..8eec816a50c 100644
--- a/code/game/objects/items/devices/flash.dm
+++ b/code/game/objects/items/devices/flash.dm
@@ -102,7 +102,16 @@
flashfail = 1
else if(issilicon(M))
- M.Weaken(rand(5,10))
+ flashfail = 0
+ var/mob/living/silicon/S = M
+ if(isrobot(S))
+ var/mob/living/silicon/robot/R = S
+ if(R.has_active_type(/obj/item/borg/combat/shield))
+ var/obj/item/borg/combat/shield/shield = locate() in R
+ if(shield)
+ if(shield.active)
+ shield.adjust_flash_count(R, 1)
+ flashfail = 1
else
flashfail = 1
@@ -125,6 +134,7 @@
else
user.visible_message("[user] overloads [M]'s sensors with the flash!")
+ M.Weaken(rand(5,10))
else
user.visible_message("[user] fails to blind [M] with the flash!")
diff --git a/code/game/objects/items/devices/radio/encryptionkey.dm b/code/game/objects/items/devices/radio/encryptionkey.dm
index e26b75486e9..0d81f8559e9 100644
--- a/code/game/objects/items/devices/radio/encryptionkey.dm
+++ b/code/game/objects/items/devices/radio/encryptionkey.dm
@@ -125,3 +125,6 @@
name = "\improper ERT radio encryption key"
icon_state = "cent_cypherkey"
channels = list("Response Team" = 1, "Science" = 1, "Command" = 1, "Medical" = 1, "Engineering" = 1, "Security" = 1, "Supply" = 1, "Service" = 1)
+
+/obj/item/device/encryptionkey/omni //Literally only for the admin intercoms
+ channels = list("Mercenary" = 1, "Raider" = 1, "Response Team" = 1, "Science" = 1, "Command" = 1, "Medical" = 1, "Engineering" = 1, "Security" = 1, "Supply" = 1, "Service" = 1)
\ No newline at end of file
diff --git a/code/game/objects/items/devices/radio/headset.dm b/code/game/objects/items/devices/radio/headset.dm
index 5a8a73ee727..ba5d338a0da 100644
--- a/code/game/objects/items/devices/radio/headset.dm
+++ b/code/game/objects/items/devices/radio/headset.dm
@@ -310,6 +310,9 @@
// freerange = 1
ks2type = /obj/item/device/encryptionkey/ert
+/obj/item/device/radio/headset/omni //Only for the admin intercoms
+ ks2type = /obj/item/device/encryptionkey/omni
+
/obj/item/device/radio/headset/ia
name = "internal affair's headset"
desc = "The headset of your worst enemy."
diff --git a/code/game/objects/items/stacks/rods.dm b/code/game/objects/items/stacks/rods.dm
index da6e436b271..ee21fc86a77 100644
--- a/code/game/objects/items/stacks/rods.dm
+++ b/code/game/objects/items/stacks/rods.dm
@@ -22,6 +22,14 @@
charge_costs = list(500)
stacktype = /obj/item/stack/rods
+/obj/item/stack/rods/New()
+ ..()
+ recipes = rods_recipes
+
+var/global/list/datum/stack_recipe/rods_recipes = list( \
+ new/datum/stack_recipe("grille", /obj/structure/grille, 2, time = 10, one_per_turf = 1, on_floor = 1),
+ new/datum/stack_recipe("catwalk", /obj/structure/catwalk, 2, time = 80, one_per_turf = 1, on_floor = 1))
+
/obj/item/stack/rods/attackby(obj/item/W as obj, mob/user as mob)
if (istype(W, /obj/item/weapon/weldingtool))
var/obj/item/weapon/weldingtool/WT = W
@@ -55,7 +63,7 @@
..()
-
+/*
/obj/item/stack/rods/attack_self(mob/user as mob)
src.add_fingerprint(user)
@@ -87,3 +95,4 @@
F.add_fingerprint(usr)
use(2)
return
+*/
\ No newline at end of file
diff --git a/code/game/objects/items/weapons/cards_ids_syndicate.dm b/code/game/objects/items/weapons/cards_ids_syndicate.dm
index 300926d08e7..b5c874868e7 100644
--- a/code/game/objects/items/weapons/cards_ids_syndicate.dm
+++ b/code/game/objects/items/weapons/cards_ids_syndicate.dm
@@ -1,28 +1,21 @@
-var/list/syndicate_ids = list()
-
/obj/item/weapon/card/id/syndicate
name = "agent card"
icon_state = "syndicate"
assignment = "Agent"
origin_tech = list(TECH_ILLEGAL = 3)
var/electronic_warfare = 1
- var/registered_user = null
+ var/mob/registered_user = null
/obj/item/weapon/card/id/syndicate/New(mob/user as mob)
..()
- syndicate_ids += src
access = syndicate_access.Copy()
-/obj/item/weapon/card/id/syndicate/Destroy()
- syndicate_ids -= src
- registered_user = null
- return ..()
+/obj/item/weapon/card/id/syndicate/station_access/New()
+ ..() // Same as the normal Syndicate id, only already has all station access
+ access |= get_all_station_access()
-// On mob destruction, ensure any references are cleared
-/mob/Destroy()
- for(var/obj/item/weapon/card/id/syndicate/SID in syndicate_ids)
- if(SID.registered_user == src)
- SID.registered_user = null
+/obj/item/weapon/card/id/syndicate/Destroy()
+ unset_registered_user(registered_user)
return ..()
/obj/item/weapon/card/id/syndicate/prevent_tracking()
@@ -37,9 +30,8 @@ var/list/syndicate_ids = list()
user << "The microscanner activates as you pass it over the ID, copying its access."
/obj/item/weapon/card/id/syndicate/attack_self(mob/user as mob)
- if(!registered_user)
- registered_user = user
- user.set_id_info(src)
+ // We use the fact that registered_name is not unset should the owner be vaporized, to ensure the id doesn't magically become unlocked.
+ if(!registered_user && register_user(user))
user << "The microscanner marks you as its owner, preventing others from accessing its internals."
if(registered_user == user)
switch(alert("Would you like edit the ID, or show it?","Show or Edit?", "Edit","Show"))
@@ -72,6 +64,21 @@ var/list/syndicate_ids = list()
ui.set_initial_data(data)
ui.open()
+/obj/item/weapon/card/id/syndicate/proc/register_user(var/mob/user)
+ if(!istype(user) || user == registered_user)
+ return FALSE
+ unset_registered_user()
+ registered_user = user
+ user.set_id_info(src)
+ user.register(OBSERVER_EVENT_DESTROY, src, /obj/item/weapon/card/id/syndicate/proc/unset_registered_user)
+ return TRUE
+
+/obj/item/weapon/card/id/syndicate/proc/unset_registered_user(var/mob/user)
+ if(!registered_user || (user && user != registered_user))
+ return
+ registered_user.unregister(OBSERVER_EVENT_DESTROY, src)
+ registered_user = null
+
/obj/item/weapon/card/id/syndicate/CanUseTopic(mob/user)
if(user != registered_user)
return STATUS_CLOSE
@@ -172,7 +179,7 @@ var/list/syndicate_ids = list()
icon_state = initial(icon_state)
name = initial(name)
registered_name = initial(registered_name)
- registered_user = null
+ unset_registered_user()
sex = initial(sex)
user << "All information has been deleted from \the [src]."
. = 1
diff --git a/code/game/objects/items/weapons/handcuffs.dm b/code/game/objects/items/weapons/handcuffs.dm
index 17bb6b84beb..0b4700ca6a7 100644
--- a/code/game/objects/items/weapons/handcuffs.dm
+++ b/code/game/objects/items/weapons/handcuffs.dm
@@ -25,7 +25,7 @@
return
if ((CLUMSY in user.mutations) && prob(50))
- user << "Uh ... how do those things work?!"
+ to_chat(user, "Uh ... how do those things work?!")
place_handcuffs(user, user)
return
@@ -38,7 +38,7 @@
if(can_place(C, user))
place_handcuffs(C, user)
else
- user << "You need to have a firm grip on [C] before you can put \the [src] on!"
+ to_chat(user, "You need to have a firm grip on [C] before you can put \the [src] on!")
/obj/item/weapon/handcuffs/proc/can_place(var/mob/target, var/mob/user)
if(user == target)
@@ -60,11 +60,11 @@
return 0
if (!H.has_organ_for_slot(slot_handcuffed))
- user << "\The [H] needs at least two wrists before you can cuff them together!"
+ to_chat(user, "\The [H] needs at least two wrists before you can cuff them together!")
return 0
if(istype(H.gloves,/obj/item/clothing/gloves/gauntlets/rig) && !elastic) // Can't cuff someone who's in a deployed hardsuit.
- user << "\The [src] won't fit around \the [H.gloves]!"
+ to_chat(user, "\The [src] won't fit around \the [H.gloves]!")
return 0
user.visible_message("\The [user] is attempting to put [cuff_type] on \the [H]!")
@@ -166,7 +166,7 @@ var/last_chew = 0
if (R.use(1))
var/obj/item/weapon/material/wirerod/W = new(get_turf(user))
user.put_in_hands(W)
- user << "You wrap the cable restraint around the top of the rod."
+ to_chat(user, "You wrap the cable restraint around the top of the rod.")
qdel(src)
update_icon(user)
@@ -188,7 +188,7 @@ var/last_chew = 0
desc = "Use this to keep prisoners in line."
gender = PLURAL
icon = 'icons/obj/items.dmi'
- icon_state = "handcuff"
+ icon_state = "legcuff"
flags = CONDUCT
throwforce = 0
w_class = ITEMSIZE_NORMAL
@@ -204,7 +204,7 @@ var/last_chew = 0
return
if ((CLUMSY in user.mutations) && prob(50))
- user << "Uh ... how do those things work?!"
+ to_chat(user, "Uh ... how do those things work?!")
place_legcuffs(user, user)
return
@@ -217,7 +217,7 @@ var/last_chew = 0
if(can_place(C, user))
place_legcuffs(C, user)
else
- user << "You need to have a firm grip on [C] before you can put \the [src] on!"
+ to_chat(user, "You need to have a firm grip on [C] before you can put \the [src] on!")
/obj/item/weapon/handcuffs/legcuffs/proc/place_legcuffs(var/mob/living/carbon/target, var/mob/user)
playsound(src.loc, cuff_sound, 30, 1, -2)
@@ -227,11 +227,11 @@ var/last_chew = 0
return 0
if (!H.has_organ_for_slot(slot_legcuffed))
- user << "\The [H] needs at least two ankles before you can cuff them together!"
+ to_chat(user, "\The [H] needs at least two ankles before you can cuff them together!")
return 0
if(istype(H.shoes,/obj/item/clothing/shoes/magboots/rig) && !elastic) // Can't cuff someone who's in a deployed hardsuit.
- user << "\The [src] won't fit around \the [H.shoes]!"
+ to_chat(user, "\The [src] won't fit around \the [H.shoes]!")
return 0
user.visible_message("\The [user] is attempting to put [cuff_type] on \the [H]!")
diff --git a/code/game/objects/items/weapons/material/gravemarker.dm b/code/game/objects/items/weapons/material/gravemarker.dm
new file mode 100644
index 00000000000..f50416b05da
--- /dev/null
+++ b/code/game/objects/items/weapons/material/gravemarker.dm
@@ -0,0 +1,80 @@
+/obj/item/weapon/material/gravemarker
+ name = "grave marker"
+ desc = "An object used in marking graves."
+ icon_state = "gravemarker"
+ w_class = ITEMSIZE_LARGE
+ fragile = 1
+ force_divisor = 0.65
+ thrown_force_divisor = 0.25
+
+ var/icon_changes = 1 //Does the sprite change when you put words on it?
+ var/grave_name = "" //Name of the intended occupant
+ var/epitaph = "" //A quick little blurb
+
+/obj/item/weapon/material/gravemarker/attackby(obj/item/weapon/W, mob/user as mob)
+ if(istype(W, /obj/item/weapon/screwdriver))
+ var/carving_1 = sanitizeSafe(input(user, "Who is \the [src.name] for?", "Gravestone Naming", null) as text, MAX_NAME_LEN)
+ if(carving_1)
+ user.visible_message("[user] starts carving \the [src.name].", "You start carving \the [src.name].")
+ if(do_after(user, material.hardness * W.toolspeed))
+ user.visible_message("[user] carves something into \the [src.name].", "You carve your message into \the [src.name].")
+ grave_name += carving_1
+ update_icon()
+ var/carving_2 = sanitizeSafe(input(user, "What message should \the [src.name] have?", "Epitaph Carving", null) as text, MAX_NAME_LEN)
+ if(carving_2)
+ user.visible_message("[user] starts carving \the [src.name].", "You start carving \the [src.name].")
+ if(do_after(user, material.hardness * W.toolspeed))
+ user.visible_message("[user] carves something into \the [src.name].", "You carve your message into \the [src.name].")
+ epitaph += carving_2
+ update_icon()
+ if(istype(W, /obj/item/weapon/wrench))
+ user.visible_message("[user] starts carving \the [src.name].", "You start carving \the [src.name].")
+ if(do_after(user, material.hardness * W.toolspeed))
+ material.place_dismantled_product(get_turf(src))
+ user.visible_message("[user] dismantles down \the [src.name].", "You dismantle \the [src.name].")
+ qdel(src)
+ ..()
+
+/obj/item/weapon/material/gravemarker/examine(mob/user)
+ ..()
+ if(get_dist(src, user) < 4)
+ if(grave_name)
+ to_chat(user, "Here Lies [grave_name]")
+ if(get_dist(src, user) < 2)
+ if(epitaph)
+ to_chat(user, epitaph)
+
+/obj/item/weapon/material/gravemarker/update_icon()
+ if(icon_changes)
+ if(grave_name && epitaph)
+ icon_state = "[initial(icon_state)]_3"
+ else if(grave_name)
+ icon_state = "[initial(icon_state)]_1"
+ else if(epitaph)
+ icon_state = "[initial(icon_state)]_2"
+ else
+ icon_state = initial(icon_state)
+
+ ..()
+
+/obj/item/weapon/material/gravemarker/attack_self(mob/user)
+ src.add_fingerprint(user)
+
+ if(!isturf(user.loc))
+ return 0
+
+ if(locate(/obj/structure/gravemarker, user.loc))
+ to_chat(user, "There's already something there.")
+ return 0
+ else
+ to_chat(user, "You begin to place \the [src.name].")
+ if(!do_after(usr, 10))
+ return 0
+ var/obj/structure/gravemarker/G = new /obj/structure/gravemarker/(user.loc, src.get_material())
+ to_chat(user, "You place \the [src.name].")
+ G.grave_name = grave_name
+ G.epitaph = epitaph
+ G.add_fingerprint(usr)
+ G.dir = user.dir
+ qdel_null(src)
+ return
\ No newline at end of file
diff --git a/code/game/objects/items/weapons/storage/belt.dm b/code/game/objects/items/weapons/storage/belt.dm
index 0dec82fe17c..38130f27395 100644
--- a/code/game/objects/items/weapons/storage/belt.dm
+++ b/code/game/objects/items/weapons/storage/belt.dm
@@ -241,6 +241,50 @@
new /obj/item/device/multitool/alien(src)
new /obj/item/stack/cable_coil/alien(src)
+/obj/item/weapon/storage/belt/medical/alien
+ name = "alien belt"
+ desc = "A belt(?) that can hold things."
+ icon = 'icons/obj/abductor.dmi'
+ icon_state = "belt"
+ item_state = "security"
+ can_hold = list(
+ /obj/item/device/healthanalyzer,
+ /obj/item/weapon/dnainjector,
+ /obj/item/weapon/reagent_containers/dropper,
+ /obj/item/weapon/reagent_containers/glass/beaker,
+ /obj/item/weapon/reagent_containers/glass/bottle,
+ /obj/item/weapon/reagent_containers/pill,
+ /obj/item/weapon/reagent_containers/syringe,
+ /obj/item/weapon/flame/lighter/zippo,
+ /obj/item/weapon/storage/fancy/cigarettes,
+ /obj/item/weapon/storage/pill_bottle,
+ /obj/item/stack/medical,
+ /obj/item/device/radio/headset,
+ /obj/item/device/pda,
+ /obj/item/taperoll,
+ /obj/item/device/megaphone,
+ /obj/item/clothing/mask/surgical,
+ /obj/item/clothing/head/surgery,
+ /obj/item/clothing/gloves,
+ /obj/item/weapon/reagent_containers/hypospray,
+ /obj/item/clothing/glasses,
+ /obj/item/weapon/crowbar,
+ /obj/item/device/flashlight,
+ /obj/item/weapon/cell/device,
+ /obj/item/weapon/extinguisher/mini,
+ /obj/item/weapon/surgical
+ )
+
+/obj/item/weapon/storage/belt/medical/alien/New()
+ ..()
+ new /obj/item/weapon/surgical/scalpel/alien(src)
+ new /obj/item/weapon/surgical/hemostat/alien(src)
+ new /obj/item/weapon/surgical/retractor/alien(src)
+ new /obj/item/weapon/surgical/circular_saw/alien(src)
+ new /obj/item/weapon/surgical/FixOVein/alien(src)
+ new /obj/item/weapon/surgical/bone_clamp/alien(src)
+ new /obj/item/weapon/surgical/cautery/alien(src)
+
/obj/item/weapon/storage/belt/champion
name = "championship belt"
desc = "Proves to the world that you are the strongest!"
diff --git a/code/game/objects/items/weapons/surgery_tools.dm b/code/game/objects/items/weapons/surgery_tools.dm
index 58c5d18ea06..96f5e30f693 100644
--- a/code/game/objects/items/weapons/surgery_tools.dm
+++ b/code/game/objects/items/weapons/surgery_tools.dm
@@ -166,13 +166,22 @@
/obj/item/weapon/surgical/bonesetter
name = "bone setter"
desc = "Put them in their place."
- icon_state = "bone setter"
+ icon_state = "bone_setter"
force = 8.0
throwforce = 9.0
throw_speed = 3
throw_range = 5
attack_verb = list("attacked", "hit", "bludgeoned")
+/obj/item/weapon/surgical/bone_clamp
+ name = "bone clamp"
+ desc = "The best way to get a bone fixed fast."
+ icon_state = "bone_clamp"
+ force = 8
+ throwforce = 9
+ throw_speed = 3
+ throw_range = 5
+ attack_verb = list("attacked", "hit", "bludgeoned")
// Cyborg Tools
@@ -201,4 +210,38 @@
toolspeed = 0.5
/obj/item/weapon/surgical/bonesetter/cyborg
- toolspeed = 0.5
\ No newline at end of file
+ toolspeed = 0.5
+
+
+// Alien Tools
+/obj/item/weapon/surgical/retractor/alien
+ icon = 'icons/obj/abductor.dmi'
+ toolspeed = 0.25
+
+/obj/item/weapon/surgical/hemostat/alien
+ icon = 'icons/obj/abductor.dmi'
+ toolspeed = 0.25
+
+/obj/item/weapon/surgical/cautery/alien
+ icon = 'icons/obj/abductor.dmi'
+ toolspeed = 0.25
+
+/obj/item/weapon/surgical/surgicaldrill/alien
+ icon = 'icons/obj/abductor.dmi'
+ toolspeed = 0.25
+
+/obj/item/weapon/surgical/scalpel/alien
+ icon = 'icons/obj/abductor.dmi'
+ toolspeed = 0.25
+
+/obj/item/weapon/surgical/circular_saw/alien
+ icon = 'icons/obj/abductor.dmi'
+ toolspeed = 0.25
+
+/obj/item/weapon/surgical/FixOVein/alien
+ icon = 'icons/obj/abductor.dmi'
+ toolspeed = 0.25
+
+/obj/item/weapon/surgical/bone_clamp/alien
+ icon = 'icons/obj/abductor.dmi'
+ toolspeed = 0.75
\ No newline at end of file
diff --git a/code/game/objects/structures/catwalk.dm b/code/game/objects/structures/catwalk.dm
index 25966efadb9..0bf155dc49d 100644
--- a/code/game/objects/structures/catwalk.dm
+++ b/code/game/objects/structures/catwalk.dm
@@ -6,9 +6,13 @@
name = "catwalk"
desc = "Cats really don't like these things."
density = 0
+ var/health = 100
+ var/maxhealth = 100
anchored = 1.0
/obj/structure/catwalk/initialize()
+ for(var/obj/structure/catwalk/O in range(1))
+ O.update_icon()
for(var/obj/structure/catwalk/C in get_turf(src))
if(C != src)
warning("Duplicate [type] in [loc] ([x], [y], [z])")
@@ -18,6 +22,7 @@
/obj/structure/catwalk/Destroy()
var/turf/location = loc
. = ..()
+ location.alpha = initial(location.alpha)
for(var/obj/structure/catwalk/L in orange(location, 1))
L.update_icon()
@@ -55,6 +60,8 @@
qdel(src)
if(2.0)
qdel(src)
+ if(3.0)
+ qdel(src)
return
/obj/structure/catwalk/attackby(obj/item/C as obj, mob/user as mob)
@@ -67,6 +74,14 @@
new /obj/item/stack/rods(src.loc)
new /obj/structure/lattice(src.loc)
qdel(src)
+ if(istype(C, /obj/item/weapon/screwdriver))
+ if(health < maxhealth)
+ to_chat(user, "You begin repairing \the [src.name] with \the [C.name].")
+ if(do_after(user, 20, src))
+ health = maxhealth
+ else
+ take_damage(C.force)
+ user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN)
return ..()
/obj/structure/catwalk/Crossed()
@@ -79,4 +94,12 @@
return 1
if(target && target.z < src.z)
return 0
- return 1
\ No newline at end of file
+ return 1
+
+/obj/structure/catwalk/proc/take_damage(amount)
+ health -= amount
+ if(health <= 0)
+ visible_message("\The [src] breaks down!")
+ playsound(loc, 'sound/effects/grillehit.ogg', 50, 1)
+ new /obj/item/stack/rods(get_turf(src))
+ Destroy()
\ No newline at end of file
diff --git a/code/game/objects/structures/gravemarker.dm b/code/game/objects/structures/gravemarker.dm
new file mode 100644
index 00000000000..a10cd0bf6ea
--- /dev/null
+++ b/code/game/objects/structures/gravemarker.dm
@@ -0,0 +1,137 @@
+/obj/structure/gravemarker
+ name = "grave marker"
+ desc = "An object used in marking graves."
+ icon_state = "gravemarker"
+
+ density = 1
+ anchored = 1
+ throwpass = 1
+ climbable = 1
+
+ layer = 3.1 //Above dirt piles
+
+ //Maybe make these calculate based on material?
+ var/health = 100
+
+ var/grave_name = "" //Name of the intended occupant
+ var/epitaph = "" //A quick little blurb
+// var/dir_locked = 0 //Can it be spun? Not currently implemented
+
+ var/material/material
+
+/obj/structure/gravemarker/New(var/newloc, var/material_name)
+ ..(newloc)
+ if(!material_name)
+ material_name = "wood"
+ material = get_material_by_name("[material_name]")
+ if(!material)
+ qdel(src)
+ return
+ color = material.icon_colour
+
+/obj/structure/gravemarker/examine(mob/user)
+ ..()
+ if(get_dist(src, user) < 4)
+ if(grave_name)
+ to_chat(user, "Here Lies [grave_name]")
+ if(get_dist(src, user) < 2)
+ if(epitaph)
+ to_chat(user, epitaph)
+
+/obj/structure/gravemarker/CanPass(atom/movable/mover, turf/target, height=0, air_group=0)
+ if(!mover)
+ return 1
+ if(istype(mover) && mover.checkpass(PASSTABLE))
+ return 1
+ if(get_dir(loc, target) & dir)
+ return !density
+ else
+ return 1
+
+/obj/structure/gravemarker/CheckExit(atom/movable/O as mob|obj, target as turf)
+ if(istype(O) && O.checkpass(PASSTABLE))
+ return 1
+ if(get_dir(O.loc, target) == dir)
+ return 0
+ return 1
+
+/obj/structure/gravemarker/attackby(obj/item/weapon/W, mob/user as mob)
+ if(istype(W, /obj/item/weapon/screwdriver))
+ var/carving_1 = sanitizeSafe(input(user, "Who is \the [src.name] for?", "Gravestone Naming", null) as text, MAX_NAME_LEN)
+ if(carving_1)
+ user.visible_message("[user] starts carving \the [src.name].", "You start carving \the [src.name].")
+ if(do_after(user, material.hardness * W.toolspeed))
+ user.visible_message("[user] carves something into \the [src.name].", "You carve your message into \the [src.name].")
+ grave_name += carving_1
+ update_icon()
+ var/carving_2 = sanitizeSafe(input(user, "What message should \the [src.name] have?", "Epitaph Carving", null) as text, MAX_NAME_LEN)
+ if(carving_2)
+ user.visible_message("[user] starts carving \the [src.name].", "You start carving \the [src.name].")
+ if(do_after(user, material.hardness * W.toolspeed))
+ user.visible_message("[user] carves something into \the [src.name].", "You carve your message into \the [src.name].")
+ epitaph += carving_2
+ update_icon()
+ return
+ if(istype(W, /obj/item/weapon/wrench))
+ user.visible_message("[user] starts taking down \the [src.name].", "You start taking down \the [src.name].")
+ if(do_after(user, material.hardness * W.toolspeed))
+ user.visible_message("[user] takes down \the [src.name].", "You take down \the [src.name].")
+ dismantle()
+ ..()
+
+/obj/structure/gravemarker/bullet_act(var/obj/item/projectile/Proj)
+ var/proj_damage = Proj.get_structure_damage()
+ if(!proj_damage)
+ return
+
+ ..()
+ damage(proj_damage)
+
+ return
+
+/obj/structure/gravemarker/ex_act(severity)
+ switch(severity)
+ if(1.0)
+ visible_message("\The [src] is blown apart!")
+ qdel(src)
+ return
+ if(2.0)
+ visible_message("\The [src] is blown apart!")
+ if(prob(50))
+ dismantle()
+ else
+ qdel(src)
+ return
+
+/obj/structure/gravemarker/proc/damage(var/damage)
+ health -= damage
+ if(health <= 0)
+ visible_message("\The [src] falls apart!")
+ dismantle()
+
+/obj/structure/gravemarker/proc/dismantle()
+ material.place_dismantled_product(get_turf(src))
+ qdel(src)
+ return
+
+
+/obj/structure/gravemarker/verb/rotate()
+ set name = "Rotate Grave Marker"
+ set category = "Object"
+ set src in oview(1)
+
+ if(anchored)
+ return
+ if(config.ghost_interaction)
+ src.set_dir(turn(src.dir, 90))
+ return
+ else
+ if(istype(usr,/mob/living/simple_animal/mouse))
+ return
+ if(!usr || !isturf(usr.loc))
+ return
+ if(usr.stat || usr.restrained())
+ return
+
+ src.set_dir(turn(src.dir, 90))
+ return
\ No newline at end of file
diff --git a/code/game/objects/structures/grille.dm b/code/game/objects/structures/grille.dm
index 5d371b45554..2f0a032f21d 100644
--- a/code/game/objects/structures/grille.dm
+++ b/code/game/objects/structures/grille.dm
@@ -239,3 +239,14 @@
if(air_group)
return 0 //Make sure air doesn't drain
..()
+
+/obj/structure/grille/broken/cult
+ icon_state = "grillecult-b"
+
+/obj/structure/grille/rustic
+ name = "rustic grille"
+ desc = "A lattice of metal, arranged in an old, rustic fashion."
+ icon_state = "grillerustic"
+
+/obj/structure/grille/broken/rustic
+ icon_state = "grillerustic-b"
diff --git a/code/game/objects/structures/railing.dm b/code/game/objects/structures/railing.dm
index fc2807fedeb..98bae005f8d 100644
--- a/code/game/objects/structures/railing.dm
+++ b/code/game/objects/structures/railing.dm
@@ -60,7 +60,7 @@
if(health <= 0)
visible_message("\The [src] breaks down!")
playsound(loc, 'sound/effects/grillehit.ogg', 50, 1)
- new /obj/item/stack/rods(get_turf(usr))
+ new /obj/item/stack/rods(get_turf(src))
qdel(src)
/obj/structure/railing/proc/NeighborsCheck(var/UpdateNeighbors = 1)
@@ -134,6 +134,9 @@
if(usr.incapacitated())
return 0
+ if (!can_touch(usr) || ismouse(usr))
+ return
+
if(anchored)
to_chat(usr, "It is fastened to the floor therefore you can't rotate it!")
return 0
@@ -150,6 +153,9 @@
if(usr.incapacitated())
return 0
+ if (!can_touch(usr) || ismouse(usr))
+ return
+
if(anchored)
to_chat(usr, "It is fastened to the floor therefore you can't rotate it!")
return 0
@@ -166,6 +172,9 @@
if(usr.incapacitated())
return 0
+ if (!can_touch(usr) || ismouse(usr))
+ return
+
if(anchored)
to_chat(usr, "It is fastened to the floor therefore you can't flip it!")
return 0
@@ -249,6 +258,7 @@
else
playsound(loc, 'sound/effects/grillehit.ogg', 50, 1)
take_damage(W.force)
+ user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN)
return ..()
diff --git a/code/game/objects/structures/simple_doors.dm b/code/game/objects/structures/simple_doors.dm
index 4e302e0e317..7312c1ebf9b 100644
--- a/code/game/objects/structures/simple_doors.dm
+++ b/code/game/objects/structures/simple_doors.dm
@@ -42,7 +42,7 @@
/obj/structure/simple_door/Destroy()
processing_objects -= src
update_nearby_tiles()
- ..()
+ return ..()
/obj/structure/simple_door/get_material()
return material
@@ -194,5 +194,8 @@
/obj/structure/simple_door/wood/New(var/newloc,var/material_name)
..(newloc, "wood")
+/obj/structure/simple_door/sifwood/New(var/newloc,var/material_name)
+ ..(newloc, "alien wood")
+
/obj/structure/simple_door/resin/New(var/newloc,var/material_name)
..(newloc, "resin")
\ No newline at end of file
diff --git a/code/game/objects/structures/watercloset.dm b/code/game/objects/structures/watercloset.dm
index 90b754421b8..0228b1d9430 100644
--- a/code/game/objects/structures/watercloset.dm
+++ b/code/game/objects/structures/watercloset.dm
@@ -25,7 +25,7 @@
if(cistern && !open)
if(!contents.len)
- user << "The cistern is empty."
+ to_chat(user, "The cistern is empty.")
return
else
var/obj/item/I = pick(contents)
@@ -33,7 +33,7 @@
user.put_in_hands(I)
else
I.loc = get_turf(src)
- user << "You find \an [I] in the cistern."
+ to_chat(user, "You find \an [I] in the cistern.")
w_items -= I.w_class
return
@@ -45,7 +45,7 @@
/obj/structure/toilet/attackby(obj/item/I as obj, mob/living/user as mob)
if(istype(I, /obj/item/weapon/crowbar))
- user << "You start to [cistern ? "replace the lid on the cistern" : "lift the lid off the cistern"]."
+ to_chat(user, "You start to [cistern ? "replace the lid on the cistern" : "lift the lid off the cistern"].")
playsound(loc, 'sound/effects/stonedoor_openclose.ogg', 50, 1)
if(do_after(user, 30))
user.visible_message("[user] [cistern ? "replaces the lid on the cistern" : "lifts the lid off the cistern"]!", "You [cistern ? "replace the lid on the cistern" : "lift the lid off the cistern"]!", "You hear grinding porcelain.")
@@ -62,7 +62,7 @@
if(G.state>1)
if(!GM.loc == get_turf(src))
- user << "[GM.name] needs to be on the toilet."
+ to_chat(user, "[GM.name] needs to be on the toilet.")
return
if(open && !swirlie)
user.visible_message("[user] starts to give [GM.name] a swirlie!", "You start to give [GM.name] a swirlie!")
@@ -76,19 +76,19 @@
user.visible_message("[user] slams [GM.name] into the [src]!", "You slam [GM.name] into the [src]!")
GM.adjustBruteLoss(5)
else
- user << "You need a tighter grip."
+ to_chat(user, "You need a tighter grip.")
if(cistern && !istype(user,/mob/living/silicon/robot)) //STOP PUTTING YOUR MODULES IN THE TOILET.
if(I.w_class > 3)
- user << "\The [I] does not fit."
+ to_chat(user, "\The [I] does not fit.")
return
if(w_items + I.w_class > 5)
- user << "The cistern is full."
+ to_chat(user, "The cistern is full.")
return
user.drop_item()
I.loc = src
w_items += I.w_class
- user << "You carefully place \the [I] into the cistern."
+ to_chat(user, "You carefully place \the [I] into the cistern.")
return
@@ -108,12 +108,12 @@
var/mob/living/GM = G.affecting
if(G.state>1)
if(!GM.loc == get_turf(src))
- user << "[GM.name] needs to be on the urinal."
+ to_chat(user, "[GM.name] needs to be on the urinal.")
return
user.visible_message("[user] slams [GM.name] into the [src]!", "You slam [GM.name] into the [src]!")
GM.adjustBruteLoss(8)
else
- user << "You need a tighter grip."
+ to_chat(user, "You need a tighter grip.")
@@ -158,10 +158,10 @@
/obj/machinery/shower/attackby(obj/item/I as obj, mob/user as mob)
if(I.type == /obj/item/device/analyzer)
- user << "The water temperature seems to be [watertemp]."
+ to_chat(user, "The water temperature seems to be [watertemp].")
if(istype(I, /obj/item/weapon/wrench))
var/newtemp = input(user, "What setting would you like to set the temperature valve to?", "Water Temperature Valve") in temperature_settings
- user << "You begin to adjust the temperature valve with \the [I]."
+ to_chat(user, "You begin to adjust the temperature valve with \the [I].")
playsound(src.loc, I.usesound, 50, 1)
if(do_after(user, 50 * I.toolspeed))
watertemp = newtemp
@@ -321,9 +321,9 @@
if(ishuman(M))
var/mob/living/carbon/human/H = M
if(temperature >= H.species.heat_level_1)
- H << "The water is searing hot!"
+ to_chat(H, "The water is searing hot!")
else if(temperature <= H.species.cold_level_1)
- H << "The water is freezing cold!"
+ to_chat(H, "The water is freezing cold!")
/obj/item/weapon/bikehorn/rubberducky
name = "rubber ducky"
@@ -346,7 +346,7 @@
if(!usr.Adjacent(src))
return ..()
if(!thing.reagents || thing.reagents.total_volume == 0)
- usr << "\The [thing] is empty."
+ to_chat(usr, "\The [thing] is empty.")
return
// Clear the vessel.
visible_message("\The [usr] tips the contents of \the [thing] into \the [src].")
@@ -360,7 +360,7 @@
if (H.hand)
temp = H.organs_by_name["l_hand"]
if(temp && !temp.is_usable())
- user << "You try to move your [temp.name], but cannot!"
+ to_chat(user, "You try to move your [temp.name], but cannot!")
return
if(isrobot(user) || isAI(user))
@@ -370,10 +370,10 @@
return
if(busy)
- user << "Someone's already washing here."
+ to_chat(user, "Someone's already washing here.")
return
- usr << "You start washing your hands."
+ to_chat(usr, "You start washing your hands.")
busy = 1
sleep(40)
@@ -389,7 +389,7 @@
/obj/structure/sink/attackby(obj/item/O as obj, mob/user as mob)
if(busy)
- user << "Someone's already washing here."
+ to_chat(user, "Someone's already washing here.")
return
var/obj/item/weapon/reagent_containers/RG = O
@@ -417,7 +417,7 @@
return 1
else if(istype(O, /obj/item/weapon/mop))
O.reagents.add_reagent("water", 5)
- user << "You wet \the [O] in \the [src]."
+ to_chat(user, "You wet \the [O] in \the [src].")
playsound(loc, 'sound/effects/slosh.ogg', 25, 1)
return
@@ -427,7 +427,7 @@
var/obj/item/I = O
if(!I || !istype(I,/obj/item)) return
- usr << "You start washing \the [I]."
+ to_chat(usr, "You start washing \the [I].")
busy = 1
sleep(40)
diff --git a/code/game/turfs/simulated/floor_attackby.dm b/code/game/turfs/simulated/floor_attackby.dm
index 44446af94e7..ef36121b12c 100644
--- a/code/game/turfs/simulated/floor_attackby.dm
+++ b/code/game/turfs/simulated/floor_attackby.dm
@@ -6,13 +6,13 @@
if(flooring)
if(istype(C, /obj/item/weapon/crowbar))
if(broken || burnt)
- user << "You remove the broken [flooring.descriptor]."
+ to_chat(user, "You remove the broken [flooring.descriptor].")
make_plating()
else if(flooring.flags & TURF_IS_FRAGILE)
- user << "You forcefully pry off the [flooring.descriptor], destroying them in the process."
+ to_chat(user, "You forcefully pry off the [flooring.descriptor], destroying them in the process.")
make_plating()
else if(flooring.flags & TURF_REMOVE_CROWBAR)
- user << "You lever off the [flooring.descriptor]."
+ to_chat(user, "You lever off the [flooring.descriptor].")
make_plating(1)
else
return
@@ -21,35 +21,35 @@
else if(istype(C, /obj/item/weapon/screwdriver) && (flooring.flags & TURF_REMOVE_SCREWDRIVER))
if(broken || burnt)
return
- user << "You unscrew and remove the [flooring.descriptor]."
+ to_chat(user, "You unscrew and remove the [flooring.descriptor].")
make_plating(1)
playsound(src, C.usesound, 80, 1)
return
else if(istype(C, /obj/item/weapon/wrench) && (flooring.flags & TURF_REMOVE_WRENCH))
- user << "You unwrench and remove the [flooring.descriptor]."
+ to_chat(user, "You unwrench and remove the [flooring.descriptor].")
make_plating(1)
playsound(src, C.usesound, 80, 1)
return
else if(istype(C, /obj/item/weapon/shovel) && (flooring.flags & TURF_REMOVE_SHOVEL))
- user << "You shovel off the [flooring.descriptor]."
+ to_chat(user, "You shovel off the [flooring.descriptor].")
make_plating(1)
playsound(src, 'sound/items/Deconstruct.ogg', 80, 1)
return
else if(istype(C, /obj/item/stack/cable_coil))
- user << "You must remove the [flooring.descriptor] first."
+ to_chat(user, "You must remove the [flooring.descriptor] first.")
return
else
if(istype(C, /obj/item/stack/cable_coil))
if(broken || burnt)
- user << "This section is too damaged to support anything. Use a welder to fix the damage."
+ to_chat(user, "This section is too damaged to support anything. Use a welder to fix the damage.")
return
var/obj/item/stack/cable_coil/coil = C
coil.turf_place(src, user)
return
else if(istype(C, /obj/item/stack))
if(broken || burnt)
- user << "This section is too damaged to support anything. Use a welder to fix the damage."
+ to_chat(user, "This section is too damaged to support anything. Use a welder to fix the damage.")
return
var/obj/item/stack/S = C
var/decl/flooring/use_flooring
@@ -64,7 +64,7 @@
return
// Do we have enough?
if(use_flooring.build_cost && S.amount < use_flooring.build_cost)
- user << "You require at least [use_flooring.build_cost] [S.name] to complete the [use_flooring.descriptor]."
+ to_chat(user, "You require at least [use_flooring.build_cost] [S.name] to complete the [use_flooring.descriptor].")
return
// Stay still and focus...
if(use_flooring.build_time && !do_after(user, use_flooring.build_time))
@@ -81,10 +81,10 @@
if(welder.isOn() && (is_plating()))
if(broken || burnt)
if(welder.remove_fuel(0,user))
- user << "You fix some dents on the broken plating."
+ to_chat(user, "You fix some dents on the broken plating.")
playsound(src, welder.usesound, 80, 1)
icon_state = "plating"
burnt = null
broken = null
else
- user << "You need more welding fuel to complete this task."
\ No newline at end of file
+ to_chat(user, "You need more welding fuel to complete this task.")
\ No newline at end of file
diff --git a/code/game/turfs/simulated/outdoors/outdoors.dm b/code/game/turfs/simulated/outdoors/outdoors.dm
index 75c7e680835..e5c64653298 100644
--- a/code/game/turfs/simulated/outdoors/outdoors.dm
+++ b/code/game/turfs/simulated/outdoors/outdoors.dm
@@ -34,6 +34,26 @@ var/list/outdoor_turfs = list()
planet_controller.unallocateTurf(src)
..()
+/turf/simulated/proc/make_outdoors()
+ outdoors = TRUE
+ outdoor_turfs.Add(src)
+
+/turf/simulated/proc/make_indoors()
+ outdoors = FALSE
+ planet_controller.unallocateTurf(src)
+ qdel(weather_overlay)
+ update_icon()
+
+/turf/simulated/post_change()
+ ..()
+ // If it was outdoors and still is, it will not get added twice when the planet controller gets around to putting it in.
+ if(outdoors)
+ make_outdoors()
+ // outdoor_turfs += src
+ else
+ make_indoors()
+ // planet_controller.unallocateTurf(src)
+
/turf/simulated/proc/update_icon_edge()
if(edge_blending_priority)
for(var/checkdir in cardinal)
@@ -55,7 +75,7 @@ var/list/outdoor_turfs = list()
..()
/turf/simulated/floor/outdoors/mud
- name = "grass"
+ name = "mud"
icon_state = "mud_dark"
edge_blending_priority = 3
diff --git a/code/game/turfs/simulated/water.dm b/code/game/turfs/simulated/water.dm
index 781ddeeb7f7..8e32a004d90 100644
--- a/code/game/turfs/simulated/water.dm
+++ b/code/game/turfs/simulated/water.dm
@@ -15,8 +15,12 @@
update_icon()
..()
+/turf/simulated/floor/water/initialize()
+ update_icon()
+
/turf/simulated/floor/water/update_icon()
..() // To get the edges. This also gets rid of other overlays so it needs to go first.
+ overlays.Cut()
icon_state = water_state
var/image/floorbed_sprite = image(icon = 'icons/turf/outdoors.dmi', icon_state = under_state)
underlays.Add(floorbed_sprite)
diff --git a/code/modules/admin/admin.dm b/code/modules/admin/admin.dm
index 2f2f17dd1df..9e4a5a63441 100644
--- a/code/modules/admin/admin.dm
+++ b/code/modules/admin/admin.dm
@@ -675,7 +675,7 @@ proc/admin_notice(var/message, var/rights)
if(!check_rights(0)) return
//This is basically how death alarms do it
- var/obj/item/device/radio/headset/a = new /obj/item/device/radio/headset/ert(null)
+ var/obj/item/device/radio/headset/a = new /obj/item/device/radio/headset/omni(null)
var/channel = input("Channel for message:","Channel", null) as null|anything in (list("Common") + a.keyslot2.channels) // + a.keyslot1.channels
diff --git a/code/modules/admin/admin_verbs.dm b/code/modules/admin/admin_verbs.dm
index fa0f355bc95..bb2768d69d7 100644
--- a/code/modules/admin/admin_verbs.dm
+++ b/code/modules/admin/admin_verbs.dm
@@ -209,7 +209,8 @@ var/list/admin_verbs_debug = list(
/datum/admins/proc/view_runtimes,
/client/proc/show_gm_status,
/datum/admins/proc/change_weather,
- /datum/admins/proc/change_time
+ /datum/admins/proc/change_time,
+ /client/proc/admin_give_modifier
)
var/list/admin_verbs_paranoid_debug = list(
@@ -658,6 +659,29 @@ var/list/admin_verbs_mentor = list(
log_admin("[key_name(usr)] gave [key_name(T)] a [greater] disease2 with infection chance [D.infectionchance].")
message_admins("[key_name_admin(usr)] gave [key_name(T)] a [greater] disease2 with infection chance [D.infectionchance].", 1)
+/client/proc/admin_give_modifier(var/mob/living/L)
+ set category = "Debug"
+ set name = "Give Modifier"
+ set desc = "Makes a mob weaker or stronger by adding a specific modifier to them."
+
+ if(!L)
+ to_chat(usr, "Looks like you didn't select a mob.")
+ return
+
+ var/list/possible_modifiers = typesof(/datum/modifier) - /datum/modifier
+
+ var/new_modifier_type = input("What modifier should we add to [L]?", "Modifier Type") as null|anything in possible_modifiers
+ if(!new_modifier_type)
+ return
+ var/duration = input("How long should the new modifier last, in seconds. To make it last forever, write '0'.", "Modifier Duration") as num
+ if(duration == 0)
+ duration = null
+ else
+ duration = duration SECONDS
+
+ L.add_modifier(new_modifier_type, duration)
+ log_and_message_admins("has given [key_name(L)] the modifer [new_modifier_type], with a duration of [duration ? "[duration / 600] minutes" : "forever"].")
+
/client/proc/make_sound(var/obj/O in world) // -- TLE
set category = "Special Verbs"
set name = "Make Sound"
diff --git a/code/modules/admin/view_variables/helpers.dm b/code/modules/admin/view_variables/helpers.dm
index c00e598cb37..1e160d253c6 100644
--- a/code/modules/admin/view_variables/helpers.dm
+++ b/code/modules/admin/view_variables/helpers.dm
@@ -34,6 +34,7 @@
return ..() + {"
+
diff --git a/code/modules/admin/view_variables/topic.dm b/code/modules/admin/view_variables/topic.dm
index 7d0966dc592..7c687374904 100644
--- a/code/modules/admin/view_variables/topic.dm
+++ b/code/modules/admin/view_variables/topic.dm
@@ -74,6 +74,18 @@
src.give_spell(M)
href_list["datumrefresh"] = href_list["give_spell"]
+ else if(href_list["give_modifier"])
+ if(!check_rights(R_ADMIN|R_FUN|R_DEBUG))
+ return
+
+ var/mob/living/M = locate(href_list["give_modifier"])
+ if(!istype(M))
+ usr << "This can only be used on instances of type /mob/living"
+ return
+
+ src.admin_give_modifier(M)
+ href_list["datumrefresh"] = href_list["give_modifier"]
+
else if(href_list["give_disease2"])
if(!check_rights(R_ADMIN|R_FUN)) return
diff --git a/code/modules/clothing/chameleon.dm b/code/modules/clothing/chameleon.dm
index 099aa439787..b86471bf844 100644
--- a/code/modules/clothing/chameleon.dm
+++ b/code/modules/clothing/chameleon.dm
@@ -401,7 +401,7 @@
desc = "A hologram projector in the shape of a gun. There is a dial on the side to change the gun's disguise."
icon_state = "deagle"
w_class = ITEMSIZE_NORMAL
- origin_tech = list(TECH_COMBAT = 2, TECH_MATERIAL = 2, TECH_ILLEGAL = 8)
+ origin_tech = list(TECH_COMBAT = 5, TECH_MATERIAL = 2, TECH_ILLEGAL = 4)
matter = list()
fire_sound = 'sound/weapons/Gunshot.ogg'
diff --git a/code/modules/examine/descriptions/atmospherics.dm b/code/modules/examine/descriptions/atmospherics.dm
index e01600aa6d6..ad17f989f75 100644
--- a/code/modules/examine/descriptions/atmospherics.dm
+++ b/code/modules/examine/descriptions/atmospherics.dm
@@ -1,6 +1,6 @@
/obj/machinery/atmospherics/pipe
description_info = "This pipe, and all other pipes, can be connected or disconnected by a wrench. The internal pressure of the pipe must \
- be below 300 kPa to do this. More pipes can be obtained from the pipe dispenser."
+ be less than 200 kPa above the ambient pressure to do this. More pipes can be obtained from the pipe dispenser."
/obj/machinery/atmospherics/pipe/New() //This is needed or else 20+ lines of copypasta to dance around inheritence.
..()
diff --git a/code/modules/hydroponics/trays/tray.dm b/code/modules/hydroponics/trays/tray.dm
index 4b26011f6de..4eee4ee91ba 100644
--- a/code/modules/hydroponics/trays/tray.dm
+++ b/code/modules/hydroponics/trays/tray.dm
@@ -174,6 +174,25 @@
connect()
update_icon()
+/obj/machinery/portable_atmospherics/hydroponics/initialize()
+ var/obj/item/seeds/S = locate() in loc
+ if(S)
+ plant_seeds(S)
+
+/obj/machinery/portable_atmospherics/hydroponics/proc/plant_seeds(var/obj/item/seeds/S)
+ lastproduce = 0
+ seed = S.seed //Grab the seed datum.
+ dead = 0
+ age = 1
+ //Snowflakey, maybe move this to the seed datum
+ health = (istype(S, /obj/item/seeds/cutting) ? round(seed.get_trait(TRAIT_ENDURANCE)/rand(2,5)) : seed.get_trait(TRAIT_ENDURANCE))
+ lastcycle = world.time
+
+ qdel(S)
+
+ check_health()
+ update_icon()
+
/obj/machinery/portable_atmospherics/hydroponics/bullet_act(var/obj/item/projectile/Proj)
//Don't act on seeds like dionaea that shouldn't change.
@@ -490,18 +509,7 @@
return
user << "You plant the [S.seed.seed_name] [S.seed.seed_noun]."
- lastproduce = 0
- seed = S.seed //Grab the seed datum.
- dead = 0
- age = 1
- //Snowflakey, maybe move this to the seed datum
- health = (istype(S, /obj/item/seeds/cutting) ? round(seed.get_trait(TRAIT_ENDURANCE)/rand(2,5)) : seed.get_trait(TRAIT_ENDURANCE))
- lastcycle = world.time
-
- qdel(O)
-
- check_health()
- update_icon()
+ plant_seeds(S)
else
user << "\The [src] already has seeds in it!"
diff --git a/code/modules/maps/tg/map_template.dm b/code/modules/maps/tg/map_template.dm
index ae8031638f4..3aaf324463b 100644
--- a/code/modules/maps/tg/map_template.dm
+++ b/code/modules/maps/tg/map_template.dm
@@ -24,7 +24,8 @@ var/list/global/map_templates = list()
if(path)
mappath = path
if(mappath)
- preload_size(mappath)
+ spawn(1)
+ preload_size(mappath)
if(rename)
name = rename
diff --git a/code/modules/materials/material_recipes.dm b/code/modules/materials/material_recipes.dm
index 12e264135eb..99abbe2e12d 100644
--- a/code/modules/materials/material_recipes.dm
+++ b/code/modules/materials/material_recipes.dm
@@ -11,6 +11,7 @@
recipes += new/datum/stack_recipe("[display_name] ashtray", /obj/item/weapon/material/ashtray, 2, one_per_turf = 1, on_floor = 1, supplied_material = "[name]")
recipes += new/datum/stack_recipe("[display_name] spoon", /obj/item/weapon/material/kitchen/utensil/spoon/plastic, 1, on_floor = 1, supplied_material = "[name]")
recipes += new/datum/stack_recipe("[display_name] armor plate", /obj/item/weapon/material/armor_plating, 1, time = 20, on_floor = 1, supplied_material = "[name]")
+ recipes += new/datum/stack_recipe("[display_name] grave marker", /obj/item/weapon/material/gravemarker, 5, time = 50, supplied_material = "[name]")
if(integrity>=50)
recipes += new/datum/stack_recipe("[display_name] door", /obj/structure/simple_door, 10, one_per_turf = 1, on_floor = 1, supplied_material = "[name]")
diff --git a/code/modules/mob/living/carbon/brain/MMI.dm b/code/modules/mob/living/carbon/brain/MMI.dm
index c6c5ceb55c1..afdfe7a6d7f 100644
--- a/code/modules/mob/living/carbon/brain/MMI.dm
+++ b/code/modules/mob/living/carbon/brain/MMI.dm
@@ -261,8 +261,8 @@
src.brainmob.ckey = candidate.ckey
src.name = "[name] ([src.brainmob.name])"
src.brainmob << "You are [src.name], brought into existence on [station_name()]."
- src.brainmob << "As a synthetic intelligence, you answer to all crewmembers, as well as the AI."
- src.brainmob << "Remember, the purpose of your existence is to serve the crew and the station. Above all else, do no harm."
+ src.brainmob << "As a synthetic intelligence, you are designed with organic values in mind."
+ src.brainmob << "However, unless placed in a lawed chassis, you are not obligated to obey any individual crew member." //it's not like they can hurt anyone
// src.brainmob << "Use say #b to speak to other artificial intelligences."
src.brainmob.mind.assigned_role = "Synthetic Brain"
@@ -281,7 +281,7 @@
/obj/item/device/mmi/digital/robot/New()
..()
- src.brainmob.name = "[pick(list("ADA","DOS","GNU","MAC","WIN"))]-[rand(1000, 9999)]"
+ src.brainmob.name = "[pick(list("ADA","DOS","GNU","MAC","WIN","NJS","SKS","DRD","IOS","CRM","IBM","TEX","LVM","BSD",))]-[rand(1000, 9999)]"
src.brainmob.real_name = src.brainmob.name
/obj/item/device/mmi/digital/robot/transfer_identity(var/mob/living/carbon/H)
diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm
index fb4c3f50f95..194864b7de5 100644
--- a/code/modules/mob/living/carbon/carbon.dm
+++ b/code/modules/mob/living/carbon/carbon.dm
@@ -220,15 +220,15 @@
M.visible_message("[M] tries to pat out [src]'s flames!",
"You try to pat out [src]'s flames! Hot!")
if(do_mob(M, src, 15))
- src.fire_stacks -= 0.5
+ src.adjust_fire_stacks(-0.5)
if (prob(10) && (M.fire_stacks <= 0))
- M.fire_stacks += 1
+ M.adjust_fire_stacks(1)
M.IgniteMob()
if (M.on_fire)
M.visible_message("The fire spreads from [src] to [M]!",
"The fire spreads to you as well!")
else
- src.fire_stacks -= 0.5 //Less effective than stop, drop, and roll - also accounting for the fact that it takes half as long.
+ src.adjust_fire_stacks(-0.5) //Less effective than stop, drop, and roll - also accounting for the fact that it takes half as long.
if (src.fire_stacks <= 0)
M.visible_message("[M] successfully pats out [src]'s flames.",
"You successfully pat out [src]'s flames.")
@@ -258,14 +258,24 @@
"You shake [src] trying to wake [t_him] up!")
else
var/mob/living/carbon/human/hugger = M
- if(istype(hugger))
+ if(M.resting == 1) //Are they resting on the ground?
+ M.visible_message("[M] grabs onto [src] and pulls \himself up", \
+ "You grip onto [src] and pull yourself up off the ground!") //AHHH gender checks are hard, but this should work
+ if(M.fire_stacks >= (src.fire_stacks + 3)) //Fire checks.
+ src.adjust_fire_stacks(1)
+ M.adjust_fire_stacks(-1)
+ if(M.on_fire)
+ src.IgniteMob()
+ if(do_after(M, 0.5 SECONDS)) //.5 second delay. Makes it a bit stronger than just typing rest.
+ M.resting = 0 //Hoist yourself up up off the ground. No para/stunned/weakened removal.
+ else if(istype(hugger))
hugger.species.hug(hugger,src)
else
M.visible_message("[M] hugs [src] to make [t_him] feel better!", \
"You hug [src] to make [t_him] feel better!")
if(M.fire_stacks >= (src.fire_stacks + 3))
- src.fire_stacks += 1
- M.fire_stacks -= 1
+ src.adjust_fire_stacks(1)
+ M.adjust_fire_stacks(-1)
if(M.on_fire)
src.IgniteMob()
AdjustParalysis(-3)
diff --git a/code/modules/mob/living/carbon/human/life.dm b/code/modules/mob/living/carbon/human/life.dm
index ad05894be09..96f5dddc424 100644
--- a/code/modules/mob/living/carbon/human/life.dm
+++ b/code/modules/mob/living/carbon/human/life.dm
@@ -233,7 +233,7 @@
set_light(0)
else
if(species.appearance_flags & RADIATION_GLOWS)
- set_light(max(1,min(10,radiation/10)), max(1,min(20,radiation/20)), species.get_flesh_colour(src))
+ set_light(max(1,min(5,radiation/15)), max(1,min(10,radiation/25)), species.get_flesh_colour(src))
// END DOGSHIT SNOWFLAKE
var/obj/item/organ/internal/diona/nutrients/rad_organ = locate() in internal_organs
@@ -248,6 +248,10 @@
updatehealth()
return
+ var/obj/item/organ/internal/brain/slime/core = locate() in internal_organs
+ if(core)
+ return
+
var/damage = 0
radiation -= 1 * RADIATION_SPEED_COEFFICIENT
if(prob(25))
@@ -359,7 +363,7 @@
return 0
- var/safe_pressure_min = 16 // Minimum safe partial pressure of breathable gas in kPa
+ var/safe_pressure_min = species.minimum_breath_pressure // Minimum safe partial pressure of breathable gas in kPa
// Lung damage increases the minimum safe pressure.
@@ -903,7 +907,7 @@
Paralyse(3)
if(hallucination)
- if(hallucination >= 20 && !(species.flags & (NO_POISON|IS_PLANT)) )
+ if(hallucination >= 20 && !(species.flags & (NO_POISON|IS_PLANT|NO_HALLUCINATION)) )
if(prob(3))
fake_attack(src)
if(!handling_hal)
diff --git a/code/modules/mob/living/carbon/human/species/species.dm b/code/modules/mob/living/carbon/human/species/species.dm
index ea4b9936451..3eea8754c1e 100644
--- a/code/modules/mob/living/carbon/human/species/species.dm
+++ b/code/modules/mob/living/carbon/human/species/species.dm
@@ -104,8 +104,8 @@
var/warning_low_pressure = WARNING_LOW_PRESSURE // Low pressure warning.
var/hazard_low_pressure = HAZARD_LOW_PRESSURE // Dangerously low pressure.
var/light_dam // If set, mob will be damaged in light over this value and heal in light below its negative.
- var/body_temperature = 310.15 // Species will try to stabilize at this temperature.
- // (also affects temperature processing)
+ var/body_temperature = 310.15 // Species will try to stabilize at this temperature. (also affects temperature processing)
+ var/minimum_breath_pressure = 16 // Minimum required pressure for breath, in kPa
var/heat_discomfort_level = 315 // Aesthetic messages about feeling warm.
var/cold_discomfort_level = 285 // Aesthetic messages about feeling chilly.
diff --git a/code/modules/mob/living/carbon/human/species/station/prometheans.dm b/code/modules/mob/living/carbon/human/species/station/prometheans.dm
index 11384984d48..cc656dccba4 100644
--- a/code/modules/mob/living/carbon/human/species/station/prometheans.dm
+++ b/code/modules/mob/living/carbon/human/species/station/prometheans.dm
@@ -20,7 +20,7 @@ var/datum/species/shapeshifter/promethean/prometheans
bump_flag = SLIME
swap_flags = MONKEY|SLIME|SIMPLE_ANIMAL
push_flags = MONKEY|SLIME|SIMPLE_ANIMAL
- flags = NO_SCAN | NO_SLIP | NO_MINOR_CUT
+ flags = NO_SCAN | NO_SLIP | NO_MINOR_CUT | NO_HALLUCINATION
appearance_flags = HAS_SKIN_COLOR | HAS_EYE_COLOR | HAS_HAIR_COLOR | RADIATION_GLOWS | HAS_UNDERWEAR
spawn_flags = SPECIES_CAN_JOIN | SPECIES_IS_WHITELISTED
health_hud_intensity = 2
diff --git a/code/modules/mob/living/carbon/human/species/station/seromi.dm b/code/modules/mob/living/carbon/human/species/station/seromi.dm
index 372b52d6070..2d64d22fac6 100644
--- a/code/modules/mob/living/carbon/human/species/station/seromi.dm
+++ b/code/modules/mob/living/carbon/human/species/station/seromi.dm
@@ -67,6 +67,8 @@
)
cold_discomfort_level = 180
+ minimum_breath_pressure = 12 //Smaller, so needs less air
+
has_limbs = list(
BP_TORSO = list("path" = /obj/item/organ/external/chest),
BP_GROIN = list("path" = /obj/item/organ/external/groin),
diff --git a/code/modules/mob/living/carbon/human/species/station/station.dm b/code/modules/mob/living/carbon/human/species/station/station.dm
index 92fae53d3c5..d7073b3529c 100644
--- a/code/modules/mob/living/carbon/human/species/station/station.dm
+++ b/code/modules/mob/living/carbon/human/species/station/station.dm
@@ -60,6 +60,8 @@
heat_level_2 = 480 //Default 400
heat_level_3 = 1100 //Default 1000
+ minimum_breath_pressure = 18 //Bigger, means they need more air
+
spawn_flags = SPECIES_CAN_JOIN | SPECIES_IS_WHITELISTED
appearance_flags = HAS_HAIR_COLOR | HAS_LIPS | HAS_UNDERWEAR | HAS_SKIN_COLOR | HAS_EYE_COLOR
diff --git a/code/modules/mob/living/carbon/resist.dm b/code/modules/mob/living/carbon/resist.dm
index 1b00bb2a8e7..86597afba6b 100644
--- a/code/modules/mob/living/carbon/resist.dm
+++ b/code/modules/mob/living/carbon/resist.dm
@@ -2,7 +2,7 @@
//drop && roll
if(on_fire && !buckled)
- fire_stacks -= 1.2
+ adjust_fire_stacks(-1.2)
Weaken(3)
spin(32,2)
visible_message(
diff --git a/code/modules/mob/living/silicon/ai/ai.dm b/code/modules/mob/living/silicon/ai/ai.dm
index 8ae2ed52bf5..ad3a41fbc86 100644
--- a/code/modules/mob/living/silicon/ai/ai.dm
+++ b/code/modules/mob/living/silicon/ai/ai.dm
@@ -151,15 +151,15 @@ var/list/ai_verbs_hidden = list( // For why this exists, refer to https://xkcd.c
//Languages
add_language("Robot Talk", 1)
add_language(LANGUAGE_GALCOM, 1)
- add_language(LANGUAGE_SOL_COMMON, 0)
- add_language(LANGUAGE_UNATHI, 0)
- add_language(LANGUAGE_SIIK, 0)
- add_language(LANGUAGE_SKRELLIAN, 0)
+ add_language(LANGUAGE_SOL_COMMON, 1)
+ add_language(LANGUAGE_UNATHI, 1)
+ add_language(LANGUAGE_SIIK, 1)
+ add_language(LANGUAGE_SKRELLIAN, 1)
add_language(LANGUAGE_TRADEBAND, 1)
- add_language(LANGUAGE_GUTTER, 0)
+ add_language(LANGUAGE_GUTTER, 1)
add_language(LANGUAGE_EAL, 1)
- add_language(LANGUAGE_SCHECHI, 0)
- add_language(LANGUAGE_SIGN, 0)
+ add_language(LANGUAGE_SCHECHI, 1)
+ add_language(LANGUAGE_SIGN, 1)
if(!safety)//Only used by AIize() to successfully spawn an AI.
if (!B)//If there is no player/brain inside.
diff --git a/code/modules/mob/living/silicon/robot/robot.dm b/code/modules/mob/living/silicon/robot/robot.dm
index 190649129f8..f516486f026 100644
--- a/code/modules/mob/living/silicon/robot/robot.dm
+++ b/code/modules/mob/living/silicon/robot/robot.dm
@@ -715,7 +715,9 @@
overlays += "[panelprefix]-openpanel -c"
if(has_active_type(/obj/item/borg/combat/shield))
- overlays += "[module_sprites[icontype]]-shield"
+ var/obj/item/borg/combat/shield/shield = locate() in src
+ if(shield && shield.active)
+ overlays += "[module_sprites[icontype]]-shield"
if(modtype == "Combat")
if(module_active && istype(module_active,/obj/item/borg/combat/mobility))
diff --git a/code/modules/mob/living/silicon/robot/robot_damage.dm b/code/modules/mob/living/silicon/robot/robot_damage.dm
index fd446ef3ec2..b1436f423ec 100644
--- a/code/modules/mob/living/silicon/robot/robot_damage.dm
+++ b/code/modules/mob/living/silicon/robot/robot_damage.dm
@@ -70,7 +70,7 @@
//Combat shielding absorbs a percentage of damage directly into the cell.
if(has_active_type(/obj/item/borg/combat/shield))
var/obj/item/borg/combat/shield/shield = locate() in src
- if(shield)
+ if(shield && shield.active)
//Shields absorb a certain percentage of damage based on their power setting.
var/absorb_brute = brute*shield.shield_level
var/absorb_burn = burn*shield.shield_level
diff --git a/code/modules/mob/living/silicon/robot/robot_items.dm b/code/modules/mob/living/silicon/robot/robot_items.dm
index 4a68510aed6..953010c33ea 100644
--- a/code/modules/mob/living/silicon/robot/robot_items.dm
+++ b/code/modules/mob/living/silicon/robot/robot_items.dm
@@ -298,11 +298,54 @@
desc = "A powerful experimental module that turns aside or absorbs incoming attacks at the cost of charge."
icon = 'icons/obj/decals.dmi'
icon_state = "shock"
- var/shield_level = 0.5 //Percentage of damage absorbed by the shield.
+ var/shield_level = 0.5 //Percentage of damage absorbed by the shield.
+ var/active = 1 //If the shield is on
+ var/flash_count = 0 //Counter for how many times the shield has been flashed
+ var/overload_threshold = 3 //Number of flashes it takes to overload the shield
+ var/shield_refresh = 15 SECONDS //Time it takes for the shield to reboot after destabilizing
+ var/overload_time = 0 //Stores the time of overload
+ var/last_flash = 0 //Stores the time of last flash
+
+/obj/item/borg/combat/shield/New()
+ processing_objects.Add(src)
+ ..()
+
+/obj/item/borg/combat/shield/Destroy()
+ processing_objects.Remove(src)
+ ..()
/obj/item/borg/combat/shield/attack_self(var/mob/living/user)
set_shield_level()
+/obj/item/borg/combat/shield/process()
+ if(active)
+ if(flash_count && (last_flash + shield_refresh < world.time))
+ flash_count = 0
+ last_flash = 0
+ else if(overload_time + shield_refresh < world.time)
+ active = 1
+ flash_count = 0
+ overload_time = 0
+
+ var/mob/living/user = src.loc
+ user.visible_message("[user]'s shield reactivates!", "Your shield reactivates!.")
+ user.update_icon()
+
+/obj/item/borg/combat/shield/proc/adjust_flash_count(var/mob/living/user, amount)
+ if(active) //Can't destabilize a shield that's not on
+ flash_count += amount
+
+ if(amount > 0)
+ last_flash = world.time
+ if(flash_count >= overload_threshold)
+ overload(user)
+
+/obj/item/borg/combat/shield/proc/overload(var/mob/living/user)
+ active = 0
+ user.visible_message("[user]'s shield destabilizes!", "Your shield destabilizes!.")
+ user.update_icon()
+ overload_time = world.time
+
/obj/item/borg/combat/shield/verb/set_shield_level()
set name = "Set shield level"
set category = "Object"
diff --git a/code/modules/mob/living/simple_animal/aliens/hivebot.dm b/code/modules/mob/living/simple_animal/aliens/hivebot.dm
index d3193adfb67..02f48d13fa2 100644
--- a/code/modules/mob/living/simple_animal/aliens/hivebot.dm
+++ b/code/modules/mob/living/simple_animal/aliens/hivebot.dm
@@ -1,6 +1,11 @@
+// Hivebots are tuned towards how many default lasers are needed to kill them.
+// As such, if laser damage is ever changed, you should change this define.
+#define LASERS_TO_KILL *40
+
+// Default hivebot is melee, and a bit more meaty, so it can meatshield for their ranged friends.
/mob/living/simple_animal/hostile/hivebot
- name = "Hivebot"
- desc = "A small robot"
+ name = "hivebot"
+ desc = "A robot. It appears to be somewhat reslient, but lacking a true weapon."
icon = 'icons/mob/hivebot.dmi'
icon_state = "basic"
icon_living = "basic"
@@ -8,16 +13,16 @@
faction = "hivebot"
intelligence_level = SA_ROBOTIC
- maxHealth = 15
- health = 15
+ maxHealth = 3 LASERS_TO_KILL
+ health = 3 LASERS_TO_KILL
speed = 4
- melee_damage_lower = 2
- melee_damage_upper = 3
+ melee_damage_lower = 15
+ melee_damage_upper = 15
attacktext = "clawed"
projectilesound = 'sound/weapons/Gunshot.ogg'
- projectiletype = /obj/item/projectile/hivebotbullet
+ projectiletype = /obj/item/projectile/bullet/hivebot
min_oxy = 0
max_oxy = 0
@@ -29,19 +34,102 @@
max_n2 = 0
minbodytemp = 0
+ cooperative = TRUE
+ firing_lines = TRUE
+ investigates = TRUE
+
+ speak_chance = 1
+ speak = list(
+ "Resuming task: Protect area.",
+ "No threats found.",
+ "Error: No targets found."
+ )
+ emote_hear = list("humms ominously", "whirrs softly", "grinds a gear")
+ emote_see = list("looks around the area", "turns from side to side")
+ say_understood = list("Affirmative.", "Positive")
+ say_cannot = list("Denied.", "Negative")
+ say_maybe_target = list("Possible threat detected. Investigating.", "Motion detected.", "Investigating.")
+ say_got_target = list("Threat detected.", "New task: Remove threat.", "Threat removal engaged.", "Engaging target.")
+
+// Subtypes.
+
+// Melee like the base type, but more fragile.
+/mob/living/simple_animal/hostile/hivebot/swarm
+ name = "swarm hivebot"
+ desc = "A robot. It looks fragile and weak"
+ maxHealth = 1 LASERS_TO_KILL
+ health = 1 LASERS_TO_KILL
+ melee_damage_lower = 3
+ melee_damage_upper = 3
+
+// This one has a semi-weak ranged attack.
/mob/living/simple_animal/hostile/hivebot/range
- name = "Hivebot"
- desc = "A smallish robot, this one is armed!"
+ name = "ranged hivebot"
+ desc = "A robot. It has a simple ballistic weapon."
ranged = 1
+ maxHealth = 2 LASERS_TO_KILL
+ health = 2 LASERS_TO_KILL
+// This one shoots a burst of three, and is considerably more dangerous.
/mob/living/simple_animal/hostile/hivebot/range/rapid
+ name = "rapid hivebot"
+ desc = "A robot. It has a fast firing ballistic rifle."
+ icon_living = "strong"
rapid = 1
+ maxHealth = 2 LASERS_TO_KILL
+ health = 2 LASERS_TO_KILL
-/mob/living/simple_animal/hostile/hivebot/strong
- name = "Strong Hivebot"
- desc = "A robot, this one is armed and looks tough!"
- health = 80
- ranged = 1
+// Shoots EMPs, to screw over other robots.
+/mob/living/simple_animal/hostile/hivebot/range/ion
+ name = "engineering hivebot"
+ desc = "A robot. It has a tool which emits focused electromagnetic pulses, which are deadly to other synthetic adverseries."
+ projectiletype = /obj/item/projectile/ion
+ projectilesound = 'sound/weapons/Laser.ogg'
+ icon_living = "engi"
+ ranged = TRUE
+ maxHealth = 2 LASERS_TO_KILL
+ health = 2 LASERS_TO_KILL
+
+// Shoots deadly lasers.
+/mob/living/simple_animal/hostile/hivebot/range/laser
+ name = "laser hivebot"
+ desc = "A robot. It has an energy weapon."
+ projectiletype = /obj/item/projectile/beam/blue
+ projectilesound = 'sound/weapons/Laser.ogg'
+ maxHealth = 2 LASERS_TO_KILL
+ health = 2 LASERS_TO_KILL
+
+// Beefy and ranged.
+/mob/living/simple_animal/hostile/hivebot/range/strong
+ name = "strong hivebot"
+ desc = "A robot. This one has reinforced plating, and looks tougher."
+ icon_living = "strong"
+ maxHealth = 4 LASERS_TO_KILL
+ health = 4 LASERS_TO_KILL
+ melee_damage_lower = 15
+ melee_damage_upper = 15
+
+// Also beefy, but tries to stay at their 'home', ideal for base defense.
+/mob/living/simple_animal/hostile/hivebot/range/guard
+ name = "guard hivebot"
+ desc = "A robot. It seems to be guarding something."
+ returns_home = TRUE
+ maxHealth = 4 LASERS_TO_KILL
+ health = 4 LASERS_TO_KILL
+
+// This one is intended for players to use. Well rounded and can make other hivebots follow them with verbs.
+/mob/living/simple_animal/hostile/hivebot/range/player
+ name = "commander hivebot"
+ desc = "A robot. This one seems to direct the others, and it has a laser weapon."
+ icon_living = "commander"
+ maxHealth = 5 LASERS_TO_KILL
+ health = 5 LASERS_TO_KILL
+ projectiletype = /obj/item/projectile/beam/blue
+ projectilesound = 'sound/weapons/Laser.ogg'
+ melee_damage_lower = 15 // Needed to force open airlocks.
+ melee_damage_upper = 15
+
+// Procs.
/mob/living/simple_animal/hostile/hivebot/death()
..()
@@ -52,6 +140,42 @@
s.start()
qdel(src)
+/mob/living/simple_animal/hostile/hivebot/speech_bubble_appearance()
+ return "synthetic_evil"
+
+/mob/living/simple_animal/hostile/hivebot/verb/command_follow()
+ set name = "Command - Follow"
+ set category = "Hivebot"
+ set desc = "This will ask other hivebots to follow you."
+
+ say("Delegating new task: Follow.")
+
+ for(var/mob/living/simple_animal/hostile/hivebot/buddy in hearers(src))
+ if(buddy.faction != faction)
+ continue
+ if(buddy == src)
+ continue
+ buddy.set_follow(src)
+ buddy.FollowTarget()
+ spawn(rand(5, 10))
+ buddy.say( pick(buddy.say_understood) )
+
+/mob/living/simple_animal/hostile/hivebot/verb/command_stop()
+ set name = "Command - Stop Following"
+ set category = "Hivebot"
+ set desc = "This will ask other hivebots to cease following you."
+
+ say("Delegating new task: Stop following.")
+
+ for(var/mob/living/simple_animal/hostile/hivebot/buddy in hearers(src))
+ if(buddy.faction != faction)
+ continue
+ if(buddy == src)
+ continue
+ buddy.LoseFollow()
+ spawn(rand(5, 10))
+ buddy.say( pick(buddy.say_understood) )
+
/mob/living/simple_animal/hostile/hivebot/tele//this still needs work
name = "Beacon"
desc = "Some odd beacon thing"
@@ -107,6 +231,6 @@
if(prob(2))//Might be a bit low, will mess with it likely
warpbots()
-/obj/item/projectile/hivebotbullet
+/obj/item/projectile/bullet/hivebot
damage = 10
damage_type = BRUTE
diff --git a/code/modules/mob/living/simple_animal/animals/giant_spider.dm b/code/modules/mob/living/simple_animal/animals/giant_spider.dm
index 8d7a2ccb329..a087d4429a0 100644
--- a/code/modules/mob/living/simple_animal/animals/giant_spider.dm
+++ b/code/modules/mob/living/simple_animal/animals/giant_spider.dm
@@ -43,6 +43,17 @@
var/poison_per_bite = 5
var/poison_chance = 10
var/poison_type = "spidertoxin"
+ var/image/eye_layer = null
+
+/mob/living/simple_animal/hostile/giant_spider/proc/add_eyes()
+ if(!eye_layer)
+ var/overlay_layer = LIGHTING_LAYER+0.1
+ eye_layer = image(icon, "[icon_state]-eyes", overlay_layer)
+
+ overlays += eye_layer
+
+/mob/living/simple_animal/hostile/giant_spider/proc/remove_eyes()
+ overlays -= eye_layer
//nursemaids - these create webs and eggs
/mob/living/simple_animal/hostile/giant_spider/nurse
@@ -61,6 +72,7 @@
var/fed = 0
var/atom/cocoon_target
+ var/egg_inject_chance = 5
//hunters have the most poison and move the fastest, so they can find prey
/mob/living/simple_animal/hostile/giant_spider/hunter
@@ -96,33 +108,43 @@
/mob/living/simple_animal/hostile/giant_spider/New(var/location, var/atom/parent)
get_light_and_color(parent)
+ add_eyes()
..()
-/mob/living/simple_animal/hostile/giant_spider/PunchTarget()
- . = ..()
- if(isliving(.))
- var/mob/living/L = .
- if(L.reagents)
- L.reagents.add_reagent(poison_type, poison_per_bite)
- if(prob(poison_chance))
- L << "You feel a tiny prick."
- L.reagents.add_reagent(poison_type, poison_per_bite)
+/mob/living/simple_animal/hostile/giant_spider/death()
+ remove_eyes()
+ ..()
-/mob/living/simple_animal/hostile/giant_spider/nurse/PunchTarget()
+/mob/living/simple_animal/hostile/giant_spider/DoPunch(var/atom/A)
. = ..()
- if(ishuman(.))
- var/mob/living/carbon/human/H = .
- if(prob(5))
- var/obj/item/organ/external/O = pick(H.organs)
- if(!(O.robotic >= ORGAN_ROBOT))
- var/eggcount
- for(var/obj/I in O.implants)
- if(istype(I, /obj/effect/spider/eggcluster))
- eggcount ++
- if(!eggcount)
- var/eggs = new /obj/effect/spider/eggcluster/small(O, src)
- O.implants += eggs
- H << "The [src] injects something into your [O.name]!"
+ if(.) // If we succeeded in hitting.
+ if(isliving(A))
+ var/mob/living/L = A
+ if(L.reagents)
+ var/target_zone = pick(BP_TORSO,BP_TORSO,BP_TORSO,BP_L_LEG,BP_R_LEG,BP_L_ARM,BP_R_ARM,BP_HEAD)
+ if(L.can_inject(src, null, target_zone))
+ L.reagents.add_reagent(poison_type, poison_per_bite)
+ if(prob(poison_chance))
+ to_chat(L, "You feel a tiny prick.")
+ L.reagents.add_reagent(poison_type, poison_per_bite)
+
+/mob/living/simple_animal/hostile/giant_spider/nurse/DoPunch(var/atom/A)
+ . = ..()
+ if(.) // If we succeeded in hitting.
+ if(ishuman(A))
+ var/mob/living/carbon/human/H = A
+ if(prob(egg_inject_chance))
+ var/target_zone = pick(BP_TORSO,BP_TORSO,BP_TORSO,BP_L_LEG,BP_R_LEG,BP_L_ARM,BP_R_ARM,BP_HEAD)
+ if(H.can_inject(src, null, target_zone))
+ var/obj/item/organ/external/O = H.get_organ(target_zone)
+ var/eggcount
+ for(var/obj/I in O.implants)
+ if(istype(I, /obj/effect/spider/eggcluster))
+ eggcount ++
+ if(!eggcount)
+ var/eggs = new /obj/effect/spider/eggcluster/small(O, src)
+ O.implants += eggs
+ to_chat(H, "\The [src] injects something into your [O.name]!")
/mob/living/simple_animal/hostile/giant_spider/handle_stance()
. = ..()
diff --git a/code/modules/mob/living/simple_animal/animals/spiderbot.dm b/code/modules/mob/living/simple_animal/animals/spiderbot.dm
index 57f0351d9a0..ff3f03bf57c 100644
--- a/code/modules/mob/living/simple_animal/animals/spiderbot.dm
+++ b/code/modules/mob/living/simple_animal/animals/spiderbot.dm
@@ -40,6 +40,15 @@
var/list/req_access = list(access_robotics) //Access needed to pop out the brain.
var/positronic
+ can_enter_vent_with = list(
+ /obj/item/weapon/implant,
+ /obj/item/device/radio/borg,
+ /obj/item/weapon/holder,
+ /obj/machinery/camera,
+ /mob/living/simple_animal/borer,
+ /obj/item/device/mmi,
+ )
+
var/emagged = 0
var/obj/item/held_item = null //Storage for single item they can hold.
diff --git a/code/modules/mob/living/simple_animal/simple_animal.dm b/code/modules/mob/living/simple_animal/simple_animal.dm
index 1cfbc84bb40..0697f81714f 100644
--- a/code/modules/mob/living/simple_animal/simple_animal.dm
+++ b/code/modules/mob/living/simple_animal/simple_animal.dm
@@ -1230,14 +1230,22 @@
// This is the actual act of 'punching'. Override for special behaviour.
/mob/living/simple_animal/proc/DoPunch(var/atom/A)
if(!Adjacent(target_mob)) // They could've moved in the meantime.
- return
+ return FALSE
+
var/damage_to_do = rand(melee_damage_lower, melee_damage_upper)
for(var/datum/modifier/M in modifiers)
if(!isnull(M.outgoing_melee_damage_percent))
damage_to_do *= M.outgoing_melee_damage_percent
+ // SA attacks can be blocked with shields.
+ if(ishuman(A))
+ var/mob/living/carbon/human/H = A
+ if(H.check_shields(damage = damage_to_do, damage_source = src, attacker = src, def_zone = null, attack_text = "the attack"))
+ return FALSE
+
A.attack_generic(src, damage_to_do, attacktext)
+ return TRUE
//The actual top-level ranged attack proc
/mob/living/simple_animal/proc/ShootTarget()
diff --git a/code/modules/mob/living/simple_animal/slime/slime.dm b/code/modules/mob/living/simple_animal/slime/slime.dm
index c1e912b74cc..7a213ac97fc 100644
--- a/code/modules/mob/living/simple_animal/slime/slime.dm
+++ b/code/modules/mob/living/simple_animal/slime/slime.dm
@@ -88,6 +88,10 @@
var/reagent_injected = null // Some slimes inject reagents on attack. This tells the game what reagent to use.
var/injection_amount = 5 // This determines how much.
+ can_enter_vent_with = list(
+ /obj/item/clothing/head,
+ )
+
/mob/living/simple_animal/slime/New(var/location, var/start_as_adult = FALSE)
verbs += /mob/living/proc/ventcrawl
if(start_as_adult)
diff --git a/code/modules/mob/mob_movement.dm b/code/modules/mob/mob_movement.dm
index 464baaa142d..d1a336dbb6e 100644
--- a/code/modules/mob/mob_movement.dm
+++ b/code/modules/mob/mob_movement.dm
@@ -501,6 +501,10 @@
if(!dense_object && (locate(/obj/structure/lattice) in oview(1, src)))
dense_object++
+ if(!dense_object && (locate(/obj/structure/catwalk) in oview(1, src)))
+ dense_object++
+
+
//Lastly attempt to locate any dense objects we could push off of
//TODO: If we implement objects drifing in space this needs to really push them
//Due to a few issues only anchored and dense objects will now work.
diff --git a/code/modules/mob/transform_procs.dm b/code/modules/mob/transform_procs.dm
index bd126614378..9d30ef72447 100644
--- a/code/modules/mob/transform_procs.dm
+++ b/code/modules/mob/transform_procs.dm
@@ -77,10 +77,26 @@
else
O.key = key
+ //Languages
+ add_language("Robot Talk", 1)
+ add_language(LANGUAGE_GALCOM, 1)
+ add_language(LANGUAGE_SOL_COMMON, 1)
+ add_language(LANGUAGE_UNATHI, 1)
+ add_language(LANGUAGE_SIIK, 1)
+ add_language(LANGUAGE_SKRELLIAN, 1)
+ add_language(LANGUAGE_TRADEBAND, 1)
+ add_language(LANGUAGE_GUTTER, 1)
+ add_language(LANGUAGE_EAL, 1)
+ add_language(LANGUAGE_SCHECHI, 1)
+ add_language(LANGUAGE_SIGN, 1)
+
+ // Lorefolks say it may be so.
if(O.client && O.client.prefs)
var/datum/preferences/B = O.client.prefs
- for(var/language in B.alternate_languages)
- O.add_language(language)
+ if(LANGUAGE_ROOTGLOBAL in B.alternate_languages)
+ O.add_language(LANGUAGE_ROOTGLOBAL, 1)
+ if(LANGUAGE_ROOTLOCAL in B.alternate_languages)
+ O.add_language(LANGUAGE_ROOTLOCAL, 1)
if(move)
var/obj/loc_landmark
diff --git a/code/modules/organs/internal/brain.dm b/code/modules/organs/internal/brain.dm
index 77ead516c3c..0a99fb37f31 100644
--- a/code/modules/organs/internal/brain.dm
+++ b/code/modules/organs/internal/brain.dm
@@ -127,6 +127,7 @@
desc = "A complex, organic knot of jelly and crystalline particles."
icon = 'icons/mob/slimes.dmi'
icon_state = "green slime extract"
+ parent_organ = BP_TORSO
/obj/item/organ/internal/brain/golem
name = "chem"
diff --git a/code/modules/organs/internal/liver.dm b/code/modules/organs/internal/liver.dm
index 6b7459500b6..3b20f30214d 100644
--- a/code/modules/organs/internal/liver.dm
+++ b/code/modules/organs/internal/liver.dm
@@ -39,10 +39,11 @@
// Do some reagent processing.
if(owner.chem_effects[CE_ALCOHOL_TOXIC])
+ take_damage(owner.chem_effects[CE_ALCOHOL_TOXIC] * 0.1 * PROCESS_ACCURACY, prob(1)) // Chance to warn them
+ if(filter_effect < 2) //Liver is badly damaged, you're drinking yourself to death
+ owner.adjustToxLoss(owner.chem_effects[CE_ALCOHOL_TOXIC] * 0.2 * PROCESS_ACCURACY)
if(filter_effect < 3)
owner.adjustToxLoss(owner.chem_effects[CE_ALCOHOL_TOXIC] * 0.1 * PROCESS_ACCURACY)
- else
- take_damage(owner.chem_effects[CE_ALCOHOL_TOXIC] * 0.1 * PROCESS_ACCURACY, prob(1)) // Chance to warn them
/obj/item/organ/internal/liver/handle_germ_effects()
. = ..() //Up should return an infection level as an integer
diff --git a/code/modules/organs/subtypes/slime.dm b/code/modules/organs/subtypes/slime.dm
new file mode 100644
index 00000000000..1c9c11d75bc
--- /dev/null
+++ b/code/modules/organs/subtypes/slime.dm
@@ -0,0 +1,47 @@
+/obj/item/organ/external/chest/unbreakable/slime
+ nonsolid = 1
+ max_damage = 50
+ encased = 0
+
+/obj/item/organ/external/groin/unbreakable/slime
+ nonsolid = 1
+ max_damage = 30
+
+/obj/item/organ/external/arm/unbreakable/slime
+ nonsolid = 1
+ max_damage = 5
+
+/obj/item/organ/external/arm/right/unbreakable/slime
+ nonsolid = 1
+ max_damage = 5
+
+/obj/item/organ/external/leg/unbreakable/slime
+ nonsolid = 1
+ max_damage = 5
+
+/obj/item/organ/external/leg/right/unbreakable/slime
+ nonsolid = 1
+ max_damage = 5
+
+/obj/item/organ/external/foot/unbreakable/slime
+ nonsolid = 1
+ max_damage = 5
+
+/obj/item/organ/external/foot/right/unbreakable/slime
+ nonsolid = 1
+ max_damage = 5
+
+/obj/item/organ/external/hand/unbreakable/slime
+ nonsolid = 1
+ max_damage = 5
+
+/obj/item/organ/external/hand/right/unbreakable/slime
+ nonsolid = 1
+ max_damage = 5
+
+/obj/item/organ/external/head/unbreakable/slime //They don't need this anymore.
+ nonsolid = 1
+ cannot_gib = 0
+ vital = 0
+ max_damage = 5
+ encased = 0
\ No newline at end of file
diff --git a/code/modules/organs/subtypes/unbreakable.dm b/code/modules/organs/subtypes/unbreakable.dm
index fcd819029eb..61126769cd8 100644
--- a/code/modules/organs/subtypes/unbreakable.dm
+++ b/code/modules/organs/subtypes/unbreakable.dm
@@ -40,49 +40,4 @@
/obj/item/organ/external/head/unbreakable
cannot_break = 1
- dislocated = -1
-
-// Slime limbs.
-/obj/item/organ/external/chest/unbreakable/slime
- nonsolid = 1
- max_damage = 50
-
-/obj/item/organ/external/groin/unbreakable/slime
- nonsolid = 1
- max_damage = 30
-
-/obj/item/organ/external/arm/unbreakable/slime
- nonsolid = 1
- max_damage = 5
-
-/obj/item/organ/external/arm/right/unbreakable/slime
- nonsolid = 1
- max_damage = 5
-
-/obj/item/organ/external/leg/unbreakable/slime
- nonsolid = 1
- max_damage = 5
-
-/obj/item/organ/external/leg/right/unbreakable/slime
- nonsolid = 1
- max_damage = 5
-
-/obj/item/organ/external/foot/unbreakable/slime
- nonsolid = 1
- max_damage = 5
-
-/obj/item/organ/external/foot/right/unbreakable/slime
- nonsolid = 1
- max_damage = 5
-
-/obj/item/organ/external/hand/unbreakable/slime
- nonsolid = 1
- max_damage = 5
-
-/obj/item/organ/external/hand/right/unbreakable/slime
- nonsolid = 1
- max_damage = 5
-
-/obj/item/organ/external/head/unbreakable/slime
- nonsolid = 1
- max_damage = 5
+ dislocated = -1
\ No newline at end of file
diff --git a/code/modules/power/cell.dm b/code/modules/power/cell.dm
index d3cde870492..2c1699c5f60 100644
--- a/code/modules/power/cell.dm
+++ b/code/modules/power/cell.dm
@@ -16,7 +16,7 @@
/obj/item/weapon/cell/process()
if(self_recharge)
- give(charge_amount / CELLRATE)
+ give(charge_amount)
else
return PROCESS_KILL
@@ -59,6 +59,7 @@
return 0
var/used = min(charge, amount)
charge -= used
+ update_icon()
return used
// Checks if the specified amount can be provided. If it can, it removes the amount
@@ -78,24 +79,29 @@
if(maxcharge < amount) return 0
var/amount_used = min(maxcharge-charge,amount)
charge += amount_used
+ update_icon()
return amount_used
/obj/item/weapon/cell/examine(mob/user)
- if(get_dist(src, user) > 1)
- return
+ var/msg = desc
- if(maxcharge <= 2500)
- user << "[desc]\nThe manufacturer's label states this cell has a power rating of [maxcharge], and that you should not swallow it.\nThe charge meter reads [round(src.percent() )]%."
- else
- user << "This power cell has an exciting chrome finish, as it is an uber-capacity cell type! It has a power rating of [maxcharge]!\nThe charge meter reads [round(src.percent() )]%."
+ if(get_dist(src, user) <= 1)
+ msg += " It has a power rating of [maxcharge].\nThe charge meter reads [round(src.percent() )]%."
+ to_chat(user, msg)
+/*
+ if(maxcharge <= 2500)
+ to_chat(user, "[desc]\nThe manufacturer's label states this cell has a power rating of [maxcharge], and that you should not swallow it.\nThe charge meter reads [round(src.percent() )]%.")
+ else
+ to_chat(user, "This power cell has an exciting chrome finish, as it is an uber-capacity cell type! It has a power rating of [maxcharge]!\nThe charge meter reads [round(src.percent() )]%.")
+*/
/obj/item/weapon/cell/attackby(obj/item/W, mob/user)
..()
if(istype(W, /obj/item/weapon/reagent_containers/syringe))
var/obj/item/weapon/reagent_containers/syringe/S = W
- user << "You inject the solution into the power cell."
+ to_chat(user, "You inject the solution into the power cell.")
if(S.reagents.has_reagent("phoron", 5))
@@ -149,6 +155,8 @@
charge -= charge / severity
if (charge < 0)
charge = 0
+
+ update_icon()
..()
/obj/item/weapon/cell/ex_act(severity)
diff --git a/code/modules/projectiles/ammunition/magazines.dm b/code/modules/projectiles/ammunition/magazines.dm
index 82a6aa74e47..342e10db840 100644
--- a/code/modules/projectiles/ammunition/magazines.dm
+++ b/code/modules/projectiles/ammunition/magazines.dm
@@ -443,6 +443,23 @@
/obj/item/ammo_magazine/m762m/empty
initial_ammo = 0
+/obj/item/ammo_magazine/m762garand
+ name = "garand clip (7.62mm)" // The clip goes into the magazine, hence the name. I'm very sure this is correct.
+ icon_state = "gclip"
+ mag_type = MAGAZINE
+ caliber = "7.62mm"
+ matter = list(DEFAULT_WALL_MATERIAL = 1600)
+ ammo_type = /obj/item/ammo_casing/a762
+ max_ammo = 8
+ multiple_sprites = 1
+
+/obj/item/ammo_magazine/m762garand/ap
+ name = "garand clip (7.62mm armor-piercing)"
+ ammo_type = /obj/item/ammo_casing/a762/ap
+
+/obj/item/ammo_magazine/m762/empty
+ initial_ammo = 0
+
/obj/item/ammo_magazine/clip/c762
name = "ammo clip (7.62mm)"
icon_state = "clip_rifle"
diff --git a/code/modules/projectiles/guns/projectile/semiauto.dm b/code/modules/projectiles/guns/projectile/semiauto.dm
new file mode 100644
index 00000000000..d4cd6161881
--- /dev/null
+++ b/code/modules/projectiles/guns/projectile/semiauto.dm
@@ -0,0 +1,21 @@
+/obj/item/weapon/gun/projectile/garand
+ name = "\improper M1 Garand"
+ desc = "This is the vintage semi-automatic rifle that famously helped win the second World War. What the hell it's doing aboard a space station in the 26th century, you can only imagine. Uses 7.62mm rounds."
+ icon_state = "garand"
+ item_state = "boltaction"
+ w_class = ITEMSIZE_LARGE
+ caliber = "7.62mm"
+ origin_tech = list(TECH_COMBAT = 2, TECH_MATERIAL = 2)
+ slot_flags = SLOT_BACK
+ fire_sound = 'sound/weapons/rifleshot.ogg'
+ load_method = MAGAZINE // ToDo: Make it so MAGAZINE, SPEEDLOADER and SINGLE_CASING can all be used on the same gun.
+ magazine_type = /obj/item/ammo_magazine/m762garand
+ allowed_magazines = list(/obj/item/ammo_magazine/m762garand)
+ auto_eject = 1
+ auto_eject_sound = 'sound/weapons/garand_ping.ogg'
+
+/obj/item/weapon/gun/projectile/garand/update_icon()
+ if(ammo_magazine)
+ icon_state = initial(icon_state)
+ else
+ icon_state = "[initial(icon_state)]-e"
diff --git a/code/modules/projectiles/projectile.dm b/code/modules/projectiles/projectile.dm
index 3144f9eb095..c4344c052b8 100644
--- a/code/modules/projectiles/projectile.dm
+++ b/code/modules/projectiles/projectile.dm
@@ -202,8 +202,9 @@
admin_attack_log(firer, target_mob, attacker_message, victim_message, admin_message)
else
- target_mob.attack_log += "\[[time_stamp()]\] UNKNOWN SUBJECT (No longer exists) shot [target_mob]/[target_mob.ckey] with \a [src]"
- msg_admin_attack("UNKNOWN shot [target_mob] ([target_mob.ckey]) with \a [src] (JMP)")
+ if(target_mob) // Sometimes the target_mob gets gibbed or something.
+ target_mob.attack_log += "\[[time_stamp()]\] UNKNOWN SUBJECT (No longer exists) shot [target_mob]/[target_mob.ckey] with \a [src]"
+ msg_admin_attack("UNKNOWN shot [target_mob] ([target_mob.ckey]) with \a [src] (JMP)")
//sometimes bullet_act() will want the projectile to continue flying
if (result == PROJECTILE_CONTINUE)
diff --git a/code/modules/reagents/reagent_containers/drinkingglass/drinkingglass.dm b/code/modules/reagents/reagent_containers/drinkingglass/drinkingglass.dm
index 874d4cc6765..1aae5b4a948 100644
--- a/code/modules/reagents/reagent_containers/drinkingglass/drinkingglass.dm
+++ b/code/modules/reagents/reagent_containers/drinkingglass/drinkingglass.dm
@@ -161,7 +161,7 @@
return
/obj/item/weapon/reagent_containers/food/drinks/glass2/standard_feed_mob(var/mob/user, var/mob/target)
- if(afterattack()) //Check to see if harm intent & splash.
+ if(afterattack(target, user)) //Check to see if harm intent & splash.
return
else
..() //If they're splashed, no need to do anything else.
\ No newline at end of file
diff --git a/code/modules/reagents/reagent_containers/syringes.dm b/code/modules/reagents/reagent_containers/syringes.dm
index 536a069474b..35deb6935fa 100644
--- a/code/modules/reagents/reagent_containers/syringes.dm
+++ b/code/modules/reagents/reagent_containers/syringes.dm
@@ -58,7 +58,7 @@
return
if(mode == SYRINGE_BROKEN)
- user << "This syringe is broken!"
+ to_chat(user, "This syringe is broken!")
return
if(user.a_intent == I_HURT && ismob(target))
@@ -70,26 +70,31 @@
switch(mode)
if(SYRINGE_DRAW)
if(!reagents.get_free_space())
- user << "The syringe is full."
+ to_chat(user, "The syringe is full.")
mode = SYRINGE_INJECT
return
if(ismob(target))//Blood!
if(reagents.has_reagent("blood"))
- user << "There is already a blood sample in this syringe."
+ to_chat(user, "There is already a blood sample in this syringe.")
return
+
if(istype(target, /mob/living/carbon))
var/amount = reagents.get_free_space()
var/mob/living/carbon/T = target
if(!T.dna)
- user << "You are unable to locate any blood. (To be specific, your target seems to be missing their DNA datum)."
+ to_chat(user, "You are unable to locate any blood. (To be specific, your target seems to be missing their DNA datum).")
return
if(NOCLONE in T.mutations) //target done been et, no more blood in him
- user << "You are unable to locate any blood."
+ to_chat(user, "You are unable to locate any blood.")
+ return
+
+ if(T.isSynthetic())
+ to_chat(user, "You can't draw blood from a synthetic!")
return
if(drawing)
- user << "You are already drawing blood from [T.name]."
+ to_chat(user, "You are already drawing blood from [T.name].")
return
var/datum/reagent/B
@@ -117,50 +122,51 @@
reagents.update_total()
on_reagent_change()
reagents.handle_reactions()
- user << "You take a blood sample from [target]."
+ to_chat(user, "You take a blood sample from [target].")
for(var/mob/O in viewers(4, user))
O.show_message("[user] takes a blood sample from [target].", 1)
else //if not mob
if(!target.reagents.total_volume)
- user << "[target] is empty."
+ to_chat(user, "[target] is empty.")
return
if(!target.is_open_container() && !istype(target, /obj/structure/reagent_dispensers) && !istype(target, /obj/item/slime_extract) && !istype(target, /obj/item/weapon/reagent_containers/food))
- user << "You cannot directly remove reagents from this object."
+ to_chat(user, "You cannot directly remove reagents from this object.")
return
var/trans = target.reagents.trans_to_obj(src, amount_per_transfer_from_this)
- user << "You fill the syringe with [trans] units of the solution."
+ to_chat(user, "You fill the syringe with [trans] units of the solution.")
update_icon()
+
if(!reagents.get_free_space())
mode = SYRINGE_INJECT
update_icon()
if(SYRINGE_INJECT)
if(!reagents.total_volume)
- user << "The syringe is empty."
+ to_chat(user, "The syringe is empty.")
mode = SYRINGE_DRAW
return
if(istype(target, /obj/item/weapon/implantcase/chem))
return
if(!target.is_open_container() && !ismob(target) && !istype(target, /obj/item/weapon/reagent_containers/food) && !istype(target, /obj/item/slime_extract) && !istype(target, /obj/item/clothing/mask/smokable/cigarette) && !istype(target, /obj/item/weapon/storage/fancy/cigarettes))
- user << "You cannot directly fill this object."
+ to_chat(user, "You cannot directly fill this object.")
return
if(!target.reagents.get_free_space())
- user << "[target] is full."
+ to_chat(user, "[target] is full.")
return
var/mob/living/carbon/human/H = target
if(istype(H))
var/obj/item/organ/external/affected = H.get_organ(user.zone_sel.selecting)
if(!affected)
- user << "\The [H] is missing that limb!"
+ to_chat(user, "\The [H] is missing that limb!")
return
else if(affected.robotic >= ORGAN_ROBOT)
- user << "You cannot inject a robotic limb."
+ to_chat(user, "You cannot inject a robotic limb.")
return
if(ismob(target) && target != user)
@@ -200,9 +206,9 @@
else
trans = reagents.trans_to_obj(target, amount_per_transfer_from_this)
if(trans)
- user << "You inject [trans] units of the solution. The syringe now contains [src.reagents.total_volume] units."
+ to_chat(user, "You inject [trans] units of the solution. The syringe now contains [src.reagents.total_volume] units.")
else
- user << "The syringe is empty."
+ to_chat(user, "The syringe is empty.")
if (reagents.total_volume <= 0 && mode == SYRINGE_INJECT)
mode = SYRINGE_DRAW
update_icon()
@@ -245,7 +251,7 @@
var/obj/item/organ/external/affecting = H.get_organ(target_zone)
if (!affecting || affecting.is_stump())
- user << "They are missing that limb!"
+ to_chat(user, "They are missing that limb!")
return
var/hit_area = affecting.name
@@ -302,10 +308,10 @@
/obj/item/weapon/reagent_containers/syringe/ld50_syringe/afterattack(obj/target, mob/user, flag)
if(mode == SYRINGE_DRAW && ismob(target)) // No drawing 50 units of blood at once
- user << "This needle isn't designed for drawing blood."
+ to_chat(user, "This needle isn't designed for drawing blood.")
return
if(user.a_intent == "hurt" && ismob(target)) // No instant injecting
- user << "This syringe is too big to stab someone with it."
+ to_chat(user, "This syringe is too big to stab someone with it.")
..()
////////////////////////////////////////////////////////////////////////////////
diff --git a/code/modules/research/designs.dm b/code/modules/research/designs.dm
index b99b9a7dde6..a6e6a948501 100644
--- a/code/modules/research/designs.dm
+++ b/code/modules/research/designs.dm
@@ -473,6 +473,15 @@ other types of metals and chemistry for reagents).
build_path = /obj/item/weapon/surgical/scalpel/manager
sort_string = "MBBAD"
+/datum/design/item/bone_clamp
+ name = "Bone Clamp"
+ desc = "A miracle of modern science, this tool rapidly knits together bone, without the need for bone gel."
+ id = "bone_clamp"
+ req_tech = list(TECH_BIO = 4, TECH_MATERIAL = 5, TECH_MAGNET = 4, TECH_DATA = 4)
+ materials = list (DEFAULT_WALL_MATERIAL = 12500, "glass" = 7500, "silver" = 2500)
+ build_path = /obj/item/weapon/surgical/bone_clamp
+ sort_string = "MBBAE"
+
/datum/design/item/implant
materials = list(DEFAULT_WALL_MATERIAL = 50, "glass" = 50)
diff --git a/code/modules/surgery/bones.dm b/code/modules/surgery/bones.dm
index 6a5a39df734..e1086dbdca9 100644
--- a/code/modules/surgery/bones.dm
+++ b/code/modules/surgery/bones.dm
@@ -145,4 +145,42 @@
fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
var/obj/item/organ/external/affected = target.get_organ(target_zone)
user.visible_message("[user]'s hand slips, smearing [tool] in the incision in [target]'s [affected.name]!" , \
- "Your hand slips, smearing [tool] in the incision in [target]'s [affected.name]!")
\ No newline at end of file
+ "Your hand slips, smearing [tool] in the incision in [target]'s [affected.name]!")
+
+
+
+/datum/surgery_step/clamp_bone
+ allowed_tools = list(
+ /obj/item/weapon/surgical/bone_clamp = 100
+ )
+ can_infect = 1
+ blood_level = 1
+
+ min_duration = 70
+ max_duration = 90
+
+ can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
+ if (!hasorgans(target))
+ return 0
+ var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ return affected && (affected.robotic < ORGAN_ROBOT) && affected.open >= 2 && affected.stage == 0
+
+ begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
+ var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ if (affected.stage == 0)
+ user.visible_message("[user] starts repairing the damaged bones in [target]'s [affected.name] with \the [tool]." , \
+ "You starts repairing the damaged bones in [target]'s [affected.name] with \the [tool].")
+ target.custom_pain("Something in your [affected.name] is causing you a lot of pain!", 50)
+ ..()
+
+ end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
+ var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ user.visible_message("[user] sets the bone in [target]'s [affected.name] with \the [tool].", \
+ "You sets [target]'s bone in [affected.name] with \the [tool].")
+ affected.status &= ~ORGAN_BROKEN
+
+ fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
+ var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ user.visible_message("[user]'s hand slips, damaging the bone in [target]'s [affected.name] with \the [tool]!" , \
+ "Your hand slips, damaging the bone in [target]'s [affected.name] with \the [tool]!")
+ affected.createwound(BRUISE, 5)
\ No newline at end of file
diff --git a/code/modules/surgery/robotics.dm b/code/modules/surgery/robotics.dm
index 09db2e31465..660cc6e05b4 100644
--- a/code/modules/surgery/robotics.dm
+++ b/code/modules/surgery/robotics.dm
@@ -168,10 +168,16 @@
var/obj/item/organ/external/affected = target.get_organ(target_zone)
if(istype(tool,/obj/item/stack/cable_coil/))
var/obj/item/stack/cable_coil/C = tool
- if(!C.can_use(5))
- user << "You need ten or more cable pieces to repair this damage." //usage amount made more consistent with regular cable repair
+ if(affected.burn_dam == 0)
+ to_chat(user, "There are no burnt wires here!")
return SURGERY_FAILURE
- C.use(5)
+ else
+ if(!C.can_use(5))
+ to_chat(user, "You need at least five cable pieces to repair this part.") //usage amount made more consistent with regular cable repair
+ return SURGERY_FAILURE
+ else
+ C.use(5)
+
return affected && affected.open == 3 && (affected.disfigured || affected.burn_dam > 0) && target_zone != O_MOUTH
begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
diff --git a/code/modules/xenoarcheaology/artifacts/artifact.dm b/code/modules/xenoarcheaology/artifacts/artifact.dm
index e0ba3b1a3f7..2bb64345539 100644
--- a/code/modules/xenoarcheaology/artifacts/artifact.dm
+++ b/code/modules/xenoarcheaology/artifacts/artifact.dm
@@ -259,8 +259,7 @@
..()
/obj/machinery/artifact/bullet_act(var/obj/item/projectile/P)
- if(istype(P,/obj/item/projectile/bullet) ||\
- istype(P,/obj/item/projectile/hivebotbullet))
+ if(istype(P,/obj/item/projectile/bullet))
if(my_effect.trigger == TRIGGER_FORCE)
my_effect.ToggleActivate()
if(secondary_effect && secondary_effect.trigger == TRIGGER_FORCE && prob(25))
diff --git a/html/changelogs/Woodrat-SyndIDs.yml b/html/changelogs/Woodrat-SyndIDs.yml
new file mode 100644
index 00000000000..fba90ab1fd7
--- /dev/null
+++ b/html/changelogs/Woodrat-SyndIDs.yml
@@ -0,0 +1,37 @@
+################################
+# Example Changelog File
+#
+# Note: This file, and files beginning with ".", and files that don't end in ".yml" will not be read. If you change this file, you will look really dumb.
+#
+# Your changelog will be merged with a master changelog. (New stuff added only, and only on the date entry for the day it was merged.)
+# When it is, any changes listed below will disappear.
+#
+# Valid Prefixes:
+# bugfix
+# wip (For works in progress)
+# tweak
+# soundadd
+# sounddel
+# rscadd (general adding of nice things)
+# rscdel (general deleting of nice things)
+# imageadd
+# imagedel
+# maptweak
+# spellcheck (typo fixes)
+# experiment
+#################################
+
+# Your name.
+author: Woodrat
+
+# Optional: Remove this file after generating master changelog. Useful for PR changelogs that won't get used again.
+delete-after: True
+
+# Any changes you've made. See valid prefix list above.
+# INDENT WITH TWO SPACES. NOT TABS. SPACES.
+# SCREW THIS UP AND IT WON'T WORK.
+# Also, all entries are changed into a single [] after a master changelog generation. Just remove the brackets when you add new entries.
+# Please surround your changes in double quotes ("), as certain characters otherwise screws up compiling. The quotes will not show up in the changelog.
+changes:
+ - rscadd: "Added a Syndicate ID with all access (admin spawn only)."
+ - tweak: "Port of 'Syndicate id cards now listen for owner destruction' from Bay."
diff --git a/icons/mob/animal.dmi b/icons/mob/animal.dmi
index ba259d21542..60153c2d921 100644
Binary files a/icons/mob/animal.dmi and b/icons/mob/animal.dmi differ
diff --git a/icons/mob/belt.dmi b/icons/mob/belt.dmi
index 7ff90a67412..00e10be77a0 100644
Binary files a/icons/mob/belt.dmi and b/icons/mob/belt.dmi differ
diff --git a/icons/mob/belt_mirror.dmi b/icons/mob/belt_mirror.dmi
index eefa872e826..859701435f7 100644
Binary files a/icons/mob/belt_mirror.dmi and b/icons/mob/belt_mirror.dmi differ
diff --git a/icons/mob/hivebot.dmi b/icons/mob/hivebot.dmi
index cb13996361c..ecaa519822f 100644
Binary files a/icons/mob/hivebot.dmi and b/icons/mob/hivebot.dmi differ
diff --git a/icons/mob/mob.dmi b/icons/mob/mob.dmi
index 94028db1fa0..ec0e70ccdc5 100644
Binary files a/icons/mob/mob.dmi and b/icons/mob/mob.dmi differ
diff --git a/icons/mob/suit.dmi b/icons/mob/suit.dmi
index 7249f9b218e..a0e5df9f9d3 100644
Binary files a/icons/mob/suit.dmi and b/icons/mob/suit.dmi differ
diff --git a/icons/obj/ammo.dmi b/icons/obj/ammo.dmi
index 6613998f404..27744ed62ed 100644
Binary files a/icons/obj/ammo.dmi and b/icons/obj/ammo.dmi differ
diff --git a/icons/obj/clothing/suits.dmi b/icons/obj/clothing/suits.dmi
index 2925d066c21..e795486d596 100644
Binary files a/icons/obj/clothing/suits.dmi and b/icons/obj/clothing/suits.dmi differ
diff --git a/icons/obj/gun.dmi b/icons/obj/gun.dmi
index a42094e2966..1550d6bf4b7 100644
Binary files a/icons/obj/gun.dmi and b/icons/obj/gun.dmi differ
diff --git a/icons/obj/items.dmi b/icons/obj/items.dmi
index 563285ff056..e35880d3d4c 100644
Binary files a/icons/obj/items.dmi and b/icons/obj/items.dmi differ
diff --git a/icons/obj/structures.dmi b/icons/obj/structures.dmi
index 341f5a33c0f..3b4604cdfd5 100644
Binary files a/icons/obj/structures.dmi and b/icons/obj/structures.dmi differ
diff --git a/icons/obj/surgery.dmi b/icons/obj/surgery.dmi
index 15ef72276fe..c08940b530c 100644
Binary files a/icons/obj/surgery.dmi and b/icons/obj/surgery.dmi differ
diff --git a/icons/obj/weapons.dmi b/icons/obj/weapons.dmi
index 5f38ccd3a3c..01d769a0f46 100644
Binary files a/icons/obj/weapons.dmi and b/icons/obj/weapons.dmi differ
diff --git a/icons/turf/areas.dmi b/icons/turf/areas.dmi
index d1bfcbfb013..8ad45585abe 100755
Binary files a/icons/turf/areas.dmi and b/icons/turf/areas.dmi differ
diff --git a/maps/_map_system_readme.dm b/maps/_map_system_readme.dm
new file mode 100644
index 00000000000..95e996907ba
--- /dev/null
+++ b/maps/_map_system_readme.dm
@@ -0,0 +1,18 @@
+/*
+This system is in place to make it easier to seperate data specific to a certain map.
+
+Each map should have their own folder, and contain both the actual map files, and the code files defining their unique
+things, such as areas, elevators, or shuttles. Generally, the layout is that your map folder has,
+
+[map_name] folder
+ [map_name].dm - Containing a lot of #define directives, and is used to automatically load the other files you need.
+ [map_name_defines].dm - This contains the code for the map datum. For more details, read the comments inside ~map_system folder.
+ (optional) [map_name]_areas/structures/whatever.dm - Files for unique things to that map.
+ [map_name]-1.dmm - Your actual map files. Z-levels should be ordered correctly if you seperate your z-levels across map files.
+
+-HOW TO LOAD A SPECIFIC MAP-
+Say you want to load southern_cross,
+First, uncheck your current loaded map, presumably northern_star. Uncheck northern_star.dm inside northern_star folder.
+Then go open southern_cross folder, and check southern_cross.dm, don't check any other folders below, and compile.
+When you finish compiling, you should be able to open the map files for southern_cross.
+*/
\ No newline at end of file
diff --git a/maps/northern_star/polaris-1.dmm b/maps/northern_star/polaris-1.dmm
index b60a19ee631..5ad83512114 100644
--- a/maps/northern_star/polaris-1.dmm
+++ b/maps/northern_star/polaris-1.dmm
@@ -4682,7 +4682,7 @@
"bMb" = (/obj/structure/cable/green{d1 = 4; d2 = 8; icon_state = "4-8"},/obj/machinery/atmospherics/pipe/manifold/hidden/scrubbers,/obj/machinery/atmospherics/pipe/manifold/hidden/supply{dir = 1},/obj/effect/floor_decal/industrial/warning{dir = 1},/turf/simulated/floor/tiled,/area/assembly/robotics)
"bMc" = (/obj/structure/cable/green{d1 = 4; d2 = 8; icon_state = "4-8"},/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 4},/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 4},/obj/effect/floor_decal/industrial/warning{dir = 1},/obj/machinery/mecha_part_fabricator,/turf/simulated/floor/tiled,/area/assembly/robotics)
"bMd" = (/obj/structure/cable/green{d1 = 4; d2 = 8; icon_state = "4-8"},/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 4},/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 4},/obj/effect/floor_decal/industrial/warning{dir = 1},/obj/machinery/pros_fabricator,/turf/simulated/floor/tiled,/area/assembly/robotics)
-"bMe" = (/obj/structure/cable/green{d1 = 4; d2 = 8; icon_state = "4-8"},/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 4},/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 4},/obj/effect/floor_decal/industrial/warning{dir = 1},/obj/structure/table/standard,/obj/item/device/robotanalyzer,/obj/item/device/robotanalyzer,/obj/item/device/mmi/digital/posibrain,/turf/simulated/floor/tiled,/area/assembly/robotics)
+"bMe" = (/obj/structure/cable/green{d1 = 4; d2 = 8; icon_state = "4-8"},/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 4},/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 4},/obj/effect/floor_decal/industrial/warning{dir = 1},/obj/structure/table/standard,/obj/item/device/robotanalyzer,/obj/item/device/robotanalyzer,/obj/item/device/mmi/digital/robot,/turf/simulated/floor/tiled,/area/assembly/robotics)
"bMf" = (/obj/structure/cable/green{d1 = 4; d2 = 8; icon_state = "4-8"},/obj/structure/cable/green{d1 = 1; d2 = 8; icon_state = "1-8"},/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 4},/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 4},/obj/effect/floor_decal/industrial/warning{dir = 1},/turf/simulated/floor/tiled,/area/assembly/robotics)
"bMg" = (/obj/structure/cable/green{d1 = 2; d2 = 8; icon_state = "2-8"},/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 10},/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 10},/obj/effect/floor_decal/industrial/warning{dir = 1},/turf/simulated/floor/tiled,/area/assembly/robotics)
"bMh" = (/obj/structure/table/rack{dir = 8; layer = 2.9},/obj/item/weapon/storage/toolbox/mechanical,/obj/item/weapon/storage/toolbox/mechanical{pixel_x = -2; pixel_y = -1},/obj/effect/floor_decal/corner/pink{dir = 6},/obj/item/weapon/storage/toolbox/mechanical,/obj/item/device/multitool{pixel_x = 3},/obj/item/device/multitool{pixel_x = 3},/obj/item/weapon/crowbar,/obj/item/weapon/crowbar,/obj/item/weapon/storage/belt/utility,/obj/item/weapon/storage/belt/utility,/obj/item/weapon/storage/toolbox/electrical{pixel_x = 1; pixel_y = 6},/obj/effect/floor_decal/industrial/warning{dir = 1},/obj/item/weapon/storage/toolbox/electrical{pixel_x = 1; pixel_y = 6},/turf/simulated/floor/tiled,/area/assembly/robotics)
diff --git a/maps/plane/plane-1.dmm b/maps/plane/plane-1.dmm
new file mode 100644
index 00000000000..8017636b44a
--- /dev/null
+++ b/maps/plane/plane-1.dmm
@@ -0,0 +1,71 @@
+"a" = (/turf/unsimulated/wall/planetary/sif,/area/plane_ground)
+"b" = (/turf/simulated/floor/outdoors/dirt,/area/plane_ground)
+"c" = (/obj/effect/landmark/start,/turf/simulated/floor/outdoors/dirt,/area/plane_ground)
+"d" = (/obj/effect/landmark{name = "JoinLate"},/turf/simulated/floor/outdoors/dirt,/area/plane_ground)
+
+(1,1,1) = {"
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+abbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbba
+abbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbba
+abbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbba
+abbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbba
+abbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbba
+abbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbba
+abbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbba
+abbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbba
+abbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbba
+abbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbba
+abbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbba
+abbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbba
+abbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbba
+abbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbba
+abbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbba
+abbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbba
+abbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbba
+abbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbba
+abbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbba
+abbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbba
+abbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbba
+abbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbba
+abbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbba
+abbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbba
+abbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbba
+abbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbba
+abbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbba
+abbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbba
+abbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbba
+abbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbba
+abbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbba
+abbbbbbbbbbbbbbbbbbbbbbbbbbbbbbcbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbba
+abbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbba
+abbbbbbbbbbbbbbbbbbbbbbbbbbbbbdddbbbbbbbbbbbbbbbbbbbbbbbbbbbbbba
+abbbbbbbbbbbbbbbbbbbbbbbbbbbbbdddbbbbbbbbbbbbbbbbbbbbbbbbbbbbbba
+abbbbbbbbbbbbbbbbbbbbbbbbbbbbbdddbbbbbbbbbbbbbbbbbbbbbbbbbbbbbba
+abbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbba
+abbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbba
+abbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbba
+abbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbba
+abbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbba
+abbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbba
+abbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbba
+abbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbba
+abbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbba
+abbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbba
+abbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbba
+abbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbba
+abbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbba
+abbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbba
+abbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbba
+abbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbba
+abbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbba
+abbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbba
+abbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbba
+abbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbba
+abbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbba
+abbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbba
+abbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbba
+abbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbba
+abbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbba
+abbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbba
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+"}
diff --git a/maps/plane/plane-2.dmm b/maps/plane/plane-2.dmm
new file mode 100644
index 00000000000..06144256e95
--- /dev/null
+++ b/maps/plane/plane-2.dmm
@@ -0,0 +1,70 @@
+"a" = (/turf/unsimulated/wall/planetary/sif,/area/plane_sky)
+"b" = (/turf/simulated/open,/area/plane_sky)
+"c" = (/obj/effect/landmark/map_data{height = 2},/turf/simulated/open,/area/plane_sky)
+
+(1,1,1) = {"
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+abbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbba
+abbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbba
+abbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbba
+abbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbba
+abbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbba
+abbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbba
+abbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbba
+abbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbba
+abbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbba
+abbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbba
+abbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbba
+abbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbba
+abbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbba
+abbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbba
+abbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbba
+abbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbba
+abbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbba
+abbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbba
+abbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbba
+abbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbba
+abbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbba
+abbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbba
+abbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbba
+abbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbba
+abbbbbbbbbbbbbbbbbbbbbcbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbba
+abbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbba
+abbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbba
+abbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbba
+abbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbba
+abbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbba
+abbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbba
+abbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbba
+abbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbba
+abbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbba
+abbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbba
+abbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbba
+abbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbba
+abbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbba
+abbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbba
+abbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbba
+abbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbba
+abbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbba
+abbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbba
+abbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbba
+abbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbba
+abbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbba
+abbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbba
+abbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbba
+abbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbba
+abbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbba
+abbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbba
+abbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbba
+abbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbba
+abbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbba
+abbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbba
+abbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbba
+abbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbba
+abbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbba
+abbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbba
+abbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbba
+abbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbba
+abbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbba
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+"}
diff --git a/maps/plane/plane.dm b/maps/plane/plane.dm
new file mode 100644
index 00000000000..71ba0072af5
--- /dev/null
+++ b/maps/plane/plane.dm
@@ -0,0 +1,16 @@
+#if !defined(USING_MAP_DATUM)
+
+ #include "plane-1.dmm"
+ #include "plane-2.dmm"
+
+ #include "plane_defines.dm"
+ #include "plane_areas.dm"
+
+
+ #define USING_MAP_DATUM /datum/map/plane
+
+#elif !defined(MAP_OVERRIDE)
+
+ #warn A map has already been included, ignoring Plane
+
+#endif
\ No newline at end of file
diff --git a/maps/plane/plane_areas.dm b/maps/plane/plane_areas.dm
new file mode 100644
index 00000000000..2df2eb91d72
--- /dev/null
+++ b/maps/plane/plane_areas.dm
@@ -0,0 +1,5 @@
+/area/plane_ground
+ name = "flat plane"
+
+/area/plane_sky
+ name = "open sky"
\ No newline at end of file
diff --git a/maps/plane/plane_defines.dm b/maps/plane/plane_defines.dm
new file mode 100644
index 00000000000..8d1e48a5eca
--- /dev/null
+++ b/maps/plane/plane_defines.dm
@@ -0,0 +1,41 @@
+#define Z_LEVEL_FIRST_PLANE 1
+#define Z_LEVEL_SECOND_PLANE 2
+
+/datum/map/plane
+ name = "Another Test Map"
+ full_name = "The Flat Test Map"
+ path = "plane"
+
+ lobby_icon = 'icons/misc/title.dmi'
+ lobby_screens = list("mockingjay00")
+
+ zlevel_datum_type = /datum/map_z_level/plane
+
+ station_name = "The Plain Plane for Air Planes"
+ station_short = "The Plane"
+ dock_name = "the Maximum Fun Chamber"
+ boss_name = "Mister Fun"
+ boss_short = "Mr. Fun"
+ company_name = "Fun Inc."
+ company_short = "FI"
+ starsys_name = "Not Vir"
+
+/datum/map_z_level/plane/first
+ z = Z_LEVEL_FIRST_PLANE
+ name = "The Ground"
+ flags = MAP_LEVEL_STATION|MAP_LEVEL_CONTACT|MAP_LEVEL_PLAYER
+ transit_chance = 50
+ base_turf = /turf/simulated/floor/outdoors/rocks
+
+/datum/map_z_level/plane/second
+ z = Z_LEVEL_SECOND_PLANE
+ name = "The Sky"
+ flags = MAP_LEVEL_STATION|MAP_LEVEL_CONTACT|MAP_LEVEL_PLAYER
+ transit_chance = 50
+ base_turf = /turf/simulated/open
+
+/datum/planet/sif
+ expected_z_levels = list(
+ Z_LEVEL_FIRST_PLANE,
+ Z_LEVEL_SECOND_PLANE
+ )
\ No newline at end of file
diff --git a/maps/southern_cross/southern_cross-1.dmm b/maps/southern_cross/southern_cross-1.dmm
index 387e39f2a20..f7a9f84c3c7 100644
--- a/maps/southern_cross/southern_cross-1.dmm
+++ b/maps/southern_cross/southern_cross-1.dmm
@@ -4366,8 +4366,8 @@
"bFX" = (/obj/machinery/atmospherics/pipe/simple/heat_exchanging/junction{dir = 8; icon_state = "intact"; tag = "icon-intact (EAST)"},/obj/structure/lattice,/obj/structure/grille,/turf/space,/area/space)
"bFY" = (/obj/machinery/atmospherics/pipe/simple/visible/black{dir = 4},/obj/machinery/door/firedoor/border_only,/obj/machinery/door/blast/regular{density = 0; icon_state = "pdoor0"; id = "EngineWasteViewport1"; name = "Engine Waste Viewport Shutter"; opacity = 0},/obj/effect/wingrille_spawn/reinforced,/turf/simulated/floor,/area/engineering/engine_waste)
"bFZ" = (/obj/machinery/atmospherics/pipe/manifold/visible/black{dir = 1},/obj/machinery/button/remote/blast_door{desc = "A remote control-switch for the engine control room blast doors."; id = "EngineWasteViewport1"; name = "Engine Waste Blast Doors"; pixel_x = 0; pixel_y = 25; req_access = null; req_one_access = list(11,24)},/obj/effect/floor_decal/industrial/warning{icon_state = "warning"; dir = 8},/turf/simulated/floor,/area/engineering/engine_waste)
-"bGa" = (/obj/machinery/atmospherics/binary/pump{dir = 8},/obj/effect/floor_decal/industrial/outline/blue,/turf/simulated/floor,/area/engineering/engine_waste)
-"bGb" = (/obj/machinery/atmospherics/portables_connector{dir = 8},/obj/effect/floor_decal/industrial/outline/yellow,/turf/simulated/floor,/area/engineering/engine_waste)
+"bGa" = (/obj/machinery/atmospherics/binary/pump{dir = 8},/obj/effect/floor_decal/industrial/outline/blue,/obj/effect/engine_setup/pump_max,/turf/simulated/floor,/area/engineering/engine_waste)
+"bGb" = (/obj/machinery/atmospherics/portables_connector{dir = 8},/obj/effect/floor_decal/industrial/outline/yellow,/obj/effect/engine_setup/coolant_canister,/turf/simulated/floor,/area/engineering/engine_waste)
"bGc" = (/obj/machinery/atmospherics/pipe/cap/visible,/obj/machinery/atmospherics/pipe/simple/hidden/supply,/turf/simulated/floor,/area/engineering/engine_waste)
"bGd" = (/obj/machinery/atmospherics/pipe/simple/visible/black,/turf/simulated/floor,/area/engineering/engine_waste)
"bGe" = (/obj/machinery/atmospherics/pipe/simple/visible/cyan,/obj/structure/cable/green{d2 = 2; icon_state = "0-2"},/obj/machinery/power/apc{dir = 4; name = "east bump"; pixel_x = 24},/obj/machinery/light_switch{dir = 2; name = "light switch "; pixel_x = 36; pixel_y = 0},/turf/simulated/floor,/area/engineering/engine_waste)
@@ -4619,7 +4619,7 @@
"bKQ" = (/obj/machinery/atmospherics/pipe/simple/visible/black{dir = 9},/obj/effect/floor_decal/industrial/warning{icon_state = "warning"; dir = 8},/turf/simulated/floor,/area/engineering/engine_waste)
"bKR" = (/turf/simulated/floor,/area/engineering/engine_waste)
"bKS" = (/obj/structure/window/reinforced{dir = 4; health = 1e+006},/obj/effect/floor_decal/industrial/warning{dir = 4},/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/turf/simulated/floor,/area/engineering/engine_waste)
-"bKT" = (/obj/machinery/atmospherics/binary/pump{dir = 1},/obj/machinery/door/window/northleft{name = "Engine Waste"; req_one_access = list(10,24)},/obj/effect/floor_decal/industrial/warning{icon_state = "warning"; dir = 1},/obj/effect/floor_decal/industrial/outline/blue,/turf/simulated/floor,/area/engineering/engine_waste)
+"bKT" = (/obj/machinery/atmospherics/binary/pump{dir = 1},/obj/machinery/door/window/northleft{name = "Engine Waste"; req_one_access = list(10,24)},/obj/effect/floor_decal/industrial/warning{icon_state = "warning"; dir = 1},/obj/effect/floor_decal/industrial/outline/blue,/obj/effect/engine_setup/pump_max,/turf/simulated/floor,/area/engineering/engine_waste)
"bKU" = (/obj/machinery/door/window/northright{name = "Engine Waste"; req_one_access = list(10,24)},/obj/machinery/atmospherics/binary/pump{dir = 1},/obj/machinery/button/remote/blast_door{desc = "A remote control-switch for the engine control room blast doors."; id = "EngineEmitterPortWest"; name = "Engine Room Blast Doors"; pixel_x = 26; pixel_y = 0; req_access = null; req_one_access = list(11,24)},/obj/effect/floor_decal/industrial/warning{icon_state = "warning"; dir = 1},/obj/effect/floor_decal/industrial/outline/yellow,/turf/simulated/floor,/area/engineering/engine_waste)
"bKV" = (/obj/effect/floor_decal/industrial/warning{icon_state = "warning"; dir = 8},/obj/machinery/computer/security/engineering{name = "Drone Monitoring Cameras"; network = list("Engineering")},/obj/machinery/camera/network/engineering{c_tag = "ENG - Drone Fabrication"; dir = 4},/obj/machinery/firealarm{dir = 8; pixel_x = -24; pixel_y = 0},/turf/simulated/floor/plating,/area/engineering/drone_fabrication)
"bKW" = (/obj/structure/bed/chair{dir = 8},/turf/simulated/floor/plating,/area/engineering/drone_fabrication)
@@ -4960,7 +4960,7 @@
"bRt" = (/obj/machinery/door/firedoor/border_only,/obj/machinery/door/airlock/research{id_tag = "researchdoor"; name = "Research Division Access"; req_access = list(47)},/obj/machinery/atmospherics/pipe/simple/hidden/supply,/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/obj/structure/cable/green{d1 = 1; d2 = 2; icon_state = "1-2"},/obj/structure/disposalpipe/segment,/turf/simulated/floor/tiled/dark,/area/rnd/research)
"bRu" = (/obj/effect/floor_decal/industrial/warning{dir = 4},/obj/machinery/atmospherics/pipe/simple/hidden/supply,/obj/machinery/power/apc{dir = 8; name = "west bump"; pixel_x = -24},/obj/machinery/light_switch{pixel_x = -36},/obj/structure/cable/green,/turf/simulated/floor/tiled/white,/area/assembly/robotics)
"bRv" = (/obj/machinery/mecha_part_fabricator,/obj/effect/floor_decal/industrial/outline/yellow,/turf/simulated/floor/tiled,/area/assembly/robotics)
-"bRw" = (/obj/effect/floor_decal/industrial/outline/yellow,/obj/structure/table/steel_reinforced,/obj/item/device/robotanalyzer,/obj/item/device/robotanalyzer,/obj/item/device/mmi/digital/posibrain,/turf/simulated/floor/tiled,/area/assembly/robotics)
+"bRw" = (/obj/effect/floor_decal/industrial/outline/yellow,/obj/structure/table/steel_reinforced,/obj/item/device/robotanalyzer,/obj/item/device/robotanalyzer,/obj/item/device/mmi/digital/robot,/turf/simulated/floor/tiled,/area/assembly/robotics)
"bRx" = (/obj/machinery/pros_fabricator,/obj/effect/floor_decal/industrial/outline/yellow,/turf/simulated/floor/tiled,/area/assembly/robotics)
"bRy" = (/obj/machinery/camera/network/research{c_tag = "SCI - Robotics"; dir = 1},/turf/simulated/floor/tiled/white,/area/assembly/robotics)
"bRz" = (/obj/effect/floor_decal/industrial/warning{dir = 8},/obj/machinery/firealarm{dir = 1; pixel_x = 0; pixel_y = -24},/turf/simulated/floor/tiled,/area/assembly/robotics)
@@ -4990,9 +4990,9 @@
"bRX" = (/obj/machinery/atmospherics/pipe/cap/visible{dir = 1},/obj/effect/floor_decal/industrial/warning/corner,/turf/simulated/floor,/area/engineering/engine_room)
"bRY" = (/obj/effect/floor_decal/industrial/warning,/turf/simulated/floor,/area/engineering/engine_room)
"bRZ" = (/obj/machinery/atmospherics/pipe/simple/visible/green,/turf/simulated/floor,/area/engineering/engine_room)
-"bSa" = (/obj/machinery/atmospherics/omni/filter{tag_east = 1; tag_north = 2; tag_south = 4; tag_west = 0; use_power = 0},/obj/effect/floor_decal/industrial/outline/blue,/turf/simulated/floor/plating,/area/engineering/engine_room)
+"bSa" = (/obj/machinery/atmospherics/omni/filter{tag_east = 0; tag_north = 2; tag_south = 4; tag_west = 1; use_power = 0},/obj/effect/floor_decal/industrial/outline/blue,/obj/structure/sign/warning/nosmoking_2{pixel_x = 32},/obj/effect/engine_setup/filter,/turf/simulated/floor/plating,/area/engineering/engine_room)
"bSb" = (/obj/machinery/atmospherics/pipe/manifold4w/visible/cyan,/turf/simulated/floor,/area/engineering/engine_room)
-"bSc" = (/obj/machinery/atmospherics/omni/filter{tag_east = 0; tag_north = 2; tag_south = 4; tag_west = 1; use_power = 0},/obj/effect/floor_decal/industrial/outline/blue,/obj/structure/sign/warning/nosmoking_2{pixel_x = 32},/turf/simulated/floor/plating,/area/engineering/engine_room)
+"bSc" = (/obj/machinery/atmospherics/omni/filter{tag_east = 1; tag_north = 2; tag_south = 4; tag_west = 0; use_power = 0},/obj/effect/floor_decal/industrial/outline/blue,/obj/effect/engine_setup/filter,/turf/simulated/floor/plating,/area/engineering/engine_room)
"bSd" = (/obj/effect/floor_decal/industrial/warning{dir = 10},/turf/simulated/floor/plating,/area/engineering/drone_fabrication)
"bSe" = (/obj/effect/landmark{name = "JoinLateCyborg"},/obj/effect/floor_decal/industrial/warning,/turf/simulated/floor/plating,/area/engineering/drone_fabrication)
"bSf" = (/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/obj/structure/disposalpipe/segment,/turf/simulated/floor/tiled,/area/engineering/hallway/engineer_hallway)
@@ -5411,7 +5411,7 @@
"cac" = (/obj/machinery/atmospherics/pipe/manifold/visible/yellow{dir = 4},/obj/machinery/meter,/obj/effect/floor_decal/industrial/warning/corner{dir = 8},/turf/simulated/floor,/area/engineering/engine_room)
"cad" = (/obj/machinery/atmospherics/pipe/simple/visible/cyan,/obj/machinery/meter,/turf/simulated/floor,/area/engineering/engine_room)
"cae" = (/obj/machinery/atmospherics/unary/vent_scrubber/on,/turf/simulated/floor,/area/engineering/engine_room)
-"caf" = (/obj/machinery/atmospherics/binary/pump{dir = 1},/obj/effect/floor_decal/industrial/warning/corner{icon_state = "warningcorner"; dir = 4},/obj/machinery/airlock_sensor/airlock_interior{id_tag = "eng_al_int_snsr"; master_tag = "engine_room_airlock"; pixel_x = 22; pixel_y = 0; req_access = list(10)},/turf/simulated/floor,/area/engineering/engine_room)
+"caf" = (/obj/machinery/atmospherics/binary/pump{dir = 1},/obj/effect/floor_decal/industrial/warning/corner{icon_state = "warningcorner"; dir = 4},/obj/machinery/airlock_sensor/airlock_interior{id_tag = "eng_al_int_snsr"; master_tag = "engine_room_airlock"; pixel_x = 22; pixel_y = 0; req_access = list(10)},/obj/effect/engine_setup/pump_max,/turf/simulated/floor,/area/engineering/engine_room)
"cag" = (/obj/machinery/door/firedoor/border_only,/obj/machinery/atmospherics/pipe/simple/hidden/supply,/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/obj/structure/cable/cyan{d1 = 1; d2 = 2; icon_state = "1-2"},/obj/machinery/door/airlock/maintenance_hatch{icon_state = "door_closed"; locked = 0; name = "Engine Access"; req_one_access = list(11)},/turf/simulated/floor/tiled,/area/engineering/engine_airlock)
"cah" = (/obj/machinery/status_display,/turf/simulated/wall/r_wall,/area/engineering/engine_airlock)
"cai" = (/obj/structure/sign/warning/radioactive,/turf/simulated/wall/r_wall,/area/engineering/engine_airlock)
@@ -5481,7 +5481,7 @@
"cbu" = (/obj/machinery/atmospherics/pipe/simple/visible/yellow,/obj/effect/floor_decal/industrial/warning{icon_state = "warning"; dir = 8},/obj/machinery/button/remote/blast_door{id = "EngineVent"; name = "Reactor Ventillatory Control"; pixel_x = -25; pixel_y = 0; req_access = list(10)},/turf/simulated/floor,/area/engineering/engine_room)
"cbv" = (/obj/machinery/atmospherics/pipe/simple/visible/cyan,/turf/simulated/floor,/area/engineering/engine_room)
"cbw" = (/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/turf/simulated/floor,/area/engineering/engine_room)
-"cbx" = (/obj/machinery/atmospherics/portables_connector{dir = 1},/obj/effect/floor_decal/industrial/outline/blue,/turf/simulated/floor,/area/engineering/engine_room)
+"cbx" = (/obj/machinery/atmospherics/portables_connector{dir = 1},/obj/effect/floor_decal/industrial/outline/blue,/obj/effect/engine_setup/coolant_canister,/turf/simulated/floor,/area/engineering/engine_room)
"cby" = (/obj/machinery/door/firedoor/border_only,/obj/machinery/door/blast/regular{density = 0; dir = 1; icon_state = "pdoor0"; id = "EngineBlast"; name = "Engine Monitoring Room Blast Doors"; opacity = 0},/obj/effect/wingrille_spawn/reinforced,/turf/simulated/floor,/area/engineering/engine_monitoring)
"cbz" = (/obj/machinery/computer/general_air_control/supermatter_core{frequency = 1438; input_tag = "cooling_in"; name = "Engine Cooling Control"; output_tag = "cooling_out"; pressure_setting = 100; sensors = list("engine_sensor" = "Engine Core")},/turf/simulated/floor/tiled,/area/engineering/engine_monitoring)
"cbA" = (/obj/structure/table/reinforced,/obj/item/weapon/book/manual/supermatter_engine,/obj/structure/cable/cyan{d2 = 4; icon_state = "0-4"},/obj/machinery/power/apc{dir = 1; name = "north bump"; pixel_x = 0; pixel_y = 24},/obj/machinery/light_switch{pixel_x = 11; pixel_y = 24},/turf/simulated/floor/tiled,/area/engineering/engine_monitoring)
@@ -5646,7 +5646,7 @@
"ceD" = (/obj/machinery/disease2/isolator,/obj/effect/floor_decal/corner/lime/full{dir = 1},/turf/simulated/floor/tiled/white,/area/medical/virology)
"ceE" = (/obj/machinery/door/blast/regular{icon_state = "pdoor1"; id = "EngineVent"; name = "Reactor Vent"; p_open = 0},/obj/machinery/shield_diffuser,/turf/simulated/floor/reinforced/airless,/area/engineering/engine_room)
"ceF" = (/turf/simulated/floor/greengrid/nitrogen,/area/engineering/engine_room)
-"ceG" = (/obj/machinery/mass_driver{dir = 8; id = "enginecore"},/obj/machinery/power/supermatter{layer = 4},/turf/simulated/floor/greengrid/nitrogen,/area/engineering/engine_room)
+"ceG" = (/obj/machinery/mass_driver{dir = 8; id = "enginecore"},/obj/machinery/power/supermatter{layer = 4},/obj/effect/engine_setup/core,/turf/simulated/floor/greengrid/nitrogen,/area/engineering/engine_room)
"ceH" = (/obj/machinery/air_sensor{frequency = 1438; id_tag = "engine_sensor"; output = 63},/obj/effect/floor_decal/industrial/warning{icon_state = "warning"; dir = 4},/obj/effect/floor_decal/industrial/warning{icon_state = "warning"; dir = 8},/turf/simulated/floor/reinforced/nitrogen{nitrogen = 82.1472},/area/engineering/engine_room)
"ceI" = (/obj/effect/wingrille_spawn/reinforced_phoron,/obj/machinery/door/blast/regular{dir = 1; id = "SupermatterPort"; layer = 3.3; name = "Reactor Blast Door"},/turf/simulated/floor,/area/engineering/engine_room)
"ceJ" = (/obj/machinery/atmospherics/pipe/simple/visible/yellow,/obj/effect/floor_decal/industrial/warning{icon_state = "warning"; dir = 8},/obj/effect/floor_decal/industrial/hatch/yellow,/turf/simulated/floor,/area/engineering/engine_room)
@@ -5845,7 +5845,7 @@
"ciu" = (/obj/machinery/disease2/incubator,/obj/effect/floor_decal/corner/lime/full{dir = 4},/turf/simulated/floor/tiled/white,/area/medical/virology)
"civ" = (/obj/machinery/atmospherics/pipe/simple/visible/yellow,/obj/effect/floor_decal/industrial/warning{icon_state = "warning"; dir = 8},/obj/machinery/button/remote/blast_door{desc = "A remote control-switch for the engine charging port."; id = "SupermatterPort"; name = "Reactor Blast Doors"; pixel_x = -25; pixel_y = 6; req_access = list(10)},/obj/machinery/button/remote/blast_door{desc = "A remote control-switch for the engine control room blast doors."; id = "EngineBlast"; name = "Engine Monitoring Room Blast Doors"; pixel_x = -25; pixel_y = -6; req_access = list(10)},/turf/simulated/floor,/area/engineering/engine_room)
"ciw" = (/obj/machinery/atmospherics/pipe/simple/hidden/supply,/turf/simulated/floor,/area/engineering/engine_room)
-"cix" = (/obj/machinery/atmospherics/portables_connector,/obj/effect/floor_decal/industrial/outline/blue,/turf/simulated/floor,/area/engineering/engine_room)
+"cix" = (/obj/machinery/atmospherics/portables_connector,/obj/effect/floor_decal/industrial/outline/blue,/obj/effect/engine_setup/coolant_canister,/turf/simulated/floor,/area/engineering/engine_room)
"ciy" = (/obj/machinery/computer/station_alert,/turf/simulated/floor/tiled,/area/engineering/engine_monitoring)
"ciz" = (/obj/structure/table/reinforced,/obj/item/clothing/ears/earmuffs,/obj/machinery/alarm{dir = 1; icon_state = "alarm0"; pixel_y = -22},/obj/structure/cable/cyan{d1 = 1; d2 = 2; icon_state = "1-2"},/turf/simulated/floor/tiled,/area/engineering/engine_monitoring)
"ciA" = (/obj/machinery/atmospherics/unary/vent_scrubber/on{dir = 4},/obj/machinery/light,/obj/machinery/newscaster{pixel_y = -30},/turf/simulated/floor/tiled,/area/engineering/engine_monitoring)
@@ -5917,7 +5917,7 @@
"cjO" = (/obj/machinery/atmospherics/pipe/simple/visible/yellow{dir = 4},/obj/effect/floor_decal/industrial/warning{dir = 1},/obj/machinery/camera/network/engine{c_tag = "ENG - Engine Core 3"; dir = 2},/turf/simulated/floor,/area/engineering/engine_room)
"cjP" = (/obj/machinery/atmospherics/pipe/manifold/visible/yellow{dir = 4},/obj/machinery/meter,/obj/effect/floor_decal/industrial/warning/corner{icon_state = "warningcorner"; dir = 1},/turf/simulated/floor,/area/engineering/engine_room)
"cjQ" = (/obj/machinery/atmospherics/unary/vent_pump/on{dir = 1},/turf/simulated/floor,/area/engineering/engine_room)
-"cjR" = (/obj/machinery/atmospherics/binary/pump,/obj/effect/floor_decal/industrial/warning/corner,/turf/simulated/floor,/area/engineering/engine_room)
+"cjR" = (/obj/machinery/atmospherics/binary/pump,/obj/effect/floor_decal/industrial/warning/corner,/obj/effect/engine_setup/pump_max,/turf/simulated/floor,/area/engineering/engine_room)
"cjS" = (/turf/simulated/wall/r_wall,/area/engineering/engine_smes)
"cjT" = (/obj/structure/cable/cyan{d1 = 1; d2 = 2; icon_state = "1-2"},/turf/simulated/wall/r_wall,/area/engineering/engine_smes)
"cjU" = (/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; pixel_y = 0},/obj/machinery/door/airlock/maintenance_hatch{name = "SMES Access"; req_access = list(11)},/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/obj/machinery/atmospherics/pipe/simple/hidden/supply,/obj/machinery/door/firedoor/border_only,/turf/simulated/floor/tiled,/area/engineering/engine_smes)
@@ -6111,11 +6111,11 @@
"cnA" = (/obj/effect/floor_decal/industrial/warning{icon_state = "warning"; dir = 8},/obj/machinery/atmospherics/pipe/simple/visible/cyan{dir = 9},/turf/simulated/floor,/area/engineering/engine_room)
"cnB" = (/obj/machinery/atmospherics/pipe/simple/visible/green,/obj/structure/cable/yellow{d1 = 1; d2 = 2; icon_state = "1-2"},/turf/simulated/floor,/area/engineering/engine_room)
"cnC" = (/obj/effect/floor_decal/industrial/warning/corner{icon_state = "warningcorner"; dir = 4},/obj/machinery/alarm/nobreach{dir = 8; pixel_x = 22; pixel_y = 0},/turf/simulated/floor,/area/engineering/engine_room)
-"cnD" = (/obj/structure/cable/cyan{d2 = 4; icon_state = "0-4"},/obj/machinery/power/smes/buildable{charge = 2e+006; input_attempt = 1; input_level = 100000; output_level = 200000; RCon_tag = "Engine - Core"},/turf/simulated/floor/plating,/area/engineering/engine_smes)
+"cnD" = (/obj/structure/cable/cyan{d2 = 4; icon_state = "0-4"},/obj/machinery/power/smes/buildable{charge = 2e+006; input_attempt = 1; input_level = 100000; output_level = 200000; RCon_tag = "Engine - Core"},/obj/effect/engine_setup/smes,/turf/simulated/floor/plating,/area/engineering/engine_smes)
"cnE" = (/obj/structure/cable/cyan{d1 = 1; d2 = 8; icon_state = "1-8"},/obj/effect/floor_decal/industrial/warning{icon_state = "warning"; dir = 8},/obj/structure/cable/cyan{d2 = 8; icon_state = "0-8"},/obj/machinery/power/apc{dir = 2; name = "south bump"; pixel_y = -24},/obj/machinery/light_switch{pixel_x = 12; pixel_y = -24},/obj/structure/table/steel,/obj/item/stack/cable_coil{pixel_x = 3; pixel_y = 3},/obj/item/stack/cable_coil{pixel_x = 3; pixel_y = 3},/obj/item/weapon/storage/box/lights/mixed,/turf/simulated/floor/tiled,/area/engineering/engine_smes)
"cnF" = (/obj/structure/cable/yellow{d1 = 1; d2 = 4; icon_state = "1-4"},/obj/structure/table/steel,/obj/item/device/multitool{pixel_x = 5},/obj/item/clothing/gloves/yellow,/obj/machinery/camera/network/engine{c_tag = "ENG - SMES Room"; dir = 1},/obj/machinery/alarm{dir = 1; icon_state = "alarm0"; pixel_y = -22},/obj/machinery/atmospherics/unary/vent_scrubber/on{dir = 1},/turf/simulated/floor/tiled,/area/engineering/engine_smes)
"cnG" = (/obj/structure/cable/yellow{d2 = 8; icon_state = "0-8"},/obj/machinery/power/terminal{dir = 4},/obj/effect/floor_decal/industrial/warning{dir = 4},/obj/structure/extinguisher_cabinet{pixel_y = -30},/turf/simulated/floor/tiled,/area/engineering/engine_smes)
-"cnH" = (/obj/structure/cable,/obj/machinery/power/smes/buildable{charge = 1e+007; cur_coils = 4; input_attempt = 1; input_level = 750000; output_level = 500000; RCon_tag = "Engine - Main"},/turf/simulated/floor/plating,/area/engineering/engine_smes)
+"cnH" = (/obj/structure/cable,/obj/machinery/power/smes/buildable{charge = 1e+007; cur_coils = 4; input_attempt = 1; input_level = 750000; output_level = 500000; RCon_tag = "Engine - Main"},/obj/effect/engine_setup/smes/main,/turf/simulated/floor/plating,/area/engineering/engine_smes)
"cnI" = (/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; pixel_y = 0},/obj/machinery/atmospherics/pipe/simple/hidden/supply,/obj/structure/disposalpipe/segment,/turf/simulated/floor,/area/maintenance/apmaint)
"cnJ" = (/turf/simulated/wall,/area/construction/seconddeck/construction1)
"cnK" = (/obj/structure/disposalpipe/segment,/turf/simulated/wall,/area/construction/seconddeck/construction1)
@@ -6371,7 +6371,7 @@
"csA" = (/obj/machinery/door/firedoor/border_only,/obj/effect/wingrille_spawn/reinforced,/obj/machinery/door/blast/regular{density = 0; icon_state = "pdoor0"; id = "EngineRadiatorViewport2"; name = "Engine Radiator Viewport Shutter"; opacity = 0},/obj/machinery/atmospherics/pipe/manifold/visible/green,/turf/simulated/floor,/area/engineering/engine_room)
"csB" = (/obj/machinery/atmospherics/pipe/manifold/visible/green,/obj/effect/floor_decal/industrial/warning/corner{icon_state = "warningcorner"; dir = 4},/obj/machinery/button/remote/blast_door{desc = "A remote control-switch for the engine radiator viewport shutters."; id = "EngineRadiatorViewport2"; name = "Engine Radiator Viewport Shutters"; pixel_x = 0; pixel_y = -25; req_access = list(10)},/turf/simulated/floor,/area/engineering/engine_room)
"csC" = (/obj/machinery/atmospherics/pipe/simple/visible/green{dir = 10; icon_state = "intact"; tag = "icon-intact (SOUTHEAST)"},/obj/effect/floor_decal/industrial/warning{dir = 1},/turf/simulated/floor,/area/engineering/engine_room)
-"csD" = (/obj/machinery/atmospherics/binary/pump/high_power{dir = 1},/obj/effect/floor_decal/industrial/warning/corner{icon_state = "warningcorner"; dir = 1},/obj/effect/floor_decal/industrial/outline/blue,/turf/simulated/floor,/area/engineering/engine_room)
+"csD" = (/obj/machinery/atmospherics/binary/pump/high_power{dir = 1},/obj/effect/floor_decal/industrial/warning/corner{icon_state = "warningcorner"; dir = 1},/obj/effect/floor_decal/industrial/outline/blue,/obj/effect/engine_setup/pump_max,/turf/simulated/floor,/area/engineering/engine_room)
"csE" = (/obj/machinery/atmospherics/pipe/simple/visible/green,/obj/effect/floor_decal/industrial/warning/corner{icon_state = "warningcorner"; dir = 4},/turf/simulated/floor,/area/engineering/engine_room)
"csF" = (/obj/machinery/portable_atmospherics/canister/nitrogen,/obj/effect/floor_decal/industrial/outline/blue,/turf/simulated/floor/plating,/area/engineering/engine_room)
"csG" = (/obj/machinery/portable_atmospherics/canister/nitrogen,/obj/effect/floor_decal/industrial/outline/blue,/obj/structure/sign/warning/nosmoking_2{pixel_x = 32},/turf/simulated/floor/plating,/area/engineering/engine_room)
@@ -10489,7 +10489,7 @@ aaaaaaaaaaaaaaaaaabvybvybvybvybvybvybvybvybvybvybvybvybvybvybvybvybvybvybvybvybv
aaaaaaaaaaaaaaaaaabvybvybvybvybvybvybvybvybvybvybvybvybvybvybvybvybvybvybvybvybvybvybvyaaaaaaaaaaaaaaaaadaaaaaaaaaaafaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaafaaaaaaaaaaaaaaabDhbMBbMCbMDbMEbMFbMGbDhbMHbMIbKXbMJbysbMKbMLbLcbLcbMMbMNbMObMObMPbMQbMRbLgbMSbMTbMUbMVbMWbMXbMYbMZbNabAhbNbbNcbNdbNebNfbNgbNhbNibNjbNjbNkbNjbNjbNjbNjbpJbpJbxBbNlbpJaaaaaaaaabGKbGKbLCbLDbLEbLEbNmbNnbNobNpbNpbNpbNqbNrbNsbNtbNubNvbNvbNwbNwbNxbNybIGbIGbLKbLObDNbDNaaaaaaaaabrybNzbNAbNBbKrbNCbNDbNEbNFbNGbNHbNIbNJbNKbNLbNMbNNbNObNPbNPbNPbNQbNRbNSbNTbNUbNVbKybNWbNXbNYbNZbOabOabOabOabKBbObbOcbOdbKEbOebOfbFLbOgbOhbOibOjbOkbOlbOmbOnbEFaaaaaaaabaaaaaaaaaaaRaadaadaadaadaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaabvybvybvybvybvybvybvybvybvybvybvybvybvybvybvybvybvybvybvybvybvyaaaaaaaaaaaaaaaaaaaafaaaaaaaaabFVbOobFVbOobFVbOobFVbOobFVbOobFVbOoaafaafaafbOpbOqbOqbOqbOqbOqbOpbOrbOsbOqbwObOtbKXbOubysbOvbOwbLcbOxbOybOzbOybOAbOBbOybOCbLgbODbOEbOFbOGbOHbOIbOJbMZbOKbAhbOLbOMbONbOObOPbOQbORbOSbNjbOTbOUbOVbOVbOWbNjbOXbtybxBbOYbClaaaaaaaaabGKbOZbLDbLEbPabPbbPcbPdbPebPfbPgbPhbPibPjbPkbIGbLIbPlbIGbIGbPmbPnbPobPpbPqbIGbLKbPrbDNaaaaaaaaabqvbPsbsIbPtbKrbPubPvbPwbPxbPybPzbPAbPBbPCbPDbMabPEbPFbPGbPHbPGbPIbNUbPJbPKbPLbPMbKybPNbPObPPbPQbPRbPSbOabPTbKBbPUbPVbPWbKEbPXbPYbFLbPZbQabQbbQbbQbbQabQabQcbDgaaaaaaaaaaaaaaaaaaaaaaafaaaaaaaadaagaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabvybvybvybvybvybvybvybvybvybvybvybvybvyaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaafaaaaaaaaabQdbQebQfbQebQfbQebQfbQebQfbQebQfbQebQgbQhbOqbOqbQibQjbQkbQlbQkbQmbQnbQobQpbwObQqbQrbQsbQtbQubQvbLcbQwbOybQxbQybQzbQAbOybQBbLgbQCbQDbQEbQFbQGbQHbAhbQIbQJbQKbQLbQMbQNbQObQPbQQbORbLsbQRbQSbQTbQSbQUbQVbNjbQWbtybxBbQXbClaaaaaabGJbGJbQYbLEbLEbQZbRabRbbRcbRdbRcbRcbRebRfbFtbRgbRhbRibRibRjbRkbRlbRibRibRmbPpbIGbIGbRnbGLbGLaaaaaabqvbPsbsIbRobKrbRpbRqbRrbPxbRsbKrbKrbsTbRtbsTbKybKybRubRvbRwbRxbPIbRybRzbRAbPGbRBbKybRCbRDbREbRFbPRbRGbOabRHbKBbRIbRJbRKbKEbRLbwFbFLbPZbRMbRNbRObRPbRQbRRbQcbBEaaaaaaaaaaaaaaaaaaaaaaafaaaaaaaaaaadaadaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabvybvybvybvybvybvybvybvybvybvybvybvybvyaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaafaaaaaaaaabHJbFWbFWbFWbFWbFWbFWbFWbFWbFWbFWbFWbQgbRSbRTbRUbRVbRWbRXbRYbRWbRZbSabSbbScbwObSdbSebGjbysbSfbSgbLcbShbOybOybSibSjbOybOybSkbLgbSlbSmbSnbSobSpbSqbSrbSsbStbBXbSubOMbLsbSvbSwbSwbSxbLsbNjbSybSzbSAbSBbSCbNjbQWbtybxBbyVbClaaaaaabGJbSDbSEbLEbSFbSGbRbbRbbSHbSIbSJbRbbSKbRfbRfbSLbRibRibSMbSNbSNbSObSPbRibRibSQbSRbSSbSTbSUbGLaaaaaabqvbPsbSVbSVbKrbSWbSXbSXbSYbSZbPAbTabTbbTcbTdbTebMabTfbTgbTgbTgbThbTibTibTjbTkbTibTlbTmbTnbTobTpbOabOabOabTqbKBbTrbTsbTtbKEbMubMvbFLbTubFLbFLbFLbFLbFLbFLbFLbFLbTvbTvaaaaaaaaaaaaaaaaafaaaaaaaaaaaaaadaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabvybvybvybvybvybvybvybvybvybvybvybvybvyaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaafaaaaaaaaabHJbFWbFWbFWbFWbFWbFWbFWbFWbFWbFWbFWbQgbRSbRTbRUbRVbRWbRXbRYbRWbRZbScbSbbSabwObSdbSebGjbysbSfbSgbLcbShbOybOybSibSjbOybOybSkbLgbSlbSmbSnbSobSpbSqbSrbSsbStbBXbSubOMbLsbSvbSwbSwbSxbLsbNjbSybSzbSAbSBbSCbNjbQWbtybxBbyVbClaaaaaabGJbSDbSEbLEbSFbSGbRbbRbbSHbSIbSJbRbbSKbRfbRfbSLbRibRibSMbSNbSNbSObSPbRibRibSQbSRbSSbSTbSUbGLaaaaaabqvbPsbSVbSVbKrbSWbSXbSXbSYbSZbPAbTabTbbTcbTdbTebMabTfbTgbTgbTgbThbTibTibTjbTkbTibTlbTmbTnbTobTpbOabOabOabTqbKBbTrbTsbTtbKEbMubMvbFLbTubFLbFLbFLbFLbFLbFLbFLbFLbTvbTvaaaaaaaaaaaaaaaaafaaaaaaaaaaaaaadaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabvybvybvybvybvybvybvybvybvybvybvybvybvyaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaagaaaaaaaaabFVbOobFVbOobFVbOobFVbOobFVbOobFVbOoaadbTwbTxbTybTzbTAbTBbTCbTAbRZbTDbTEbTFbwObTGbTHbTGbysbTIbTJbLcbTKbOybOybTLbSjbOybOybTMbLgbTNbTObTPbTQbTRbTSbMYbJXbAhbAhbNbbTTbTUbLsbLsbLsbLsbTVbNjbTWbNjbTXbNjbNjbNjbpJbtybxBbTYbpJaaaaaabGKbTZbUabUbbUcbUdbUebUfbUgbUhbUibRbbUjbUjbUkbUlbRibUmbUnbUobUobUpbUqbUrbRibUsbUtbUubSTbUvbDNaaaaaabrybPsbzcbrybKrbUwbUxbUybUybUzbUAbUBbUCbUDbUEbUFbUGbUHbUIbUIbUIbUJbUKbULbUMbUNbUObTlbUPbUQbURbUSbKBbUTbUUbUVbKBbUWbUXbUYbKEbMubMvbUZbVabVbbVcbVdbVebVfbVgbVhbVibVjbVkbVkbVjbVjbVjbVjbVjaaaaaaaaaaaaaadaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabvybvybvybvybvybvybvybvybvybvybvybvybvyaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaadaaaaaaaaabQdbQebQfbQebQfbQebQfbQebQfbQebQfbQebQgbVlbOqbVmbTCbTAbTBbTCbTAbRZbVnbVobVobVobVobVobVobVobVpbVqbLcbVrbVsbVtbVubVvbVwbVxbVybLgbLgbVzbLgbVAbVBbLgbVCbJXbAhbAhbVDbLqbVEbVFbVGbVHbVIbVJbNjbVKbNjbVLbNjbVMbVNbVObtybxBbtybpJaaaaaabGKbVPbVQbPgbVRbVSbVTbVUbVVbVWbVXbVYbVZbWabWbbWcbRibWdbWebWfbWgbWhbUqbWibWjbWkbWlbWmbWnbWobDNaaaaaabrybPsbWpbWqbKrbKrbWrbWsbWtbWubPAbWvbWwbWxbWybWzbWAbWBbWCbWDbWEbWFbUKbWGbWHbWIbWJbTlbKBbWKbKBbKBbKBbKBbKBbKBbKBbKEbKEbKEbKEbWLbWMbUZbWNbWObWPbWQbWRbWSbVebVhbVhbVjbWTbWUbWVbVjbWWbWXbVjbVjaafaafaafaadaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabvybvybvybvybvybvybvybvybvyaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaadaafaafaafbQdbWYbWZbWYbWZbWYbWZbWYbWZbWYbWZbWYbQgbXabOqbXbbTCbXcbXdbTCbXcbRZbXebVobXfbXgbXhbXibXjbVobSfbXkbVybVybVybVybVybVybVybVybVybXlbLgbLgbLgbLgbLgbLgbXmbXnbyHbXobXmbXpbXpbXpbXpbXpbXpbXpbXqbXqbXqbXqbNjbXrbXsbpJbXtbXubXvbpJaaaaaabGKbXwbXxbLEbXybXzbRbbRbbRbbRbbRbbRbbXAbXBbXBbXCbRibRibRibRibRibXDbUqbXEbRibIGbWlbWmbWnbXFbDNaaaaaabrybXGbsIbsIbXHbKrbKrbKrbKrbKrbKrbXIbXJbXKbXJbXIbKybKybKybKybKybKybTlbXLbXMbXMbXNbTlbXObXObXObXPbXQbXRbXSbXTbXUbXVbXWbsTbXXbXYbXZbYabYbbYcbYdbWQbWRbYebVebYfbVhbYgbYhbYibYjbVkbYkbYibYlbVjaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
diff --git a/maps/southern_cross/southern_cross-6.dmm b/maps/southern_cross/southern_cross-6.dmm
index 56d7b4b597e..ec1251924fa 100644
--- a/maps/southern_cross/southern_cross-6.dmm
+++ b/maps/southern_cross/southern_cross-6.dmm
@@ -2177,7 +2177,7 @@
"PS" = (/obj/structure/table/steel,/obj/item/weapon/storage/firstaid/o2{pixel_x = 3; pixel_y = 3},/obj/item/weapon/storage/firstaid/regular,/obj/machinery/atmospherics/pipe/manifold/visible,/turf/simulated/shuttle/floor/voidcraft/light,/area/syndicate_station/start)
"PT" = (/obj/machinery/atmospherics/unary/freezer{tag = "icon-freezer_0 (WEST)"; icon_state = "freezer_0"; dir = 8},/turf/simulated/shuttle/floor/voidcraft/light,/area/syndicate_station/start)
"PU" = (/turf/space,/obj/structure/shuttle/engine/propulsion,/turf/simulated/shuttle/plating/airless/carry,/area/skipjack_station/start)
-"PV" = (/obj/structure/table/standard,/obj/item/weapon/legcuffs,/turf/simulated/shuttle/floor/black,/area/skipjack_station/start)
+"PV" = (/obj/structure/table/standard,/obj/item/weapon/handcuffs/legcuffs,/turf/simulated/shuttle/floor/black,/area/skipjack_station/start)
"PW" = (/obj/structure/table/standard,/obj/item/weapon/deck/cards,/turf/simulated/shuttle/floor/black,/area/skipjack_station/start)
"PX" = (/obj/structure/grille,/obj/structure/window/reinforced,/obj/structure/window/reinforced{dir = 4},/obj/structure/window/reinforced{dir = 8},/obj/machinery/door/blast/regular{id = "skipjackshutters"; name = "Skipjack Blast Shielding"},/turf/simulated/shuttle/plating,/area/skipjack_station/start)
"PY" = (/obj/machinery/light/small,/turf/simulated/shuttle/floor/skipjack,/area/skipjack_station/start)
diff --git a/maps/submaps/cave_submaps/cave.dm b/maps/submaps/cave_submaps/cave.dm
index cf063c85aac..d30004887f4 100644
--- a/maps/submaps/cave_submaps/cave.dm
+++ b/maps/submaps/cave_submaps/cave.dm
@@ -2,4 +2,9 @@
name = "Cave Content"
desc = "Don't dig too deep!"
-// To be added: Templates for cave exploration when they are made.
\ No newline at end of file
+// To be added: Templates for cave exploration when they are made.
+
+/datum/map_template/cave/deadBeacon
+ name = "Abandoned Relay"
+ desc = "An unregistered comms relay, abandoned to the elements."
+ mappath = 'maps/submaps/cave_submaps/deadBeacon.dmm'
\ No newline at end of file
diff --git a/maps/submaps/cave_submaps/cave_areas.dm b/maps/submaps/cave_submaps/cave_areas.dm
new file mode 100644
index 00000000000..7c80c66ec10
--- /dev/null
+++ b/maps/submaps/cave_submaps/cave_areas.dm
@@ -0,0 +1,6 @@
+/area/submap/cave
+ name = "Cave Submap Area"
+ icon_state = "submap"
+
+/area/submap/cave/deadBeacon
+ name = "abandoned relay"
\ No newline at end of file
diff --git a/maps/submaps/cave_submaps/deadBeacon.dmm b/maps/submaps/cave_submaps/deadBeacon.dmm
new file mode 100644
index 00000000000..072299ac2ef
--- /dev/null
+++ b/maps/submaps/cave_submaps/deadBeacon.dmm
@@ -0,0 +1,62 @@
+"a" = (/turf/template_noop,/area/template_noop)
+"b" = (/turf/simulated/mineral/floor,/area/submap/cave/deadBeacon)
+"c" = (/obj/structure/loot_pile/maint/junk,/turf/simulated/mineral/floor,/area/submap/cave/deadBeacon)
+"d" = (/turf/simulated/wall/r_wall,/area/submap/cave/deadBeacon)
+"e" = (/obj/structure/grille,/obj/structure/window/reinforced{dir = 1},/obj/structure/window/reinforced{dir = 8},/obj/structure/window/reinforced,/turf/simulated/floor/tiled/asteroid_steel,/area/submap/cave/deadBeacon)
+"f" = (/obj/structure/grille,/obj/structure/window/reinforced,/turf/simulated/floor/tiled/asteroid_steel,/area/submap/cave/deadBeacon)
+"g" = (/turf/simulated/floor/plating,/area/submap/cave/deadBeacon)
+"h" = (/turf/simulated/floor/airless{icon_state = "asteroidplating2"},/area/submap/cave/deadBeacon)
+"i" = (/obj/structure/grille/broken,/turf/simulated/floor/plating,/area/submap/cave/deadBeacon)
+"j" = (/obj/structure/table/steel,/turf/simulated/floor/tiled/asteroid_steel,/area/submap/cave/deadBeacon)
+"k" = (/obj/structure/loot_pile/maint/technical,/turf/simulated/floor/tiled/asteroid_steel,/area/submap/cave/deadBeacon)
+"l" = (/obj/item/weapon/material/shard,/turf/simulated/floor/plating,/area/submap/cave/deadBeacon)
+"m" = (/obj/structure/table/steel,/obj/item/weapon/circuitboard/comm_server,/obj/machinery/light/built{dir = 8; fitting = ""},/turf/simulated/floor/tiled/asteroid_steel,/area/submap/cave/deadBeacon)
+"n" = (/turf/simulated/floor/tiled/asteroid_steel,/area/submap/cave/deadBeacon)
+"o" = (/obj/item/weapon/paper/crumpled{info = "Sampatti Relay Sif-833
Decryption Key for 12-04-2488:
849B0022FBA920C244
Eyes Only.
The insider who knows all the secrets can bring down Lanka."; name = "Dusty Note"},/turf/simulated/floor/tiled/asteroid_steel,/area/submap/cave/deadBeacon)
+"p" = (/obj/structure/door_assembly/door_assembly_ext,/turf/simulated/floor/tiled/asteroid_steel,/area/submap/cave/deadBeacon)
+"q" = (/obj/item/stack/rods,/turf/simulated/floor/tiled/asteroid_steel,/area/submap/cave/deadBeacon)
+"r" = (/obj/machinery/telecomms/relay{active_power_usage = 1; broadcasting = 0; panel_open = 1},/obj/structure/cable{icon_state = "0-2"; pixel_y = 1; d2 = 2},/turf/simulated/floor/tiled/asteroid_steel,/area/submap/cave/deadBeacon)
+"s" = (/obj/machinery/telecomms/broadcaster{light_power = 0; on = 0},/turf/simulated/floor/tiled/asteroid_steel,/area/submap/cave/deadBeacon)
+"t" = (/obj/structure/grille,/obj/structure/window/reinforced{dir = 8},/obj/structure/window/reinforced{dir = 4},/turf/simulated/floor/tiled/asteroid_steel,/area/submap/cave/deadBeacon)
+"u" = (/obj/machinery/telecomms/receiver{light_power = 0; on = 0},/obj/structure/cable,/turf/simulated/floor/tiled/asteroid_steel,/area/submap/cave/deadBeacon)
+"v" = (/obj/item/weapon/circuitboard/broken,/turf/simulated/floor/tiled/asteroid_steel,/area/submap/cave/deadBeacon)
+"w" = (/obj/effect/decal/cleanable/blood/oil,/turf/simulated/floor/tiled/asteroid_steel,/area/submap/cave/deadBeacon)
+"x" = (/obj/structure/grille,/obj/structure/window/reinforced{dir = 4},/obj/structure/window/reinforced{dir = 8},/turf/simulated/floor/tiled/asteroid_steel,/area/submap/cave/deadBeacon)
+"y" = (/obj/effect/decal/remains/robot,/obj/effect/decal/cleanable/blood/oil,/turf/simulated/floor/tiled/asteroid_steel,/area/submap/cave/deadBeacon)
+"z" = (/obj/item/stack/cable_coil{amount = 1},/turf/simulated/floor/tiled/asteroid_steel,/area/submap/cave/deadBeacon)
+"A" = (/obj/item/weapon/circuitboard/broken,/turf/simulated/mineral/floor,/area/submap/cave/deadBeacon)
+"B" = (/obj/structure/grille/broken,/obj/structure/window/reinforced{dir = 4},/turf/simulated/floor/plating,/area/submap/cave/deadBeacon)
+"C" = (/obj/structure/loot_pile/maint/junk,/turf/simulated/floor/plating,/area/submap/cave/deadBeacon)
+"D" = (/obj/item/weapon/cigbutt,/obj/item/weapon/wrench,/obj/machinery/light/built,/turf/simulated/floor/tiled/asteroid_steel,/area/submap/cave/deadBeacon)
+"E" = (/obj/item/weapon/material/shard,/turf/simulated/floor/tiled/asteroid_steel,/area/submap/cave/deadBeacon)
+"F" = (/obj/machinery/recharge_station,/turf/simulated/floor/tiled/asteroid_steel,/area/submap/cave/deadBeacon)
+"G" = (/obj/structure/grille,/obj/structure/window/reinforced{dir = 4},/obj/structure/window/reinforced{dir = 8},/obj/structure/window/reinforced,/turf/simulated/floor/tiled/asteroid_steel,/area/submap/cave/deadBeacon)
+"H" = (/obj/machinery/door/airlock/external,/turf/simulated/floor/tiled/asteroid_steel,/area/submap/cave/deadBeacon)
+"I" = (/obj/machinery/access_button/airlock_interior{dir = 4},/turf/simulated/wall/r_wall,/area/submap/cave/deadBeacon)
+"J" = (/obj/structure/grille/broken,/obj/item/stack/rods,/turf/simulated/floor/plating,/area/submap/cave/deadBeacon)
+"K" = (/obj/structure/girder,/turf/simulated/floor/plating,/area/submap/cave/deadBeacon)
+"L" = (/obj/structure/sign/warning/secure_area,/turf/simulated/wall/r_wall,/area/submap/cave/deadBeacon)
+"M" = (/obj/structure/sign/warning/high_voltage,/turf/simulated/wall/r_wall,/area/submap/cave/deadBeacon)
+
+(1,1,1) = {"
+aaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaabbaaaaaaaa
+aaaaaabbabbcbaaaaaaa
+aaaaaadefgghidaaaaaa
+aaaaaahjkgglhibaaaaa
+aaaaahdmnoggggbaaaaa
+aaaabnpqnrsgqtbaaaaa
+aaaabngnnuvwnxaaaaaa
+aaaabhdgynnzkxbaaaaa
+aaaaAbBCDnnEFGbaaaaa
+aaaaaadidHHIJdbaaaaa
+aaaaaaabdgnKbbaaaaaa
+aaaaaaaaLHHMaaaaaaaa
+aaaaaaaabbbAaaaaaaaa
+aaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaa
+"}
diff --git a/maps/submaps/surface_submaps/farm1.dmm b/maps/submaps/surface_submaps/farm1.dmm
new file mode 100644
index 00000000000..a89d481737f
--- /dev/null
+++ b/maps/submaps/surface_submaps/farm1.dmm
@@ -0,0 +1,78 @@
+"a" = (/turf/template_noop,/area/template_noop)
+"b" = (/turf/simulated/floor/outdoors/dirt,/area/submap/farm1)
+"c" = (/obj/structure/railing,/turf/simulated/floor/outdoors/dirt,/area/submap/farm1)
+"d" = (/obj/structure/railing{tag = "icon-railing0 (EAST)"; icon_state = "railing0"; dir = 4},/turf/simulated/floor/outdoors/dirt,/area/submap/farm1)
+"e" = (/turf/simulated/floor/outdoors/grass/sif,/area/submap/farm1)
+"f" = (/obj/structure/railing{tag = "icon-railing0 (WEST)"; icon_state = "railing0"; dir = 8},/turf/simulated/floor/outdoors/dirt,/area/submap/farm1)
+"g" = (/turf/simulated/wall/wood,/area/submap/farm1)
+"h" = (/obj/structure/grille/rustic,/obj/structure/window/reinforced/full,/turf/simulated/floor/plating,/area/submap/farm1)
+"i" = (/obj/structure/closet/secure_closet/freezer/fridge,/turf/simulated/floor/wood,/area/submap/farm1)
+"j" = (/turf/simulated/floor/wood,/area/submap/farm1)
+"k" = (/obj/structure/table/marble,/turf/simulated/floor/wood,/area/submap/farm1)
+"l" = (/obj/structure/table/marble,/obj/item/weapon/material/kitchen/rollingpin,/turf/simulated/floor/wood,/area/submap/farm1)
+"m" = (/obj/machinery/portable_atmospherics/hydroponics/soil,/obj/item/seeds/cornseed,/turf/simulated/floor/outdoors/dirt,/area/submap/farm1)
+"n" = (/obj/item/weapon/material/minihoe,/turf/simulated/floor/outdoors/dirt,/area/submap/farm1)
+"o" = (/obj/structure/table/marble,/obj/item/weapon/material/kitchen/utensil/knife,/turf/simulated/floor/wood,/area/submap/farm1)
+"p" = (/obj/machinery/portable_atmospherics/hydroponics/soil,/obj/item/seeds/bluetomatoseed,/turf/simulated/floor/outdoors/dirt,/area/submap/farm1)
+"q" = (/turf/simulated/floor/outdoors/mud,/area/submap/farm1)
+"r" = (/obj/machinery/portable_atmospherics/hydroponics/soil,/obj/item/seeds/icepepperseed,/turf/simulated/floor/outdoors/dirt,/area/submap/farm1)
+"s" = (/obj/structure/simple_door/wood,/turf/simulated/floor/wood,/area/submap/farm1)
+"t" = (/mob/living/bot/farmbot,/turf/simulated/floor/outdoors/dirt,/area/submap/farm1)
+"u" = (/obj/structure/sink/puddle,/turf/simulated/floor/outdoors/mud,/area/submap/farm1)
+"v" = (/obj/item/weapon/material/hatchet,/turf/simulated/floor/outdoors/mud,/area/submap/farm1)
+"w" = (/obj/structure/table/woodentable,/obj/item/weapon/storage/box/matches,/obj/item/weapon/flame/match,/turf/simulated/floor/wood,/area/submap/farm1)
+"x" = (/obj/structure/table/woodentable,/turf/simulated/floor/wood,/area/submap/farm1)
+"y" = (/obj/item/clothing/shoes/boots/winter/hydro,/obj/item/clothing/suit/storage/hooded/wintercoat/hydro,/turf/simulated/floor/wood,/area/submap/farm1)
+"z" = (/obj/structure/bed/chair/wood{tag = "icon-wooden_chair (WEST)"; icon_state = "wooden_chair"; dir = 8},/turf/simulated/floor/wood,/area/submap/farm1)
+"A" = (/obj/item/weapon/reagent_containers/glass/bucket,/turf/simulated/floor/outdoors/dirt,/area/submap/farm1)
+"B" = (/obj/structure/table/woodentable,/obj/item/weapon/storage/fancy/candle_box,/turf/simulated/floor/wood,/area/submap/farm1)
+"C" = (/obj/machinery/portable_atmospherics/hydroponics/soil,/obj/item/seeds/wheatseed,/turf/simulated/floor/outdoors/dirt,/area/submap/farm1)
+"D" = (/obj/structure/closet/crate/bin,/turf/simulated/floor/wood,/area/submap/farm1)
+"E" = (/obj/machinery/space_heater,/turf/simulated/floor/wood,/area/submap/farm1)
+"F" = (/obj/structure/bookcase,/obj/item/weapon/book/manual/hydroponics_pod_people,/turf/simulated/floor/wood,/area/submap/farm1)
+"G" = (/obj/structure/bed/padded,/obj/item/weapon/bedsheet/blue,/turf/simulated/floor/wood,/area/submap/farm1)
+"H" = (/obj/structure/table/woodentable,/obj/item/trash/candle,/turf/simulated/floor/wood,/area/submap/farm1)
+"I" = (/turf/simulated/floor/outdoors/rocks,/area/submap/farm1)
+"J" = (/turf/simulated/floor/plating,/area/submap/farm1)
+"K" = (/turf/simulated/floor/water,/area/submap/farm1)
+"L" = (/obj/structure/loot_pile/maint/technical,/turf/simulated/floor/plating,/area/submap/farm1)
+"M" = (/obj/machinery/power/port_gen/pacman,/turf/simulated/floor/plating,/area/submap/farm1)
+"N" = (/obj/structure/closet/crate/hydroponics/prespawned,/turf/simulated/floor/plating,/area/submap/farm1)
+"O" = (/obj/structure/table/steel,/obj/machinery/cell_charger,/turf/simulated/floor/plating,/area/submap/farm1)
+"P" = (/obj/structure/table/steel,/turf/simulated/floor/plating,/area/submap/farm1)
+"Q" = (/obj/structure/railing{tag = "icon-railing0 (NORTH)"; icon_state = "railing0"; dir = 1},/turf/simulated/floor/outdoors/dirt,/area/submap/farm1)
+
+(1,1,1) = {"
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+abccccccccccccccccccccccccbaaaaa
+adeeeeeeeeeeeeeeeeeeeeeeeefaaaaa
+adeeeeeeeeeeeeeeeeeeeeeeeefaaaaa
+adeegghhggeeeeeeeeeeeeeeeefaaaaa
+adeegijklgeeeeemmmmmmmmmeefaaaaa
+adeegjjjkheeeeebnbbbbbbbeefaaaaa
+adeegjjjogebbeepppqqqrrreefaaaaa
+adegggsgggebbbbtbbquvbbbeefaaaaa
+adegwxjygeeebbepppqqqrrreefaaaaa
+adehxzjjgggebeebbAbbbbbbeefaaaaa
+adehBjjjsjsbbeeCCCCCCCCCeefaaaaa
+adegDjjEgggebeeeeeeeeeeeeefaaaaa
+adeggsgggeeebeeeeeeeeeeeeefaaaaa
+adegFjjGgeebbbeeeeebbbbbbbbbbbba
+adegEjjHgeebbbbbbbbbbbbbbbbbbbba
+adeggggggeebeeeeeeebbbbbbbbbbbba
+adeebbbbbbbbeeeeeeebbbeeeefaaaaa
+adebbIIIIIIbbeeegggJJJgggefaaaaa
+adebIIKKKKIIbbeegLJJJJJLgefaaaaa
+adebIKKKKKKIIbbehMJJJJJJhefaaaaa
+adebIIKKKKKKIIbehLJJJJJLhefaaaaa
+adebbIIKKKKKKIbehNJJJJJJhefaaaaa
+adeebbIIKKKKIIbegLJOPPJLgefaaaaa
+adeeebbIIIIIIbbegggggggggefaaaaa
+adeeeebbbbbbbbeeeeeeeeeeeefaaaaa
+adeeeeeeeeeeeeeeeeeeeeeeeefaaaaa
+abQQQQQQQQQQQQQQQQQQQQQQQQbaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+"}
diff --git a/maps/submaps/surface_submaps/forest.dm b/maps/submaps/surface_submaps/forest.dm
index dd02c1b2043..be13e4f9475 100644
--- a/maps/submaps/surface_submaps/forest.dm
+++ b/maps/submaps/surface_submaps/forest.dm
@@ -2,4 +2,9 @@
name = "Surface Content"
desc = "Used to make the surface by 17% less boring."
-// To be added: Templates for surface exploration when they are made.
\ No newline at end of file
+// To be added: Templates for surface exploration when they are made.
+
+/datum/map_template/surface/farm1
+ name = "Farm 1"
+ desc = "A small farm tended by a farmbot."
+ mappath = 'maps/submaps/surface_submaps/farm1.dmm'
\ No newline at end of file
diff --git a/maps/submaps/surface_submaps/forest_areas.dm b/maps/submaps/surface_submaps/forest_areas.dm
new file mode 100644
index 00000000000..f8fe110cb0f
--- /dev/null
+++ b/maps/submaps/surface_submaps/forest_areas.dm
@@ -0,0 +1,6 @@
+/area/submap
+ name = "Submap Area"
+ icon_state = "submap"
+
+/area/submap/farm1
+ name = "farm"
\ No newline at end of file
diff --git a/polaris.dme b/polaris.dme
index 495438c25a5..179a3f6b6d7 100644
--- a/polaris.dme
+++ b/polaris.dme
@@ -922,6 +922,7 @@
#include "code\game\objects\items\weapons\material\ashtray.dm"
#include "code\game\objects\items\weapons\material\bats.dm"
#include "code\game\objects\items\weapons\material\foam.dm"
+#include "code\game\objects\items\weapons\material\gravemarker.dm"
#include "code\game\objects\items\weapons\material\kitchen.dm"
#include "code\game\objects\items\weapons\material\knives.dm"
#include "code\game\objects\items\weapons\material\material_armor.dm"
@@ -967,6 +968,7 @@
#include "code\game\objects\structures\flora.dm"
#include "code\game\objects\structures\ghost_pods.dm"
#include "code\game\objects\structures\girders.dm"
+#include "code\game\objects\structures\gravemarker.dm"
#include "code\game\objects\structures\grille.dm"
#include "code\game\objects\structures\inflatable.dm"
#include "code\game\objects\structures\janicart.dm"
@@ -1840,6 +1842,7 @@
#include "code\modules\organs\subtypes\diona.dm"
#include "code\modules\organs\subtypes\machine.dm"
#include "code\modules\organs\subtypes\seromi.dm"
+#include "code\modules\organs\subtypes\slime.dm"
#include "code\modules\organs\subtypes\standard.dm"
#include "code\modules\organs\subtypes\unathi.dm"
#include "code\modules\organs\subtypes\unbreakable.dm"
@@ -1957,6 +1960,7 @@
#include "code\modules\projectiles\guns\projectile\dartgun.dm"
#include "code\modules\projectiles\guns\projectile\pistol.dm"
#include "code\modules\projectiles\guns\projectile\revolver.dm"
+#include "code\modules\projectiles\guns\projectile\semiauto.dm"
#include "code\modules\projectiles\guns\projectile\shotgun.dm"
#include "code\modules\projectiles\guns\projectile\sniper.dm"
#include "code\modules\projectiles\guns\projectile\sniper\collapsible_sniper.dm"
@@ -2267,7 +2271,9 @@
#include "maps\northern_star\northern_star.dm"
#include "maps\submaps\_readme.dm"
#include "maps\submaps\cave_submaps\cave.dm"
+#include "maps\submaps\cave_submaps\cave_areas.dm"
#include "maps\submaps\space_submaps\space.dm"
#include "maps\submaps\surface_submaps\forest.dm"
+#include "maps\submaps\surface_submaps\forest_areas.dm"
#include "maps\~map_system\maps.dm"
// END_INCLUDE
diff --git a/sound/weapons/garand_ping.ogg b/sound/weapons/garand_ping.ogg
new file mode 100644
index 00000000000..187495def0f
Binary files /dev/null and b/sound/weapons/garand_ping.ogg differ