diff --git a/code/__DEFINES/~skyrat_defines/gun.dm b/code/__DEFINES/~skyrat_defines/gun.dm
index 6d2d4adcbaa..8450fd5c61f 100644
--- a/code/__DEFINES/~skyrat_defines/gun.dm
+++ b/code/__DEFINES/~skyrat_defines/gun.dm
@@ -18,3 +18,4 @@
#define COMPANY_JARNSMIOUR (1<<13)
#define COMPANY_ABDUCTOR (1<<14)
#define COMPANY_REMOVED (1<<15)
+#define COMPANY_ROMULUS (1<<16)
diff --git a/code/__DEFINES/~~bubber_defines/status_indicator_defines.dm b/code/__DEFINES/~~bubber_defines/status_indicator_defines.dm
new file mode 100644
index 00000000000..57abd103b0d
--- /dev/null
+++ b/code/__DEFINES/~~bubber_defines/status_indicator_defines.dm
@@ -0,0 +1,11 @@
+#define STUNNED "stunned"
+#define WEAKEN "weakened"
+#define PARALYSIS "paralysis"
+#define SLEEPING "sleeping"
+#define CONFUSED "confused"
+#define PLANE_STATUS_INDICATOR -12 //Status Indicators that show over mobs' heads when certain things like stuns affect them.
+#define STATUS_LAYER -2.1
+#define STATUS_INDICATOR_Y_OFFSET 2 // Offset from the edge of the icon sprite, so 32 pixels plus whatever number is here.
+#define STATUS_INDICATOR_ICON_X_SIZE 0 // Don't need to care about the Y size due to the origin being on the bottom side.
+#define STATUS_INDICATOR_ICON_MARGIN 0 // The space between two status indicators. We don't do this with the current icons.
+#define DEFAULT_MOB_SCALE 1
diff --git a/code/game/objects/items/melee/baton.dm b/code/game/objects/items/melee/baton.dm
index 4305e986c6e..85fea1f4649 100644
--- a/code/game/objects/items/melee/baton.dm
+++ b/code/game/objects/items/melee/baton.dm
@@ -385,21 +385,18 @@
/obj/item/melee/baton/security
name = "stun baton"
- desc = "A stun baton for incapacitating people with."
- desc_controls = "Left click to stun, right click to harm."
+ desc = "A stun baton for incapacitating people with. Left click to stun, right click to harm."
+
icon_state = "stunbaton"
inhand_icon_state = "baton"
worn_icon_state = "baton"
force = 10
- wound_bonus = 0
attack_verb_continuous = list("beats")
attack_verb_simple = list("beat")
- armor_type = /datum/armor/baton_security
-
throwforce = 7
- stamina_damage = 35 // SKYRAT EDIT - 4 baton crit now (Original: 45)
+ stamina_damage = 60
knockdown_time = 5 SECONDS
clumsy_knockdown_time = 15 SECONDS
cooldown = 2.5 SECONDS
@@ -416,11 +413,6 @@
var/can_remove_cell = TRUE
var/convertible = TRUE //if it can be converted with a conversion kit
-/datum/armor/baton_security
- bomb = 50
- fire = 80
- acid = 80
-
/obj/item/melee/baton/security/Initialize(mapload)
. = ..()
if(preload_cell_type)
@@ -428,20 +420,20 @@
log_mapping("[src] at [AREACOORD(src)] had an invalid preload_cell_type: [preload_cell_type].")
else
cell = new preload_cell_type(src)
- RegisterSignal(src, COMSIG_PARENT_ATTACKBY, PROC_REF(convert))
+ RegisterSignal(src, COMSIG_PARENT_ATTACKBY, .proc/convert)
update_appearance()
/obj/item/melee/baton/security/get_cell()
return cell
-/obj/item/melee/baton/security/suicide_act(mob/living/user)
+/obj/item/melee/baton/security/suicide_act(mob/user)
if(cell?.charge && active)
user.visible_message(span_suicide("[user] is putting the live [name] in [user.p_their()] mouth! It looks like [user.p_theyre()] trying to commit suicide!"))
+ . = (FIRELOSS)
attack(user, user)
- return FIRELOSS
else
user.visible_message(span_suicide("[user] is shoving the [name] down their throat! It looks like [user.p_theyre()] trying to commit suicide!"))
- return OXYLOSS
+ . = (OXYLOSS)
/obj/item/melee/baton/security/Destroy()
if(cell)
@@ -577,12 +569,12 @@
* After a period of time, we then check to see what stun duration we give.
*/
/obj/item/melee/baton/security/additional_effects_non_cyborg(mob/living/target, mob/living/user)
- target.set_jitter_if_lower(40 SECONDS)
- // target.set_confusion_if_lower(10 SECONDS) // SKYRAT EDIT REMOVAL
- target.set_stutter_if_lower(16 SECONDS)
+ target.set_timed_status_effect(40 SECONDS, /datum/status_effect/jitter, only_if_higher = TRUE)
+ target.set_timed_status_effect(10 SECONDS, /datum/status_effect/confusion, only_if_higher = TRUE)
+ target.set_timed_status_effect(16 SECONDS, /datum/status_effect/speech/stutter, only_if_higher = TRUE)
SEND_SIGNAL(target, COMSIG_LIVING_MINOR_SHOCK)
- addtimer(CALLBACK(src, PROC_REF(apply_stun_effect_end), target), 2 SECONDS)
+ addtimer(CALLBACK(src, .proc/apply_stun_effect_end, target), 2 SECONDS)
/// After the initial stun period, we check to see if the target needs to have the stun applied.
/obj/item/melee/baton/security/proc/apply_stun_effect_end(mob/living/target)
@@ -590,8 +582,7 @@
if(!target.IsKnockdown())
to_chat(target, span_warning("Your muscles seize, making you collapse[trait_check ? ", but your body quickly recovers..." : "!"]"))
- if(!trait_check)
- target.Knockdown(knockdown_time)
+ target.Knockdown(knockdown_time * (trait_check ? 0.1 : 1))
/obj/item/melee/baton/security/get_wait_description()
return span_danger("The baton is still charging!")
@@ -624,7 +615,7 @@
scramble_mode()
for(var/loops in 1 to rand(6, 12))
scramble_time = rand(5, 15) / (1 SECONDS)
- addtimer(CALLBACK(src, PROC_REF(scramble_mode)), scramble_time*loops * (1 SECONDS))
+ addtimer(CALLBACK(src, .proc/scramble_mode), scramble_time*loops * (1 SECONDS))
/obj/item/melee/baton/security/proc/scramble_mode()
if (!cell || cell.charge < cell_hit_cost)
diff --git a/code/modules/jobs/job_types/captain.dm b/code/modules/jobs/job_types/captain.dm
index afcc3fc2997..bd2dd916d58 100755
--- a/code/modules/jobs/job_types/captain.dm
+++ b/code/modules/jobs/job_types/captain.dm
@@ -70,7 +70,7 @@
gloves = /obj/item/clothing/gloves/captain
head = /obj/item/clothing/head/hats/caphat
shoes = /obj/item/clothing/shoes/laceup
-
+ r_pocket = /obj/item/flashlight/seclite
backpack = /obj/item/storage/backpack/captain
satchel = /obj/item/storage/backpack/satchel/cap
diff --git a/code/modules/jobs/job_types/detective.dm b/code/modules/jobs/job_types/detective.dm
index 4b44a3a4ae2..04503ab596a 100644
--- a/code/modules/jobs/job_types/detective.dm
+++ b/code/modules/jobs/job_types/detective.dm
@@ -56,6 +56,7 @@
/obj/item/detective_scanner = 1,
/obj/item/melee/baton = 1,
/obj/item/storage/box/evidence = 1,
+ /obj/item/flashlight/seclite = 1,
)
belt = /obj/item/modular_computer/pda/detective
ears = /obj/item/radio/headset/headset_sec/alt
diff --git a/code/modules/jobs/job_types/head_of_security.dm b/code/modules/jobs/job_types/head_of_security.dm
index 79294563a48..5a3ffbaae94 100644
--- a/code/modules/jobs/job_types/head_of_security.dm
+++ b/code/modules/jobs/job_types/head_of_security.dm
@@ -51,12 +51,14 @@
id_trim = /datum/id_trim/job/head_of_security
uniform = /obj/item/clothing/under/rank/security/head_of_security
suit = /obj/item/clothing/suit/armor/hos/trenchcoat
- //suit_store = /obj/item/gun/energy/e_gun //SKYRAT EDIT REMOVAL
+ suit_store = /obj/item/gun/energy/e_gun //KEPLER EDIT RESTORATION
backpack_contents = list(
/obj/item/evidencebag = 1,
- /obj/item/storage/box/gunset/glock18_hos = 1, //SKYRAT EDIT ADDITION
+ /obj/item/flashlight/seclite = 1,
+ /obj/item/modular_computer/pda/heads/hos = 1,
+ /obj/item/choice_beacon/head_of_security = 1,
)
- belt = /obj/item/modular_computer/pda/heads/hos
+ belt = /obj/item/storage/belt/security/full
ears = /obj/item/radio/headset/heads/hos/alt
glasses = /obj/item/clothing/glasses/hud/security/sunglasses
gloves = /obj/item/clothing/gloves/color/black/security //SKYRAT EDIT CHANGE - Original: /obj/item/clothing/gloves/color/black
@@ -85,3 +87,53 @@
head = null
mask = /obj/item/clothing/mask/gas/sechailer
internals_slot = ITEM_SLOT_SUITSTORE
+
+//TEST THIS OUT WHEN NEEDED
+
+/obj/item/choice_beacon/head_of_security
+ name = "gun choice beacon"
+ desc = "whatever you choose will determine the outcome of space station 13 and the fate of the company so choose wisely."
+ company_source = "Romulus Shipping Company"
+ company_message = span_bold("Copy that SS13, supply pod enroute!")
+
+
+/obj/item/choice_beacon/head_of_security/generate_display_names()
+ var/static/list/hosgun_list
+ if(!hosgun_list)
+ hosgun_list = list()
+ for(var/obj/item/storage/box/hosgun/box as anything in typesof(/obj/item/storage/box/hosgun))
+ hosgun_list[initial(box.name)] = box
+ return hosgun_list
+
+/obj/item/storage/box/hosgun
+ name = "Classic 3-round burst pistol 9mm"
+
+/obj/item/storage/box/hosgun/PopulateContents()
+ new /obj/item/storage/box/gunset/glock18_hos(src)
+ new /obj/item/ammo_box/c9mm(src)
+ new /obj/item/ammo_box/c9mm(src)
+ new /obj/item/storage/box/hecu_rations(src)
+ new /obj/item/storage/fancy/cigarettes/cigars(src)
+
+/obj/item/storage/box/hosgun/revolver
+ name = "Romulus Officer Heavy Revolver .460"
+
+/obj/item/storage/box/hosgun/revolver/PopulateContents()
+ new /obj/item/storage/box/gunset/hos_revolver(src)
+ new /obj/item/clothing/neck/cloak/hos/redsec(src)
+ new /obj/item/clothing/under/rank/security/head_of_security/redsec(src)
+ new /obj/item/clothing/glasses/hud/security/sunglasses/eyepatch/redsec(src)
+ new /obj/item/clothing/shoes/jackboots/sec/redsec(src)
+ new /obj/item/storage/box/nri_rations(src)
+ new /obj/item/knife/combat(src)
+
+/obj/item/storage/box/hosgun/glock
+ name = "Solaris Police Dual 9mm Pistol"
+
+/obj/item/storage/box/hosgun/glock/PopulateContents()
+ new /obj/item/storage/box/gunset/glock17(src)
+ new /obj/item/storage/box/gunset/glock17(src)
+ new /obj/item/clothing/under/rank/security/head_of_security/peacekeeper/sol(src)
+ new /obj/item/clothing/neck/tie/red(src)
+ new /obj/item/storage/pill_bottle/probital(src)
+
diff --git a/code/modules/jobs/job_types/security_officer.dm b/code/modules/jobs/job_types/security_officer.dm
index 47ce1982604..02659b2bf25 100644
--- a/code/modules/jobs/job_types/security_officer.dm
+++ b/code/modules/jobs/job_types/security_officer.dm
@@ -209,8 +209,10 @@ GLOBAL_LIST_EMPTY(security_officer_distribution)
suit_store = /obj/item/gun/energy/disabler
backpack_contents = list(
/obj/item/evidencebag = 1,
+ /obj/item/flashlight/seclite = 1,
+ /obj/item/modular_computer/pda/security = 1,
)
- belt = /obj/item/modular_computer/pda/security
+ belt = /obj/item/storage/belt/security/full
ears = /obj/item/radio/headset/headset_sec/alt
gloves = /obj/item/clothing/gloves/color/black/security //SKYRAT EDIT CHANGE - Original: /obj/item/clothing/gloves/color/black
head = /obj/item/clothing/head/security_garrison //SKYRAT EDIT CHANGE - Original: /obj/item/clothing/head/helmet/sec
diff --git a/code/modules/jobs/job_types/warden.dm b/code/modules/jobs/job_types/warden.dm
index f0e8f0cdc93..aa253eb4fbb 100644
--- a/code/modules/jobs/job_types/warden.dm
+++ b/code/modules/jobs/job_types/warden.dm
@@ -53,8 +53,11 @@
suit_store = /obj/item/gun/energy/disabler
backpack_contents = list(
/obj/item/evidencebag = 1,
+ /obj/item/modular_computer/pda/warden = 1,
+ /obj/item/flashlight/seclite = 1,
+ /obj/item/storage/box/gunset/glock17 = 1,
)
- belt = /obj/item/modular_computer/pda/warden
+ belt = /obj/item/storage/belt/security/full
ears = /obj/item/radio/headset/headset_sec/alt
glasses = /obj/item/clothing/glasses/hud/security/sunglasses
gloves = /obj/item/clothing/gloves/color/black/security //SKYRAT EDIT CHANGE - Original: /obj/item/clothing/gloves/color/black
diff --git a/code/modules/projectiles/guns/energy/stun.dm b/code/modules/projectiles/guns/energy/stun.dm
index 4e7552f4771..9278d59ff83 100644
--- a/code/modules/projectiles/guns/energy/stun.dm
+++ b/code/modules/projectiles/guns/energy/stun.dm
@@ -30,7 +30,7 @@
desc = "A self-defense weapon that exhausts organic targets, weakening them until they collapse."
icon_state = "disabler"
inhand_icon_state = null
- ammo_type = list(/obj/item/ammo_casing/energy/disabler/skyrat) // SKYRAT EDIT: ammo_type = list(/obj/item/ammo_casing/energy/disabler)
+ ammo_type = list(/obj/item/ammo_casing/energy/disabler)
ammo_x_offset = 2
cell_type = /obj/item/stock_parts/cell/super // SKYRAT EDIT ADDITION
diff --git a/code/modules/research/machinery/_production.dm b/code/modules/research/machinery/_production.dm
index c39261512c5..7c043b545b7 100644
--- a/code/modules/research/machinery/_production.dm
+++ b/code/modules/research/machinery/_production.dm
@@ -287,35 +287,7 @@
say("Not enough reagents to complete prototype[print_quantity > 1? "s" : ""].")
return FALSE
- // Charge the lathe tax at least once per ten items.
- var/total_cost = LATHE_TAX * max(round(print_quantity / 10), 1)
-
- if(!charges_tax)
- total_cost = 0
-
- if(isliving(usr))
- var/mob/living/user = usr
- var/obj/item/card/id/card = user.get_idcard(TRUE)
-
- if(!card && istype(user.pulling, /obj/item/card/id))
- card = user.pulling
-
- if(card && card.registered_account)
- var/datum/bank_account/our_acc = card.registered_account
- if(our_acc.account_job.departments_bitflags & allowed_department_flags)
- total_cost = 0 // We are not charging crew for printing their own supplies and equipment.
-
- if(attempt_charge(src, usr, total_cost) & COMPONENT_OBJ_CANCEL_CHARGE)
- say("Insufficient funds to complete prototype. Please present a holochip or valid ID card.")
- return FALSE
-
- if(iscyborg(usr))
- var/mob/living/silicon/robot/borg = usr
-
- if(!borg.cell)
- return FALSE
-
- borg.cell.use(SILICON_LATHE_TAX)
+ lathe_tax()
materials.mat_container.use_materials(efficient_mats, print_quantity)
materials.silo_log(src, "built", -print_quantity, "[design.name]", efficient_mats)
diff --git a/config/game_options.txt b/config/game_options.txt
index e72fc3af8c4..4c113a217ce 100644
--- a/config/game_options.txt
+++ b/config/game_options.txt
@@ -551,6 +551,10 @@ MAXFINE 2000
## Whether native FoV is enabled for all people.
#NATIVE_FOV
+## How much does the protolathe cost to use on station? Disabled is off.
+
+##PROTOLATHE_TAX 10
+
## Whether circuit sounds are allowed to be played or not.
#DISALLOW_CIRCUIT_SOUNDS
diff --git a/html/changelogs/AutoChangeLog-pr-189.yml b/html/changelogs/AutoChangeLog-pr-189.yml
new file mode 100644
index 00000000000..280ad21bb6b
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-189.yml
@@ -0,0 +1,4 @@
+author: "nevimer"
+delete-after: True
+changes:
+ - config: "Lathe tax is now a config option"
\ No newline at end of file
diff --git a/html/changelogs/AutoChangeLog-pr-190.yml b/html/changelogs/AutoChangeLog-pr-190.yml
new file mode 100644
index 00000000000..2f3fbe9bedb
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-190.yml
@@ -0,0 +1,4 @@
+author: "[nevimer](https://github.com/nevimer), [AtoriBirb](https://github.com/AtoriBirb)"
+delete-after: True
+changes:
+ - rscadd: "Status Indicators! Toggle in preferences!"
\ No newline at end of file
diff --git a/modular_skyrat/master_files/code/modules/projectiles/guns/gun.dm b/modular_skyrat/master_files/code/modules/projectiles/guns/gun.dm
index c7787f8c33f..04c76957ebf 100644
--- a/modular_skyrat/master_files/code/modules/projectiles/guns/gun.dm
+++ b/modular_skyrat/master_files/code/modules/projectiles/guns/gun.dm
@@ -215,6 +215,9 @@
. += "
It has [span_abductor("✌︎︎♌︎︎♎︎︎◆︎︎♍︎︎⧫︎︎❄︎♏︎♍︎♒︎")] engraved into the photon accelerator."
if(COMPANY_REMOVED)
. += "
It has had [span_grey("all identifying marks scrubbed off")]."
+ if(COMPANY_ROMULUS)
+ . += "
It has [span_blue("Romulus Technology")] etched into the barrel."
+
/obj/item/gun/proc/fire_select()
var/mob/living/carbon/human/user = usr
diff --git a/modular_skyrat/master_files/code/modules/research/techweb/protolathe.dm b/modular_skyrat/master_files/code/modules/research/techweb/protolathe.dm
new file mode 100644
index 00000000000..80998cf3216
--- /dev/null
+++ b/modular_skyrat/master_files/code/modules/research/techweb/protolathe.dm
@@ -0,0 +1,29 @@
+/obj/machinery/rnd/production
+ var/total_cost = 0
+ var/on_station_lathe = TRUE
+ var/free_lathe = FALSE
+
+/obj/machinery/rnd/production/proc/lathe_tax()
+ total_cost ? (free_lathe ? 0 : total_cost) : (CONFIG_GET(number/protolathe_tax))
+
+ if(is_station_level(z) && on_station_lathe && total_cost && !free_lathe)
+ var/mob/living/user = usr
+ var/obj/item/card/id/card = user.get_idcard(TRUE)
+ if(!card && istype(user.pulling, /obj/item/card/id))
+ card = user.pulling
+ if(card)
+ var/datum/bank_account/our_acc = card.registered_account
+ if(our_acc.account_job && SSeconomy.get_dep_account(our_acc.account_job?.paycheck_department) == SSeconomy.get_dep_account(payment_department))
+ total_cost = 0 //We are not charging crew for printing their own supplies and equipment.
+ if(!iscarbon(usr)) // catch all cyborg types
+ total_cost = 0
+ if(attempt_charge(src, usr, total_cost) & COMPONENT_OBJ_CANCEL_CHARGE)
+ return FALSE
+
+/obj/machinery/rnd/production/protolathe/offstation
+ on_station_lathe = FALSE
+
+/datum/config_entry/number/protolathe_tax
+ default = 0
+ min_val = 0
+ max_val = 65535
diff --git a/modular_skyrat/modules/blueshield/code/blueshield.dm b/modular_skyrat/modules/blueshield/code/blueshield.dm
index f9d39f4fe76..c7df4570b67 100644
--- a/modular_skyrat/modules/blueshield/code/blueshield.dm
+++ b/modular_skyrat/modules/blueshield/code/blueshield.dm
@@ -54,6 +54,8 @@
glasses = /obj/item/clothing/glasses/hud/security/sunglasses
backpack_contents = list(
/obj/item/storage/box/gunset/blueshield = 1,
+ /obj/item/gun/energy/e_gun/revolver = 1,
+ /obj/item/storage/medkit/tactical/blueshield = 1,
/obj/item/melee/baton/security/loaded = 1,)
implants = list(/obj/item/implant/mindshield)
backpack = /obj/item/storage/backpack/blueshield
@@ -62,6 +64,7 @@
head = /obj/item/clothing/head/beret/blueshield
box = /obj/item/storage/box/survival/security
belt = /obj/item/modular_computer/pda/security
+ r_pocket = /obj/item/flashlight/seclite
id = /obj/item/card/id/advanced/centcom
id_trim = /datum/id_trim/job/blueshield
diff --git a/modular_skyrat/modules/blueshield/code/special.dm b/modular_skyrat/modules/blueshield/code/special.dm
index 3e80dbfed24..b118ceb0387 100644
--- a/modular_skyrat/modules/blueshield/code/special.dm
+++ b/modular_skyrat/modules/blueshield/code/special.dm
@@ -1,7 +1,7 @@
-/obj/item/gun/energy/e_gun/revolver //The virgin gun.
+/obj/item/gun/energy/e_gun/revolver //The gun fit for a kitsune
name = "X-R12 energy revolver"
desc = "An experimental model advanced energy weapon with the capacity to shoot both electrodes and lasers, used by many private defense contractors from Romulus to New Moscow, its also rather heavy and would certainly hurt to get pistol whipped by."
- force = 16
+ force = 12
ammo_type = list(/obj/item/ammo_casing/energy/electrode, /obj/item/ammo_casing/energy/laser/blueshield)
ammo_x_offset = 1
charge_sections = 4
@@ -18,13 +18,14 @@
w_class = WEIGHT_CLASS_NORMAL
worn_icon = 'modular_skyrat/modules/aesthetics/guns/icons/guns_back.dmi'
worn_icon_state = "bsrevolver"
+ company_flag = COMPANY_ROMULUS
/obj/item/stock_parts/cell/blueshield
name = "internal revolver power cell"
maxcharge = 1200
- chargerate = 300
+ chargerate = 105 //Hit your shot and don't complain, it's self recharging.
-/obj/item/gun/energy/e_gun/revolver/pdw9 //The chad gun.
+/obj/item/gun/energy/e_gun/revolver/pdw9 //The gun fit for a real man
name = "PDW-9 taser pistol"
desc = "A military grade energy sidearm, used by many militia forces throughout the local sector. It comes with an internally recharging battery which is slow to recharge."
ammo_x_offset = 2
@@ -34,7 +35,7 @@
/obj/item/stock_parts/cell/pdw9
name = "internal pistol power cell"
- maxcharge = 1000
+ maxcharge = 1200
chargerate = 300
var/obj/item/gun/energy/e_gun/revolver/pdw9/parent
diff --git a/modular_skyrat/modules/nanotrasen_rep/code/nanotrasen_consultant.dm b/modular_skyrat/modules/nanotrasen_rep/code/nanotrasen_consultant.dm
index 5930d4c1747..f56de7887ae 100644
--- a/modular_skyrat/modules/nanotrasen_rep/code/nanotrasen_consultant.dm
+++ b/modular_skyrat/modules/nanotrasen_rep/code/nanotrasen_consultant.dm
@@ -44,7 +44,7 @@
name = "Nanotrasen Consultant"
jobtype = /datum/job/nanotrasen_consultant
- belt = /obj/item/modular_computer/pda/nanotrasen_consultant
+ belt = /obj/item/storage/belt/security/peacekeeper
glasses = /obj/item/clothing/glasses/sunglasses
ears = /obj/item/radio/headset/heads/nanotrasen_consultant
gloves = /obj/item/clothing/gloves/combat
@@ -55,6 +55,7 @@
backpack_contents = list(
/obj/item/melee/baton/telescopic = 1,
/obj/item/storage/box/gunset/nanotrasen_consultant = 1,
+ /obj/item/modular_computer/pda/nanotrasen_consultant = 1,
)
skillchips = list(/obj/item/skillchip/disk_verifier)
@@ -124,7 +125,9 @@
new /obj/item/ammo_box/magazine/m45a5(src)
new /obj/item/ammo_box/magazine/m45a5(src)
new /obj/item/ammo_box/magazine/m45a5(src)
-
+ new /obj/item/ammo_box/magazine/m45a5(src)
+ new /obj/item/ammo_box/magazine/m45a5(src)
+ new /obj/item/ammo_box/magazine/m45a5(src)
/obj/structure/closet/secure_closet/nanotrasen_consultant/station
name = "\proper nanotrasen consultant's locker"
diff --git a/modular_skyrat/modules/sec_haul/code/security_medic/security_medic.dm b/modular_skyrat/modules/sec_haul/code/security_medic/security_medic.dm
index efca4b31eb8..7e6f7430571 100644
--- a/modular_skyrat/modules/sec_haul/code/security_medic/security_medic.dm
+++ b/modular_skyrat/modules/sec_haul/code/security_medic/security_medic.dm
@@ -47,7 +47,7 @@
name = "Security Medic"
jobtype = /datum/job/security_medic
- belt = /obj/item/modular_computer/pda/security
+ belt = /obj/item/storage/belt/security/full
ears = /obj/item/radio/headset/headset_medsec
uniform = /obj/item/clothing/under/rank/security/peacekeeper/security_medic
gloves = /obj/item/clothing/gloves/latex/nitrile
@@ -58,6 +58,7 @@
head = /obj/item/clothing/head/beret/sec/peacekeeper/security_medic
backpack_contents = list(
/obj/item/storage/box/gunset/firefly = 1,
+ /obj/item/modular_computer/pda/security = 1,
)
backpack = /obj/item/storage/backpack/security
satchel = /obj/item/storage/backpack/satchel/sec
diff --git a/modular_zubbers/code/game/objects/items/reshirevolver.dm b/modular_zubbers/code/game/objects/items/reshirevolver.dm
new file mode 100644
index 00000000000..400f61c367f
--- /dev/null
+++ b/modular_zubbers/code/game/objects/items/reshirevolver.dm
@@ -0,0 +1,67 @@
+/obj/item/gun/ballistic/revolver/hos_revolver
+ name = "\improper HR-460MS 'Tracker'"
+ desc = "A brutally effectve revolver by Romulus officers prior to destruction of the planet, if the initial damage did not kill, the bleedout would. Uses the brutal .460 Rowland ammo."
+ mag_type = /obj/item/ammo_box/magazine/internal/cylinder/rowland
+ icon = 'modular_zubbers/icons/obj/reshirevolver.dmi'
+ icon_state = "tracker"
+ fire_sound = 'modular_skyrat/modules/sec_haul/sound/hpistol_fire.ogg'
+ company_flag = COMPANY_ROMULUS
+ projectile_damage_multiplier = 1.6 //48 Damages, still a lot but not too much
+//With the damage multipler, it would crit in 4, kill in 6. Does not take into account armours.
+
+/obj/item/ammo_box/magazine/internal/cylinder/rowland
+ name = "\improper rowland revolver cylinder"
+ max_ammo = 6
+ ammo_type = /obj/item/ammo_casing/b460
+ caliber = CALIBER_460
+
+/obj/item/storage/bag/b460reloadpouch
+ name = "reload pouch"
+ desc = "A pouch for holding loose casings for .460 Rowland ammo. incompatible with anything else. Fit on your belt too"
+ icon = 'modular_zubbers/icons/obj/pouches.dmi'
+ icon_state = "reloadpouch"
+ slot_flags = ITEM_SLOT_POCKETS | ITEM_SLOT_BELT
+ w_class = WEIGHT_CLASS_BULKY
+ resistance_flags = FLAMMABLE
+
+/obj/item/storage/bag/b460reloadpouch/Initialize(mapload)
+ . = ..()
+ atom_storage.max_specific_storage = WEIGHT_CLASS_SMALL
+ atom_storage.max_total_storage = 30
+ atom_storage.max_slots = 30
+ atom_storage.numerical_stacking = TRUE
+ atom_storage.set_holdable(list(
+ /obj/item/ammo_casing/b460,
+ ))
+
+/obj/item/storage/bag/b460reloadpouch/PopulateContents()
+ . = ..()
+ new /obj/item/ammo_casing/b460(src)
+ new /obj/item/ammo_casing/b460(src)
+ new /obj/item/ammo_casing/b460(src)
+ new /obj/item/ammo_casing/b460(src)
+ new /obj/item/ammo_casing/b460(src)
+ new /obj/item/ammo_casing/b460(src)
+ new /obj/item/ammo_casing/b460(src)
+ new /obj/item/ammo_casing/b460(src)
+ new /obj/item/ammo_casing/b460(src)
+ new /obj/item/ammo_casing/b460(src)
+ new /obj/item/ammo_casing/b460(src)
+ new /obj/item/ammo_casing/b460(src)
+ new /obj/item/ammo_casing/b460(src)
+ new /obj/item/ammo_casing/b460(src)
+ new /obj/item/ammo_casing/b460(src)
+ new /obj/item/ammo_casing/b460(src)
+ new /obj/item/ammo_casing/b460(src)
+ new /obj/item/ammo_casing/b460(src)
+ new /obj/item/ammo_casing/b460(src)
+ new /obj/item/ammo_casing/b460(src)
+ new /obj/item/ammo_casing/b460(src)
+ new /obj/item/ammo_casing/b460(src)
+ new /obj/item/ammo_casing/b460(src)
+ new /obj/item/ammo_casing/b460(src)
+
+/obj/item/storage/box/gunset/hos_revolver/PopulateContents()
+ . = ..()
+ new /obj/item/gun/ballistic/revolver/hos_revolver(src)
+ new /obj/item/storage/bag/b460reloadpouch(src)
diff --git a/modular_zubbers/code/modules/mob/living/living.dm b/modular_zubbers/code/modules/mob/living/living.dm
new file mode 100644
index 00000000000..840c112204e
--- /dev/null
+++ b/modular_zubbers/code/modules/mob/living/living.dm
@@ -0,0 +1,3 @@
+/mob/living/Initialize(mapload)
+ . = ..()
+ AddComponent(/datum/component/status_indicator)
diff --git a/modular_zubbers/code/modules/status_indicators/status_indicator.dm b/modular_zubbers/code/modules/status_indicators/status_indicator.dm
new file mode 100644
index 00000000000..43e1319adb4
--- /dev/null
+++ b/modular_zubbers/code/modules/status_indicators/status_indicator.dm
@@ -0,0 +1,220 @@
+
+GLOBAL_LIST_INIT(potential_indicators, list(
+ STUNNED = image(icon = 'modular_zubbers/icons/mob/status_indicators.dmi', icon_state = STUNNED),
+ WEAKEN = image(icon = 'modular_zubbers/icons/mob/status_indicators.dmi', icon_state = WEAKEN),
+ PARALYSIS = image(icon = 'modular_zubbers/icons/mob/status_indicators.dmi', icon_state = PARALYSIS),
+ SLEEPING = image(icon = 'modular_zubbers/icons/mob/status_indicators.dmi', icon_state = SLEEPING),
+ CONFUSED = image(icon = 'modular_zubbers/icons/mob/status_indicators.dmi', icon_state = CONFUSED),
+))
+
+/datum/component/status_indicator
+ var/list/status_indicators = null // Will become a list as needed. Contains our status indicator objects. Note, they are actually added to overlays, this just keeps track of what exists.
+ var/mob/living/attached_mob
+
+/// Returns true if the mob is weakened. Also known as floored.
+/datum/component/status_indicator/proc/is_weakened()
+ if(!indicator_fakeouts() && \
+ attached_mob.IsKnockdown() || \
+ HAS_TRAIT(attached_mob, TRAIT_FLOORED) && \
+ !HAS_TRAIT_FROM(attached_mob, TRAIT_FLOORED, BUCKLED_TRAIT)
+ )
+ return TRUE
+
+/// Returns true if the mob is stunned.
+/datum/component/status_indicator/proc/is_stunned()
+ if(!indicator_fakeouts() && \
+ HAS_TRAIT_FROM(attached_mob, TRAIT_INCAPACITATED, TRAIT_STATUS_EFFECT(STAT_TRAIT)) || \
+ HAS_TRAIT(attached_mob, TRAIT_CRITICAL_CONDITION) || \
+ HAS_TRAIT_FROM(attached_mob, TRAIT_IMMOBILIZED, TRAIT_STATUS_EFFECT(STAT_TRAIT)) || \
+ HAS_TRAIT_FROM(attached_mob, TRAIT_IMMOBILIZED, CHOKEHOLD_TRAIT) || \
+ HAS_TRAIT_FROM(attached_mob, TRAIT_INCAPACITATED, TRAIT_STATUS_EFFECT(STAT_TRAIT)) || \
+ HAS_TRAIT_FROM(attached_mob, TRAIT_IMMOBILIZED, TRAIT_STATUS_EFFECT(STAT_TRAIT))
+ )
+ return TRUE
+
+/// Returns true if the mob is paralyzed - for can't fight back purposes.
+/datum/component/status_indicator/proc/is_paralyzed()
+ if(!indicator_fakeouts() && \
+ attached_mob.IsParalyzed() || \
+ HAS_TRAIT_FROM(attached_mob, TRAIT_FLOORED, CHOKEHOLD_TRAIT) || \
+ HAS_TRAIT_FROM(attached_mob, TRAIT_IMMOBILIZED, TRAIT_STATUS_EFFECT(STAT_TRAIT)) || \
+ HAS_TRAIT(attached_mob, TRAIT_CRITICAL_CONDITION) || \
+ HAS_TRAIT_FROM(attached_mob, TRAIT_INCAPACITATED, STAMINA))
+ return TRUE
+
+/// Returns true if the mob is unconcious for any reason.
+/datum/component/status_indicator/proc/is_unconcious()
+ if(!indicator_fakeouts() && HAS_TRAIT(attached_mob, TRAIT_KNOCKEDOUT))
+ return TRUE
+
+/// Returns true if the mob has confusion.
+/datum/component/status_indicator/proc/is_confused()
+ if(!indicator_fakeouts() && attached_mob.has_status_effect(/datum/status_effect/confusion))
+ return TRUE
+
+/datum/component/status_indicator/RegisterWithParent()
+ attached_mob = parent
+ // The Basics
+ RegisterSignal(parent, COMSIG_LIVING_DEATH, PROC_REF(cut_indicators_overlays))
+ RegisterSignal(parent, COMSIG_LIVING_LIFE, PROC_REF(status_indicator_evaluate))
+ // When things actually happen
+ RegisterSignal(parent, COMSIG_LIVING_STATUS_STUN, PROC_REF(status_indicator_evaluate))
+ RegisterSignal(parent, COMSIG_LIVING_STATUS_KNOCKDOWN, PROC_REF(status_indicator_evaluate))
+ RegisterSignal(parent, COMSIG_LIVING_STATUS_PARALYZE, PROC_REF(status_indicator_evaluate))
+ RegisterSignal(parent, COMSIG_LIVING_STATUS_IMMOBILIZE, PROC_REF(status_indicator_evaluate))
+ RegisterSignal(parent, COMSIG_LIVING_STATUS_UNCONSCIOUS, PROC_REF(status_indicator_evaluate))
+ RegisterSignal(parent, COMSIG_MOB_LOGIN, PROC_REF(apply_pref_on_login))
+
+/datum/component/status_indicator/proc/apply_pref_on_login()
+ var/atom/movable/screen/plane_master/game_world_upper_fov_hidden/status_indicator/local_status = locate() in attached_mob.client.screen
+ if(local_status)
+ . = attached_mob.client.prefs.read_preference(/datum/preference/toggle/enable_status_indicators)
+ local_status.alpha = (.) ? 255 : 0
+
+/datum/component/status_indicator/UnregisterFromParent()
+ QDEL_NULL(status_indicators)
+ UnregisterSignal(attached_mob, COMSIG_LIVING_DEATH)
+ UnregisterSignal(attached_mob, COMSIG_LIVING_LIFE)
+ UnregisterSignal(attached_mob, COMSIG_LIVING_STATUS_STUN)
+ UnregisterSignal(attached_mob, COMSIG_LIVING_STATUS_KNOCKDOWN)
+ UnregisterSignal(attached_mob, COMSIG_LIVING_STATUS_PARALYZE)
+ UnregisterSignal(attached_mob, COMSIG_LIVING_STATUS_IMMOBILIZE)
+ UnregisterSignal(attached_mob, COMSIG_LIVING_STATUS_UNCONSCIOUS)
+ attached_mob = null
+/// This proc makes it so that mobs that have status indicators are checked to remove them, especially in fakeout situations.
+/datum/component/status_indicator/proc/check_indicators()
+ if(status_indicators)
+ status_indicator_evaluate()
+
+/// Receives signals to update on carbon health updates. Checks if the mob is dead - if true, removes all the indicators. Then, we determine what status indicators the mob should carry or remove.
+/datum/component/status_indicator/proc/status_indicator_evaluate()
+ SIGNAL_HANDLER
+ if(attached_mob.stat == DEAD)
+ return
+ else
+ weaken_indicator_update()
+ paralyzed_indicator_update()
+ stunned_indicator_update()
+ unconcious_indicator_update()
+ confused_indicator_update()
+ return
+/// Cases in which no status indicators should appear above a mob, such as changeling revive and regen coma.
+/datum/component/status_indicator/proc/indicator_fakeouts()
+ if(HAS_TRAIT(attached_mob, TRAIT_DEATHCOMA))
+ return TRUE
+ return FALSE
+
+/datum/component/status_indicator/proc/weaken_indicator_update()
+ SIGNAL_HANDLER
+ is_weakened() ? add_status_indicator(WEAKEN) : remove_status_indicator(WEAKEN)
+/datum/component/status_indicator/proc/paralyzed_indicator_update()
+ SIGNAL_HANDLER
+ is_paralyzed() ? add_status_indicator(PARALYSIS) : remove_status_indicator(PARALYSIS)
+/datum/component/status_indicator/proc/stunned_indicator_update()
+ SIGNAL_HANDLER
+ is_stunned() ? add_status_indicator(STUNNED) : remove_status_indicator(STUNNED)
+/datum/component/status_indicator/proc/unconcious_indicator_update()
+ SIGNAL_HANDLER
+ is_unconcious() ? add_status_indicator(SLEEPING) : remove_status_indicator(SLEEPING)
+/datum/component/status_indicator/proc/confused_indicator_update()
+ SIGNAL_HANDLER
+ is_confused() ? add_status_indicator(CONFUSED) : remove_status_indicator(CONFUSED)
+
+/// Adds a status indicator to the mob. Takes an image as an argument. If it exists, it won't dupe it.
+/datum/component/status_indicator/proc/add_status_indicator(image/prospective_indicator)
+ if(get_status_indicator(prospective_indicator)) // No duplicates, please.
+ return
+
+ prospective_indicator = GLOB.potential_indicators[prospective_indicator]
+ prospective_indicator.loc = src
+ LAZYADD(status_indicators, prospective_indicator)
+ handle_status_indicators(prospective_indicator)
+
+/// Similar to add_status_indicator() but removes it instead, and nulls the list if it becomes empty as a result.
+/datum/component/status_indicator/proc/remove_status_indicator(image/prospective_indicator)
+ prospective_indicator = get_status_indicator(prospective_indicator)
+
+ attached_mob.cut_overlay(prospective_indicator)
+ LAZYREMOVE(status_indicators, prospective_indicator)
+ handle_status_indicators(prospective_indicator)
+
+/// Finds a status indicator on a mob.
+/datum/component/status_indicator/proc/get_status_indicator(image/prospective_indicator)
+
+ for(var/image/indicator in status_indicators)
+ if(indicator.icon_state == prospective_indicator)
+ return indicator
+ return LAZYACCESS(status_indicators, LAZYFIND(status_indicators, prospective_indicator))
+
+/// Cuts all the indicators on a mob in a loop.
+/datum/component/status_indicator/proc/cut_indicators_overlays()
+ SIGNAL_HANDLER
+ for(var/prospective_indicator in status_indicators)
+ attached_mob.cut_overlay(prospective_indicator)
+
+/// Refreshes the indicators over a mob's head. Should only be called when adding or removing a status indicator with the above procs,
+/// or when the mob changes size visually for some reason.
+/datum/component/status_indicator/proc/handle_status_indicators(image/prospective_indicator)
+ // First, get rid of all the overlays.
+
+ cut_indicators_overlays()
+
+ if(!LAZYLEN(status_indicators))
+ return
+
+ var/mob/living/carbon/my_carbon_mob = attached_mob
+
+ var/icon_scale = get_icon_scale(my_carbon_mob)
+
+ if(my_carbon_mob.stat == DEAD)
+ cut_indicators_overlays()
+ return
+
+ // Now put them back on in the right spot.
+ var/our_sprite_x = 16 * icon_scale
+ var/our_sprite_y = 24 * icon_scale
+
+ var/x_offset = our_sprite_x // Add your own offset here later if you want.
+ var/y_offset = our_sprite_y + STATUS_INDICATOR_Y_OFFSET
+
+ // Calculates how 'long' the row of indicators and the margin between them should be.
+ // The goal is to have the center of that row be horizontally aligned with the sprite's center.
+ var/expected_status_indicator_length = (STATUS_INDICATOR_ICON_X_SIZE * status_indicators.len) + (STATUS_INDICATOR_ICON_MARGIN * max(status_indicators.len - 1, 0))
+ var/current_x_position = (x_offset / 2) - (expected_status_indicator_length / 2)
+
+ // In /mob/living's `update_transform()`, the sprite is horizontally shifted when scaled up, so that the center of the sprite doesn't move to the right.
+ // Because of that, this adjustment needs to happen with the future indicator row as well, or it will look bad.
+ current_x_position -= 16 * (icon_scale - DEFAULT_MOB_SCALE)
+
+ // Now the indicator row can actually be built.
+ for(var/all_indicators in status_indicators)
+ var/image/indicator = all_indicators
+
+ // This is a semi-HUD element, in a similar manner as medHUDs, in that they're 'above' everything else in the world,
+ // but don't pierce obfuscation layers such as blindness or darkness, unlike actual HUD elements like inventory slots.
+ indicator.plane = GAME_PLANE_UPPER_FOV_HIDDEN
+ indicator.layer = STATUS_LAYER
+ indicator.appearance_flags = PIXEL_SCALE|TILE_BOUND|NO_CLIENT_COLOR|RESET_COLOR|RESET_ALPHA|RESET_TRANSFORM|KEEP_APART
+ indicator.pixel_y = y_offset
+ indicator.pixel_x = current_x_position
+ my_carbon_mob.add_overlay(indicator)
+ // Adding the margin space every time saves a conditional check on the last iteration,
+ // and it won't cause any issues since no more icons will be added, and the var is not used for anything else.
+ current_x_position += STATUS_INDICATOR_ICON_X_SIZE + STATUS_INDICATOR_ICON_MARGIN
+
+/datum/component/status_indicator/proc/get_icon_scale(livingmob)
+ if(!iscarbon(livingmob)) // normal mobs are always 1 for scale - hopefully all borgs and simplemobs get this one
+ return DEFAULT_MOB_SCALE
+ var/mob/living/carbon/passed_mob = livingmob // we're possibly a player! We have size prefs!
+ var/mysize = (passed_mob.dna?.current_body_size ? passed_mob.dna.current_body_size : DEFAULT_MOB_SCALE)
+ return mysize
+
+/atom/movable/screen/plane_master/game_world_upper_fov_hidden/status_indicator
+ name = "Status Indicator Plane"
+ documentation = "Status Indicator Plane"
+ plane = GAME_PLANE_UPPER_FOV_HIDDEN
+ start_hidden = FALSE
+
+#undef STATUS_INDICATOR_Y_OFFSET
+#undef STATUS_INDICATOR_ICON_X_SIZE
+#undef STATUS_INDICATOR_ICON_MARGIN
diff --git a/modular_zubbers/code/modules/status_indicators/status_indicator_pref.dm b/modular_zubbers/code/modules/status_indicators/status_indicator_pref.dm
new file mode 100644
index 00000000000..87a8fd20f18
--- /dev/null
+++ b/modular_zubbers/code/modules/status_indicators/status_indicator_pref.dm
@@ -0,0 +1,26 @@
+/datum/preference/toggle/enable_status_indicators
+ category = PREFERENCE_CATEGORY_GAME_PREFERENCES
+ savefile_key = "enable_status_indicators"
+ savefile_identifier = PREFERENCE_PLAYER
+
+/datum/preference/toggle/enable_status_indicators/create_default_value()
+ return TRUE
+
+
+/datum/preference/toggle/enable_status_indicators/apply_to_client(client/client, value)
+ if(client.mob)
+ var/datum/component/status_indicator/mystatus = client.mob.GetComponent(/datum/component/status_indicator)
+ if(mystatus)
+ mystatus.apply_pref_on_login()
+
+/* if(client && client.prefs)
+ . = client?.prefs?.read_preference(/datum/preference/toggle/enable_status_indicators)
+ var/atom/movable/screen/plane_master/status/status_indicators = locate() in client.screen
+ if(isnull(status_indicators))
+ new /atom/movable/screen/plane_master/status in client.screen
+ status_indicators = locate() in client.screen
+ if(length(status_indicators) < 1)
+ pop(status_indicators)
+ (.) ? (status_indicators.alpha = 255) : (status_indicators.alpha = 0)
+
+ */
diff --git a/modular_zubbers/icons/mob/status_indicators.dmi b/modular_zubbers/icons/mob/status_indicators.dmi
new file mode 100644
index 00000000000..9c80c2bf10a
Binary files /dev/null and b/modular_zubbers/icons/mob/status_indicators.dmi differ
diff --git a/modular_zubbers/icons/obj/pouches.dmi b/modular_zubbers/icons/obj/pouches.dmi
new file mode 100644
index 00000000000..24b2462e5b3
Binary files /dev/null and b/modular_zubbers/icons/obj/pouches.dmi differ
diff --git a/modular_zubbers/icons/obj/reshirevolver.dmi b/modular_zubbers/icons/obj/reshirevolver.dmi
new file mode 100644
index 00000000000..b5a1c8d958c
Binary files /dev/null and b/modular_zubbers/icons/obj/reshirevolver.dmi differ
diff --git a/tgstation.dme b/tgstation.dme
index 1bd4f933106..424fbfff29c 100644
--- a/tgstation.dme
+++ b/tgstation.dme
@@ -390,6 +390,7 @@
#include "code\__DEFINES\~~bubber_defines\access.dm"
#include "code\__DEFINES\~~bubber_defines\quirk_whitelist.dm"
#include "code\__DEFINES\~~bubber_defines\species.dm"
+#include "code\__DEFINES\~~bubber_defines\status_indicator_defines.dm"
#include "code\__DEFINES\~~bubber_defines\traits.dm"
#include "code\__HELPERS\_auxtools_api.dm"
#include "code\__HELPERS\_lists.dm"
@@ -5354,6 +5355,7 @@
#include "modular_skyrat\master_files\code\modules\research\designs\misc_designs.dm"
#include "modular_skyrat\master_files\code\modules\research\machinery\departmental_circuit_imprinter.dm"
#include "modular_skyrat\master_files\code\modules\research\techweb\all_nodes.dm"
+#include "modular_skyrat\master_files\code\modules\research\techweb\protolathe.dm"
#include "modular_skyrat\master_files\code\modules\shuttle\shuttle.dm"
#include "modular_skyrat\master_files\code\modules\surgery\surgery.dm"
#include "modular_skyrat\master_files\code\modules\surgery\organs\tongue.dm"
@@ -6694,9 +6696,11 @@
#include "modular_zubbers\code\datums\bubber_quirks\hydrophilic.dm"
#include "modular_zubbers\code\datums\id_trim\jobs.dm"
#include "modular_zubbers\code\game\area\areas\station.dm"
+#include "modular_zubbers\code\game\objects\effects\decals.dm"
#include "modular_zubbers\code\game\objects\effects\landmarks.dm"
#include "modular_zubbers\code\game\objects\effects\items\plushes.dm"
#include "modular_zubbers\code\game\objects\items\holy_weapons.dm"
+#include "modular_zubbers\code\game\objects\items\reshirevolver.dm"
#include "modular_zubbers\code\game\objects\items\food\misc.dm"
#include "modular_zubbers\code\modules\_defines.dm"
#include "modular_zubbers\code\modules\clothing\head\helmet.dm"
@@ -6723,6 +6727,8 @@
#include "modular_zubbers\code\modules\mod\mod_theme.dm"
#include "modular_zubbers\code\modules\mod\mod_types.dm"
#include "modular_zubbers\code\modules\projectiles\guns\energy\pulse.dm"
+#include "modular_zubbers\code\modules\status_indicators\status_indicator.dm"
+#include "modular_zubbers\code\modules\status_indicators\status_indicator_pref.dm"
#include "modular_zubbers\code\modules\surgery\bodyparts\species_parts\misc_bodyparts.dm"
#include "modular_zubbers\code\modules\vending\wardrobe.dm"
// END_INCLUDE
diff --git a/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/game_preferences/skyrat/status_indicators.tsx b/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/game_preferences/skyrat/status_indicators.tsx
new file mode 100644
index 00000000000..bb1eac18f2c
--- /dev/null
+++ b/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/game_preferences/skyrat/status_indicators.tsx
@@ -0,0 +1,8 @@
+import { CheckboxInput, FeatureToggle } from '../../base';
+
+export const enable_status_indicators: FeatureToggle = {
+ name: 'Display Status Indicators',
+ category: 'GAMEPLAY',
+ description: 'This toggles whether or not you will see status indicators.',
+ component: CheckboxInput,
+};