diff --git a/citadel.dme b/citadel.dme
index 68b16e09f4f1..d9fff80cfd1f 100644
--- a/citadel.dme
+++ b/citadel.dme
@@ -22,6 +22,7 @@
#include "code\__DEFINES\_bitfields.dm"
#include "code\__DEFINES\_cooldowns.dm"
#include "code\__DEFINES\_core.dm"
+#include "code\__DEFINES\_enums.dm"
#include "code\__DEFINES\_globals.dm"
#include "code\__DEFINES\_lists.dm"
#include "code\__DEFINES\_planes+layers.dm"
@@ -201,6 +202,7 @@
#include "code\__DEFINES\fishing\fishing.dm"
#include "code\__DEFINES\inventory\accessories.dm"
#include "code\__DEFINES\inventory\bodytypes.dm"
+#include "code\__DEFINES\inventory\carry_weight.dm"
#include "code\__DEFINES\inventory\icons.dm"
#include "code\__DEFINES\inventory\misc.dm"
#include "code\__DEFINES\inventory\procs.dm"
@@ -3422,6 +3424,7 @@
#include "code\modules\mob\living\carbon\human\human_resist.dm"
#include "code\modules\mob\living\carbon\human\human_species.dm"
#include "code\modules\mob\living\carbon\human\inventory.dm"
+#include "code\modules\mob\living\carbon\human\inventory_legacy.dm"
#include "code\modules\mob\living\carbon\human\life.dm"
#include "code\modules\mob\living\carbon\human\login.dm"
#include "code\modules\mob\living\carbon\human\logout.dm"
@@ -4402,6 +4405,7 @@
#include "code\modules\shuttles\web_datums.dm"
#include "code\modules\species\abilites.dm"
#include "code\modules\species\character_species.dm"
+#include "code\modules\species\physiology.dm"
#include "code\modules\species\species.dm"
#include "code\modules\species\species_attack.dm"
#include "code\modules\species\species_getters.dm"
@@ -4641,16 +4645,17 @@
#include "code\modules\tgchat\to_chat.dm"
#include "code\modules\tgs\includes.dm"
#include "code\modules\tgui\external.dm"
-#include "code\modules\tgui\modal_vr.dm"
+#include "code\modules\tgui\modal_vr_legacy.dm"
#include "code\modules\tgui\module.dm"
#include "code\modules\tgui\states.dm"
#include "code\modules\tgui\status_composers.dm"
#include "code\modules\tgui\tgui.dm"
-#include "code\modules\tgui\tgui_alert.dm"
-#include "code\modules\tgui\tgui_input_list.dm"
-#include "code\modules\tgui\tgui_input_number.dm"
-#include "code\modules\tgui\tgui_input_text.dm"
#include "code\modules\tgui\tgui_window.dm"
+#include "code\modules\tgui\modals\tgui_alert.dm"
+#include "code\modules\tgui\modals\tgui_dynamic_input.dm"
+#include "code\modules\tgui\modals\tgui_input_list.dm"
+#include "code\modules\tgui\modals\tgui_input_number.dm"
+#include "code\modules\tgui\modals\tgui_input_text.dm"
#include "code\modules\tgui\modules\_base.dm"
#include "code\modules\tgui\modules\alarm.dm"
#include "code\modules\tgui\modules\atmos_control.dm"
diff --git a/code/__DEFINES/_enums.dm b/code/__DEFINES/_enums.dm
new file mode 100644
index 000000000000..d085dffa3793
--- /dev/null
+++ b/code/__DEFINES/_enums.dm
@@ -0,0 +1,8 @@
+// todo: enum system like bitfields
+/// KEY: must be unique, may be arbitrary; not a string, as it's used in typepath generation
+/// CONSTRAINTS: list(/type = list(varname, ...), ...)
+/// ENUMS: list of ENUM().
+#define DEFINE_ENUM(KEY, CONSTRAINTS, ENUMS)
+/// NAME: must be a string
+/// VALUE: the actual enum value, whatever it is
+#define ENUM(NAME, VALUE) ##NAME = ##VALUE
diff --git a/code/__DEFINES/_flags/item_flags.dm b/code/__DEFINES/_flags/item_flags.dm
index 29e39d3fa157..9feebe4d2d4f 100644
--- a/code/__DEFINES/_flags/item_flags.dm
+++ b/code/__DEFINES/_flags/item_flags.dm
@@ -23,6 +23,11 @@
#define ITEM_NO_LATHE_DECONSTRUCT (1<<10)
/// stack-like handling for ingredients
#define ITEM_MASS_INGREDIENT (1<<11)
+/// encumbers while in hand
+#define ITEM_ENCUMBERS_WHILE_HELD (1<<12)
+/// doesn't encumber while not in hand
+#define ITEM_ENCUMBERS_ONLY_HELD (1<<13)
+// todo: ITEM_SLOWS_WHILE_HELD for slowdown
DEFINE_BITFIELD(item_flags, list(
BITFIELD(ITEM_IN_INVENTORY),
@@ -37,6 +42,8 @@ DEFINE_BITFIELD(item_flags, list(
BITFIELD(ITEM_EASY_LATHE_DECONSTRUCT),
BITFIELD(ITEM_NO_LATHE_DECONSTRUCT),
BITFIELD(ITEM_MASS_INGREDIENT),
+ BITFIELD(ITEM_ENCUMBERS_WHILE_HELD),
+ BITFIELD(ITEM_ENCUMBERS_ONLY_HELD),
))
//! Flags for the clothing_flags var on /obj/item
@@ -47,7 +54,7 @@ DEFINE_BITFIELD(item_flags, list(
#define CLOTHING_IGNORE_BELTLINK (1<<2)
/// for plural limbs, wearable with just one
#define CLOTHING_ALLOW_SINGLE_LIMB (1<<3)
-/// Prevents syringes, parapens and hyposprays if equipped to slot_suit or SLOT_ID_HEAD.
+/// Prevents syringes, parapens and hyposprays.
#define CLOTHING_THICK_MATERIAL (1<<4)
/// Syringes / hyposprays / etc can get through, but need to pass through an injection port.
#define CLOTHING_INJECTION_PORT (1<<5)
diff --git a/code/__DEFINES/inventory/carry_weight.dm b/code/__DEFINES/inventory/carry_weight.dm
new file mode 100644
index 000000000000..3858f6880a9f
--- /dev/null
+++ b/code/__DEFINES/inventory/carry_weight.dm
@@ -0,0 +1,286 @@
+//* This file is explicitly licensed under the MIT license. *//
+//* Copyright (c) 2023 Citadel Station developers. *//
+
+//? Despite this being carry_weight.dm, this contains defines for:
+//? carry strength - how much someone can carry or move
+//? weight - how much stuff weighs, recursive
+//? encumberence - how hard it is to move with an item, non-recursive
+
+//* CHECK https://www.desmos.com/calculator/o44o3naob2 FOR INFORMATION *//
+//* DO nOT CHANGE ANY CONSTANTS WItHOUT GRAPHING IT OUT FIRST. *//
+
+//? Carry strength - flat strength. you can carry up to this with no penalty.
+
+#define CARRY_STRENGTH_BASELINE 20
+
+#define CARRY_STRENGTH_ADD_HUMAN 1.25
+#define CARRY_STRENGTH_ADD_UNATHI 2.5
+#define CARRY_STRENGTH_ADD_PROTEAN 2.5
+#define CARRY_STRENGTH_ADD_MOTH_LIGHT 1.25
+#define CARRY_STRENGTH_ADD_MOTH_DARK 0
+#define CARRY_STRENGTH_ADD_TAJARAN 0
+#define CARRY_STRENGTH_ADD_TESHARI 0
+#define CARRY_STRENGTH_ADD_XENOCHIMERA 2.5
+#define CARRY_STRENGTH_ADD_XENOHYBRID 2.5
+
+//? Carry factor - multiplier for penalizing over-limit weight; higher is worse.
+
+#define CARRY_FACTOR_BASELINE 1
+
+#define CARRY_FACTOR_MOD_HUMAN 0.92
+#define CARRY_FACTOR_MOD_UNATHI 0.92
+#define CARRY_FACTOR_MOD_MOTH_LIGHT 0.96
+#define CARRY_FACTOR_MOD_MOTH_DARK 1.08
+#define CARRY_FACTOR_MOD_TAJARAN 1.08
+#define CARRY_FACTOR_MOD_TESHARI 1.12
+#define CARRY_FACTOR_MOD_PROTEAN 1.12
+#define CARRY_FACTOR_MOD_XENOCHIMERA 0.88
+#define CARRY_FACTOR_MOD_XENOHYBRID 0.88
+
+//? Carry equation constants
+
+/// How penalizing the default penalty curve is; lower is weaker slowdowns from overweight.
+#define CARRY_WEIGHT_SCALING 2
+/// For now, constant - bias factor; higher = skip more of the curve as soon as weight goes above strength
+#define CARRY_WEIGHT_BIAS 1.2
+/// % from 0 to 1 of the curve that is automatically given ; 0.1 = the asymptote is 10%, as opposed to 0% movespeed
+#define CARRY_WEIGHT_ASYMPTOTE 0.1
+
+//? Item Encumbrance defines
+
+#define ITEM_ENCUMBRANCE_BASELINE 0
+
+//* Armor
+
+#define ITEM_ENCUMBRANCE_ARMOR_ULTRALIGHT 7.5
+#define ITEM_ENCUMBRANCE_ARMOR_LIGHT 10
+#define ITEM_ENCUMBRANCE_ARMOR_MEDIUM 15
+#define ITEM_ENCUMBRANCE_ARMOR_HEAVY 20
+#define ITEM_ENCUMBRANCE_ARMOR_SUPERHEAVY 30
+#define ITEM_ENCUMBRANCE_ARMOR_SPECIALIZED 15
+
+#define ITEM_ENCUMBRANCE_ARMOR_ULTRALIGHT_HELMET 1
+#define ITEM_ENCUMBRANCE_ARMOR_LIGHT_HELMET 1.5
+#define ITEM_ENCUMBRANCE_ARMOR_MEDIUM_HELMET 2
+#define ITEM_ENCUMBRANCE_ARMOR_HEAVY_HELMET 2.5
+#define ITEM_ENCUMBRANCE_ARMOR_SUPERHEAVY_HELMET 3
+#define ITEM_ENCUMBRANCE_ARMOR_SPECIALIZED_HELMET 2
+
+#define ITEM_ENCUMBRANCE_ARMOR_ULTRALIGHT_GLOVES 1
+#define ITEM_ENCUMBRANCE_ARMOR_LIGHT_GLOVES 2
+#define ITEM_ENCUMBRANCE_ARMOR_MEDIUM_GLOVES 3
+#define ITEM_ENCUMBRANCE_ARMOR_HEAVY_GLOVES 4
+#define ITEM_ENCUMBRANCE_ARMOR_SUPERHEAVY_GLOVES 5
+#define ITEM_ENCUMBRANCE_ARMOR_SPECIALIZED_GLOVES 3
+
+#define ITEM_ENCUMBRANCE_ARMOR_ULTRALIGHT_BOOTS 2.5
+#define ITEM_ENCUMBRANCE_ARMOR_LIGHT_BOOTS 3.5
+#define ITEM_ENCUMBRANCE_ARMOR_MEDIUM_BOOTS 5
+#define ITEM_ENCUMBRANCE_ARMOR_HEAVY_BOOTS 7.5
+#define ITEM_ENCUMBRANCE_ARMOR_SUPERHEAVY_BOOTS 10
+#define ITEM_ENCUMBRANCE_ARMOR_SPECIALIZED_BOOTS 5
+
+#define ITEM_ENCUMBRANCE_ARMOR_BIORAD_SUIT 30
+#define ITEM_ENCUMBRANCE_ARMOR_BIORAD_HELMET 0
+#define ITEM_ENCUMBRANCE_ARMOR_BOMB_SUIT 30
+#define ITEM_ENCUMBRANCE_ARMOR_BOMB_HELMET 0
+#define ITEM_ENCUMBRANCE_ARMOR_FIRE_SUIT 30
+#define ITEM_ENCUMBRANCE_ARMOR_FIRE_HELMET 0
+
+#define ITEM_ENCUMBRANCE_ARMOR_MEDIEVAL_PLATE 30
+#define ITEM_ENCUMBRANCE_ARMOR_MEDIEVAL_CHAIN 25
+
+#define ITEM_ENCUMBRANCE_ARMOR_ANOMALY 30
+#define ITEM_ENCUMBRANCE_ARMOR_ANOMALY_HELMET 0
+
+//* Clothing
+
+/// shoecuffs
+#define ITEM_ENCUMBRANCE_SHOES_CUFFED 50
+/// magboots off
+#define ITEM_ENCUMBRANCE_SHOES_MAGBOOTS 5
+/// normal magboots on
+#define ITEM_ENCUMBRANCE_SHOES_MAGBOOTS_PULSE 20
+/// ce magboots on
+#define ITEM_ENCUMBRANCE_SHOES_MAGBOOTS_PULSE_ADVANCED 7.5
+#define ITEM_ENCUMBRANCE_SHOES_CLOWN 5
+#define ITEM_ENCUMBRANCE_SHOES_FINS 5
+#define ITEM_ENCUMBRANCE_SHOES_GALOSHES 5
+
+//* Factions
+
+#define ITEM_ENCUMBRANCE_CHANGELING_MAGBOOTS 5
+#define ITEM_ENCUMBRANCE_CHANGELING_MAGBOOTS_PULSE 7.5
+#define ITEM_ENCUMBRANCE_CULT_VOIDSUIT 35
+#define ITEM_ENCUMBRANCE_CULT_VOIDSUIT_HELMET 2.5
+
+//* Spacesuits
+
+#define ITEM_ENCUMBRANCE_SOFTSUIT 30
+#define ITEM_ENCUMBRANCE_SOFTSUIT_HELMET 2.5
+
+#define ITEM_ENCUMBRANCE_VOIDSUIT 30
+#define ITEM_ENCUMBRANCE_VOIDSUIT_HELMET 0
+#define ITEM_ENCUMBRANCE_VOIDSUIT_LIGHT 25
+#define ITEM_ENCUMBRANCE_VOIDSUIT_HELMET_LIGHT 0
+#define ITEM_ENCUMBRANCE_VOIDSUIT_HEAVY 35
+#define ITEM_ENCUMBRANCE_VOIDSUIT_HELMET_HEAVY 0
+#define ITEM_ENCUMBRANCE_VOIDSUIT_ULTRALIGHT 20
+#define ITEM_ENCUMBRANCE_VOIDSUIT_HELMET_ULTRALIGHT 0
+
+#define ITEM_ENCUMBRANCE_VOIDSUIT_ANOMALY 30
+#define ITEM_ENCUMBRANCE_VOIDSUIT_ANOMALY_HELMET 2.5
+
+#define ITEM_ENCUMBRANCE_LEGACY_RIG_LIGHT 25
+#define ITEM_ENCUMBRANCE_LEGACY_RIG 30
+#define ITEM_ENCUMBRANCE_LEGACY_RIG_HEAVY 35
+
+#define ITEM_ENCUMBRANCE_EMERGENCY_SOFTSUIT 30
+#define ITEM_ENCUMBRANCE_EMERGENCY_SOFTSUIT_HELMET 0
+
+//* Storage
+
+#define ITEM_ENCUMBRANCE_STORAGE_BACKPACK 5
+#define ITEM_ENCUMBRANCE_STORAGE_DUFFLEBAG 5
+#define ITEM_ENCUMBRANCE_STORAGE_POUCH_LARGE 5
+
+//* Species
+
+#define ITEM_ENCUMBRANCE_PHORONOID_SUIT 20
+#define ITEM_ENCUMBRANCE_PHORONOID_HELMET 0
+#define ITEM_ENCUMBRANCE_TAJARAN_SWORDSMAN_ARMOR 20
+
+//* Weapons
+
+#define ITEM_ENCUMBRANCE_GUN_LIGHT 2.5
+#define ITEM_ENCUMBRANCE_GUN_NORMAL 5
+#define ITEM_ENCUMBRANCE_GUN_LARGE 7.5
+#define ITEM_ENCUMBRANCE_GUN_BULKY 12.5
+#define ITEM_ENCUMBRANCE_GUN_UNREASONABLE 17.5
+#define ITEM_ENCUMBRANCE_GUN_RIDICULOUS 30
+#define ITEM_ENCUMBRANCE_GUN_VEHICLE 60
+
+#define ITEM_ENCUMBRANCE_MELEE_SPEAR 15
+#define ITEM_ENCUMBRANCE_MELEE_SLEDGEHAMMER 20
+
+#define ITEM_ENCUMBRANCE_SHIELD_TOWER 30
+
+//? Item Flat Encumbrance defines
+
+#define ITEM_FLAT_ENCUMBRANCE_DUFFLEBAG 30
+#define ITEM_FLAT_ENCUMBRANCE_GALOSHES 30
+#define ITEM_FLAT_ENCUMBRANCE_SHOES_CLOWN 30
+#define ITEM_FLAT_ENCUMBRANCE_SHOES_FINS 30
+
+//? Item Weight defines
+
+#define ITEM_WEIGHT_BASELINE 0
+
+//* Armor
+
+#define ITEM_WEIGHT_ARMOR_ULTRALIGHT 0
+#define ITEM_WEIGHT_ARMOR_LIGHT 0
+#define ITEM_WEIGHT_ARMOR_MEDIUM 0
+#define ITEM_WEIGHT_ARMOR_HEAVY 0
+#define ITEM_WEIGHT_ARMOR_SUPERHEAVY 0
+#define ITEM_WEIGHT_ARMOR_SPECIALIZED 0
+
+#define ITEM_WEIGHT_ARMOR_ULTRALIGHT_HELMET 0
+#define ITEM_WEIGHT_ARMOR_LIGHT_HELMET 0
+#define ITEM_WEIGHT_ARMOR_MEDIUM_HELMET 0
+#define ITEM_WEIGHT_ARMOR_HEAVY_HELMET 0
+#define ITEM_WEIGHT_ARMOR_SUPERHEAVY_HELMET 0
+#define ITEM_WEIGHT_ARMOR_SPECIALIZED_HELMET 0
+
+#define ITEM_WEIGHT_ARMOR_ULTRALIGHT_GLOVES 0
+#define ITEM_WEIGHT_ARMOR_LIGHT_GLOVES 0
+#define ITEM_WEIGHT_ARMOR_MEDIUM_GLOVES 0
+#define ITEM_WEIGHT_ARMOR_HEAVY_GLOVES 0
+#define ITEM_WEIGHT_ARMOR_SUPERHEAVY_GLOVES 0
+#define ITEM_WEIGHT_ARMOR_SPECIALIZED_GLOVES 0
+
+#define ITEM_WEIGHT_ARMOR_ULTRALIGHT_BOOTS 0
+#define ITEM_WEIGHT_ARMOR_LIGHT_BOOTS 0
+#define ITEM_WEIGHT_ARMOR_MEDIUM_BOOTS 0
+#define ITEM_WEIGHT_ARMOR_HEAVY_BOOTS 0
+#define ITEM_WEIGHT_ARMOR_SUPERHEAVY_BOOTS 0
+#define ITEM_WEIGHT_ARMOR_SPECIALIZED_BOOTS 0
+
+#define ITEM_WEIGHT_ARMOR_BIORAD_SUIT 0
+#define ITEM_WEIGHT_ARMOR_BIORAD_SUIT_HELMET 0
+#define ITEM_WEIGHT_ARMOR_BOMB_SUIT 0
+#define ITEM_WEIGHT_ARMOR_BOMB_HELMET 0
+#define ITEM_WEIGHT_ARMOR_FIRE_SUIT 0
+#define ITEM_WEIGHT_ARMOR_FIRE_SUIT_HELMET 0
+
+#define ITEM_WEIGHT_ARMOR_MEDIEVAL_PLATE 0
+#define ITEM_WEIGHT_ARMOR_MEDIEVAL_CHAIN 0
+
+#define ITEM_WEIGHT_ARMOR_ANOMALY 0
+#define ITEM_WEIGHT_ARMOR_ANOMALY_HELMET 0
+
+//* Clothing
+
+//* Items
+
+#define ITEM_WEIGHT_GAS_TANK 0
+#define ITEM_WEIGHT_VEHICLE_FRAME 0
+
+//* Spacesuits / RIGs
+
+#define ITEM_WEIGHT_SOFTSUIT 0
+#define ITEM_WEIGHT_SOFTSUIT_HELMET 0
+
+#define ITEM_WEIGHT_VOIDSUIT 0
+#define ITEM_WEIGHT_VOIDSUIT_HELMET 0
+#define ITEM_WEIGHT_VOIDSUIT_LIGHT 0
+#define ITEM_WEIGHT_VOIDSUIT_HELMET_LIGHT 0
+#define ITEM_WEIGHT_VOIDSUIT_HEAVY 0
+#define ITEM_WEIGHT_VOIDSUIT_HELMET_HEAVY 0
+#define ITEM_WEIGHT_VOIDSUIT_ULTRALIGHT 0
+#define ITEM_WEIGHT_VOIDSUIT_HELMET_ULTRALIGHT 0
+
+#define ITEM_WEIGHT_VOIDSUIT_ANOMALY 0
+#define ITEM_WEIGHT_VOIDSUIT_ANOMALY_HELMET 0
+
+#define ITEM_WEIGHT_LEGACY_RIG_LIGHT 0
+#define ITEM_WEIGHT_LEGACY_RIG 0
+#define ITEM_WEIGHT_LEGACY_RIG_HEAVY 0
+
+#define ITEM_WEIGHT_EMERGENCY_SOFTSUIT 0
+#define ITEM_WEIGHT_EMERGENCY_SOFTSUIT_HELMET 0
+
+//* Species
+
+#define ITEM_WEIGHT_TAJARAN_SWORDSMAN_ARMOR 0
+#define ITEM_WEIGHT_PHORONOID_SUIT 0
+#define ITEM_WEIGHT_PHORONOID_HELMET 0
+
+//* Storage
+
+#define ITEM_WEIGHT_STORAGE_DUFFLEBAG 0
+#define ITEM_WEIGHT_STORAGE_BACKPACK 0
+#define ITEM_WEIGHT_STORAGE_POUCH_LARGE 0
+
+//* Tools
+
+#define ITEM_WEIGHT_HYBRID_TOOLS 0
+
+//* Weapons
+
+#define ITEM_WEIGHT_GUN_LIGHT 0
+#define ITEM_WEIGHT_GUN_NORMAL 0
+#define ITEM_WEIGHT_GUN_LARGE 0
+#define ITEM_WEIGHT_GUN_BULKY 0
+#define ITEM_WEIGHT_GUN_UNREASONABLE 0
+#define ITEM_WEIGHT_GUN_RIDICULOUS 0
+#define ITEM_WEIGHT_GUN_VEHICLE 0
+
+#define ITEM_WEIGHT_MELEE_SPEAR 0
+
+//* Antags
+
+#define ITEM_WEIGHT_CHANGELING_ARMOR 0
+#define ITEM_WEIGHT_CULT_VOIDSUIT_HELMET 0
+#define ITEM_WEIGHT_CULT_VOIDSUIT 0
+#define ITEM_WEIGHT_TECHNOMANCER_BULKY_CORE 0
diff --git a/code/__DEFINES/items_clothing.dm b/code/__DEFINES/items_clothing.dm
index 4053ccf656bb..6c463461f061 100644
--- a/code/__DEFINES/items_clothing.dm
+++ b/code/__DEFINES/items_clothing.dm
@@ -1,6 +1,4 @@
-/// How much shoes slow you down by default. Negative values speed you up.
-#define SHOES_SLOWDOWN 0
/// For how bright candles are.
#define CANDLE_LUM 3
diff --git a/code/__DEFINES/movespeed_modification.dm b/code/__DEFINES/movespeed_modification.dm
index 452b9fc97855..4a16ca58bfaf 100644
--- a/code/__DEFINES/movespeed_modification.dm
+++ b/code/__DEFINES/movespeed_modification.dm
@@ -1,8 +1,52 @@
-//! movespeed_modifier_flags
+//* movespeed_modifier_flags
// None yet
-//! Conflicts IDs
+//* calculation_type
+
+/// just use multiplicative_slowdown
+#define MOVESPEED_CALCULATION_HYPERBOLIC "hyperbolic"
+/// use multiplicative_slowdown and TILE_BOOST calculations
+#define MOVESPEED_CALCULATION_HYPERBOLIC_BOOST "hyperbolic_boost"
+/// use % change and TILE_BOOST calculations
+#define MOVESPEED_CALCULATION_MULTIPLY "multiply"
+/// legacy multiply
+//! TODO: REMOVE THIS SHIT
+#define MOVESPEED_CALCULATION_LEGACY_MULTIPLY "legacy_multiply"
+
+DEFINE_ENUM(movespeed_modifier_calculation_type, list(
+ /datum/movespeed_modifier = list(
+ "calculation_type",
+ ),
+), list(
+ ENUM("Hyperbolic", MOVESPEED_CALCULATION_HYPERBOLIC),
+ ENUM("Hyperbolic w/ Limit", MOVESPEED_CALCULATION_HYPERBOLIC_BOOST),
+ ENUM("Multiply", MOVESPEED_CALCULATION_MULTIPLY),
+ ENUM("Legacy Multiply", MOVESPEED_CALCULATION_LEGACY_MULTIPLY),
+))
+
+//* params for add_or_update_variable_movespeed_modifier
+
+/// multiplicative_slowdown
+#define MOVESPEED_PARAM_DELAY_MOD "delay"
+/// multiply_speed
+#define MOVESPEED_PARAM_MULTIPLY_SPEED "multiply"
+/// absolute_max_tiles_per_second
+#define MOVESPEED_PARAM_MAX_TILE_ABSOLUTE "absolute_tiles"
+/// max_tiles_per_second_boost
+#define MOVESPEED_PARAM_MAX_TILE_BOOST "max_tlies"
+
+//* Constants
+
+/// minimum movespeed
+#define MOVESPEED_ABSOLUTE_MINIMUM_TILES_PER_SECOND 0.25
+
+//* Priorities - Lower is applied first
+
+#define MOVESPEED_PRIORITY_DEFAULT 0
+#define MOVESPEED_PRIORITY_CARRY_WEIGHT 10
+
+//* Conflicts IDs
// None yet
-//! IDs
+//* IDs
// None yet
diff --git a/code/__DEFINES/tgui.dm b/code/__DEFINES/tgui.dm
index bdc4055e5556..a3eaf187df97 100644
--- a/code/__DEFINES/tgui.dm
+++ b/code/__DEFINES/tgui.dm
@@ -1,4 +1,4 @@
-// ui_status
+//* ui_status
/// Green eye; fully interactive
#define UI_INTERACTIVE 2
/// Orange eye; updates but is not interactive
@@ -8,7 +8,7 @@
/// UI Should close
#define UI_CLOSE -1
-// refreshing var
+//* refreshing var
/// no refresh queued
#define UI_NOT_REFRESHING 0
/// soft refreshing - can show a status, won't block viewport
@@ -46,6 +46,7 @@
"%7b%22type%22%3a%22[type]%22%2c%22payload%22%3a[url_encode(json_encode(payload))]%7d" \
)
+//* Legacy Modal Stuff
/// Max length for Modal Input
#define UI_MODAL_INPUT_MAX_LENGTH 1024
@@ -56,3 +57,21 @@
#define UI_MODAL_DELEGATE 2
#define UI_MODAL_ANSWER 3
#define UI_MODAL_CLOSE 4
+
+//* tgui dynamic input
+//* all constraints must be specified if it is included.
+
+#define TGUI_INPUT_DATA_TYPE "type"
+#define TGUI_INPUT_DATA_DESC "desc"
+#define TGUI_INPUT_DATA_NAME "name"
+#define TGUI_INPUT_DATA_CONSTRAINTS "constraints"
+#define TGUI_INPUT_DATA_DEFAULT "default"
+
+/// constraints: [maxlength]
+#define TGUI_INPUT_DATATYPE_TEXT "text"
+/// constraints: [min, max, round]
+#define TGUI_INPUT_DATATYPE_NUM "num"
+/// constraints (required): [str1, str2, ...]
+#define TGUI_INPUT_DATATYPE_LIST_PICK "list_single"
+/// constraints: nothing
+#define TGUI_INPUT_DATATYPE_TOGGLE "bool"
diff --git a/code/__DEFINES/vv.dm b/code/__DEFINES/vv.dm
index c911c5e2b3ed..74f97ebc4be1 100644
--- a/code/__DEFINES/vv.dm
+++ b/code/__DEFINES/vv.dm
@@ -96,6 +96,10 @@
#define VV_HK_EDIT_COLOR_MATRIX "edit_color_matrix"
#define VV_HK_EDIT_ARMOR "edit_armor"
+// /mob
+#define VV_HK_ADD_PHYSIOLOGY_MODIFIER "add_physiology_mod"
+#define VV_HK_REMOVE_PHYSIOLOGY_MODIFIER "remove_physiology_mod"
+
/*
// /obj
#define VV_HK_OSAY "osay"
diff --git a/code/datums/status_effects/grouped/staggered.dm b/code/datums/status_effects/grouped/staggered.dm
index 88e17df556ea..0d082c8b393f 100644
--- a/code/datums/status_effects/grouped/staggered.dm
+++ b/code/datums/status_effects/grouped/staggered.dm
@@ -15,7 +15,9 @@
if(applied_highest == highest)
return
applied_highest = highest
- owner.add_or_update_variable_movespeed_modifier(/datum/movespeed_modifier/mob_staggered, multiplicative_slowdown = highest)
+ owner.add_or_update_variable_movespeed_modifier(/datum/movespeed_modifier/mob_staggered, params = list(
+ MOVESPEED_PARAM_DELAY_MOD = highest
+ ))
/datum/status_effect/grouped/staggered/on_remove()
. = ..()
diff --git a/code/game/gamemodes/changeling/powers/armor.dm b/code/game/gamemodes/changeling/powers/armor.dm
index 4d3753a5f2b0..fec2083c9f33 100644
--- a/code/game/gamemodes/changeling/powers/armor.dm
+++ b/code/game/gamemodes/changeling/powers/armor.dm
@@ -64,11 +64,8 @@
action_button_name = "Toggle Grippers"
clothing_flags = NONE
item_flags = ITEM_DROPDEL
-
-/obj/item/clothing/shoes/magboots/changeling/set_slowdown()
- slowdown = worn_over? max(SHOES_SLOWDOWN, worn_over.slowdown): SHOES_SLOWDOWN //So you can't put on magboots to make you walk faster.
- if (magpulse)
- slowdown += 1 //It's already tied to a slowdown suit, 6 slowdown is huge.
+ encumbrance = ITEM_ENCUMBRANCE_CHANGELING_MAGBOOTS
+ encumbrance_on = ITEM_ENCUMBRANCE_CHANGELING_MAGBOOTS_PULSE
/obj/item/clothing/shoes/magboots/changeling/attack_self(mob/user)
. = ..()
@@ -97,7 +94,7 @@
armor_type = /datum/armor/changeling/chitin
siemens_coefficient = 0.3
max_heat_protection_temperature = FIRESUIT_MAX_HEAT_PROTECTION_TEMPERATURE
- slowdown = 3
+ weight = ITEM_WEIGHT_CHANGELING_ARMOR
/obj/item/clothing/suit/space/changeling/armored/Initialize(mapload)
. = ..()
diff --git a/code/game/gamemodes/cult/cult_items.dm b/code/game/gamemodes/cult/cult_items.dm
index 7910cef20798..ef9ea2a2578e 100644
--- a/code/game/gamemodes/cult/cult_items.dm
+++ b/code/game/gamemodes/cult/cult_items.dm
@@ -118,6 +118,8 @@
icon_state = "culthelm"
origin_tech = list(TECH_MATERIAL = 3, TECH_ARCANE = 1)
armor_type = /datum/armor/cult/space
+ encumbrance = ITEM_ENCUMBRANCE_CULT_VOIDSUIT_HELMET
+ weight = ITEM_WEIGHT_CULT_VOIDSUIT_HELMET
siemens_coefficient = 0
worn_render_flags = WORN_RENDER_SLOT_ONE_FOR_ALL
@@ -132,7 +134,8 @@
desc = "A bulky suit of armour, bristling with spikes. It looks space-worthy."
w_class = ITEMSIZE_NORMAL
allowed = list(/obj/item/book/tome,/obj/item/melee/cultblade,/obj/item/tank/emergency/oxygen,/obj/item/suit_cooling_unit)
- slowdown = 1
+ weight = ITEM_WEIGHT_CULT_VOIDSUIT
+ encumbrance = ITEM_ENCUMBRANCE_CULT_VOIDSUIT
armor_type = /datum/armor/cult/space
siemens_coefficient = 0
inv_hide_flags = HIDEGLOVES|HIDEJUMPSUIT|HIDETAIL|HIDETIE|HIDEHOLSTER
diff --git a/code/game/gamemodes/technomancer/core_obj.dm b/code/game/gamemodes/technomancer/core_obj.dm
index 3fae544560f0..969012419559 100644
--- a/code/game/gamemodes/technomancer/core_obj.dm
+++ b/code/game/gamemodes/technomancer/core_obj.dm
@@ -262,7 +262,7 @@
energy = 20000
max_energy = 20000
regen_rate = 25 //800 seconds to full
- slowdown = 1
+ weight = ITEM_WEIGHT_TECHNOMANCER_BULKY_CORE
instability_modifier = 1.0
spell_power_modifier = 1.4
diff --git a/code/game/gamemodes/technomancer/devices/shield_armor.dm b/code/game/gamemodes/technomancer/devices/shield_armor.dm
index 273428c41735..9317fb7f230f 100644
--- a/code/game/gamemodes/technomancer/devices/shield_armor.dm
+++ b/code/game/gamemodes/technomancer/devices/shield_armor.dm
@@ -16,7 +16,7 @@
require a very potent supply of an energy of some kind in order to function."
icon_state = "shield_armor_0"
blood_overlay_type = "armor"
- slowdown = 0
+ weight = ITEM_WEIGHT_BASELINE
armor_type = /datum/armor/none
action_button_name = "Toggle Shield Projector"
var/active = 0
diff --git a/code/game/gamemodes/technomancer/devices/tesla_armor.dm b/code/game/gamemodes/technomancer/devices/tesla_armor.dm
index 03668e4990e0..534079ef42b2 100644
--- a/code/game/gamemodes/technomancer/devices/tesla_armor.dm
+++ b/code/game/gamemodes/technomancer/devices/tesla_armor.dm
@@ -12,7 +12,7 @@
desc = "This rather dangerous looking armor will hopefully shock your enemies, and not you in the process."
icon_state = "tesla_armor_1" //wip
blood_overlay_type = "armor"
- slowdown = 1
+ weight = ITEM_WEIGHT_BASELINE
armor_type = /datum/armor/none
action_button_name = "Toggle Tesla Armor"
var/active = 1 //Determines if the armor will zap or block
diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm
index ecf0da767c20..e232a0c21a10 100644
--- a/code/game/objects/items.dm
+++ b/code/game/objects/items.dm
@@ -11,7 +11,7 @@
//? Flags
/// Item flags.
/// These flags are listed in [code/__DEFINES/inventory/item_flags.dm].
- var/item_flags = NONE
+ var/item_flags = ITEM_ENCUMBERS_WHILE_HELD
/// Miscellaneous flags pertaining to equippable objects.
/// These flags are listed in [code/__DEFINES/inventory/item_flags.dm].
var/clothing_flags = NONE
@@ -36,6 +36,25 @@
/// economic category for items
var/economic_category_item = ECONOMIC_CATEGORY_ITEM_DEFAULT
+ //? Carry Weight
+ /// encumberance.
+ /// calculated as max() of all encumbrance
+ /// result is calculated into slowdown value
+ /// and then max()'d with carry weight for the final slowdown used.
+ var/encumbrance = ITEM_ENCUMBRANCE_BASELINE
+ /// registered encumbrance - null if not in inventory
+ var/encumbrance_registered
+ /// carry weight in kgs. this might be generalized later so KEEP IT REALISTIC.
+ var/weight = ITEM_WEIGHT_BASELINE
+ /// registered carry weight - null if not in inventory.
+ var/weight_registered
+ /// flat encumbrance - while worn, you are treated as at **least** this encumbered
+ /// e.g. if someone is wearing a flat 50 encumbrance item, but their regular encumbrance tally is only 45, they still have 50 total.
+ var/flat_encumbrance = 0
+ /// Hard slowdown. Applied before carry weight.
+ /// This affects multiplicative movespeed.
+ var/slowdown = 0
+
//? Combat
/// Amount of damage we do on melee.
var/damage_force = 0
@@ -99,8 +118,6 @@
var/permeability_coefficient = 1
/// For electrical admittance/conductance (electrocution checks and shit)
var/siemens_coefficient = 1
- /// How much clothing is slowing you down. Negative values speeds you up
- var/slowdown = 0
/// Suit storage stuff.
var/list/allowed = null
/// All items can have an uplink hidden inside, just remember to add the triggers.
@@ -239,6 +256,40 @@
/obj/item/examine(mob/user, dist)
. = ..()
. += "[gender == PLURAL ? "They are" : "It is"] a [weightclass2text(w_class)] item."
+ switch(get_encumbrance())
+ if(-INFINITY to 0.1)
+ . += "It looks effortless to carry around and wear."
+ if(0.1 to 0.75)
+ . += "It looks very easy to carry around and wear."
+ if(0.75 to 2)
+ . += "It looks decently able to be carried around and worn."
+ if(2 to 5)
+ . += "It looks somewhat unwieldly."
+ if(5 to 10)
+ . += "It looks quite unwieldly."
+ if(10 to 20)
+ . += "It looks very unwieldly. It would take a good effort to run around with it."
+ if(20 to 40)
+ . += "It looks extremely unwieldly. You probably will have a hard time running with it."
+ if(40 to INFINITY)
+ . += "It's so unwieldly that it's a surprise you can hold it at all. You really won't be doing much running with it."
+ switch(get_weight())
+ if(-INFINITY to 0.1)
+ . += "It looks like it weighs practically nothing."
+ if(0.1 to 0.75)
+ . += "It looks like it weighs very little."
+ if(0.75 to 2)
+ . += "It looks like it's decently lightweight."
+ if(2 to 5)
+ . += "It looks like it weighs a bit."
+ if(5 to 10)
+ . += "It looks like it weighs a good amount."
+ if(10 to 20)
+ . += "It looks like it is heavy. It would take a good effort to run around with it."
+ if(20 to 40)
+ . += "It looks like it weighs a lot. You probably will have a hard time running with it."
+ if(40 to INFINITY)
+ . += "It looks like it weighs a ton. You really won't be doing much running with it."
// if(resistance_flags & INDESTRUCTIBLE)
// . += "[src] seems extremely robust! It'll probably withstand anything that could happen to it!"
@@ -753,6 +804,81 @@ modules/mob/living/carbon/human/life.dm if you die, you will be zoomed out.
// . = ..()
// update_action_buttons()
+//? Carry Weight
+
+/obj/item/proc/get_weight()
+ return weight
+
+/obj/item/proc/get_encumbrance()
+ return encumbrance
+
+/obj/item/proc/get_flat_encumbrance()
+ return flat_encumbrance
+
+/obj/item/proc/update_weight()
+ if(isnull(weight_registered))
+ return null
+ . = get_weight()
+ if(. == weight_registered)
+ return 0
+ . -= weight_registered
+ var/mob/living/wearer = worn_mob()
+ if(istype(wearer))
+ wearer.adjust_current_carry_weight(.)
+
+/obj/item/proc/update_encumbrance()
+ if(isnull(encumbrance_registered))
+ return null
+ . = get_encumbrance()
+ if(. == encumbrance_registered)
+ return 0
+ . -= encumbrance_registered
+ encumbrance_registered += .
+ var/mob/living/wearer = worn_mob()
+ if(istype(wearer))
+ wearer.adjust_current_carry_encumbrance(.)
+
+/obj/item/proc/update_flat_encumbrance()
+ var/mob/living/wearer = worn_mob()
+ if(istype(wearer))
+ wearer.recalculate_carry()
+
+/obj/item/proc/set_weight(amount)
+ if(amount == weight)
+ return
+ var/old = weight
+ weight = amount
+ update_weight()
+ propagate_weight(old, weight)
+
+/obj/item/proc/set_encumbrance(amount)
+ if(amount == encumbrance)
+ return
+ encumbrance = amount
+ update_encumbrance()
+
+/obj/item/proc/set_flat_encumbrance(amount)
+ if(amount == flat_encumbrance)
+ return
+ flat_encumbrance = amount
+ update_flat_encumbrance()
+
+/obj/item/proc/set_slowdown(amount)
+ if(amount == slowdown)
+ return
+ slowdown = amount
+ worn_mob()?.update_item_slowdown()
+
+/obj/item/proc/propagate_weight(old_weight, new_weight)
+ if(!(item_flags & ITEM_IN_STORAGE))
+ return
+ var/obj/item/storage/S = loc
+ if(!istype(S))
+ return
+ S.stored_weight_changed(src, old_weight, new_weight)
+
+//? Attack Verbs
+
/**
* grabs an attack verb to use
*
@@ -829,3 +955,34 @@ modules/mob/living/carbon/human/life.dm if you die, you will be zoomed out.
/obj/item/proc/running_mob_armor(damage, tier, flag, mode, attack_type, datum/weapon, target_zone)
damage = fetch_armor().resultant_damage(damage, tier, flag)
return args.Copy()
+
+//? VV
+
+/obj/item/vv_edit_var(var_name, var_value, mass_edit, raw_edit)
+ switch(var_name)
+ if(NAMEOF(src, item_flags))
+ var/requires_update = (item_flags & (ITEM_ENCUMBERS_WHILE_HELD | ITEM_ENCUMBERS_ONLY_HELD)) != (var_value & (ITEM_ENCUMBERS_WHILE_HELD | ITEM_ENCUMBERS_ONLY_HELD))
+ . = ..()
+ if(. && requires_update)
+ var/mob/living/L = worn_mob()
+ // check, as worn_mob() returns /mob, not /living
+ if(istype(L))
+ L.recalculate_carry()
+ L.update_carry()
+ if(NAMEOF(src, weight), NAMEOF(src, encumbrance), NAMEOF(src, flat_encumbrance))
+ // todo: introspection system update - this should be 'handled', as opposed to hooked.
+ . = ..()
+ if(. )
+ var/mob/living/L = worn_mob()
+ // check, as worn_mob() returns /mob, not /living
+ if(istype(L))
+ L.update_carry_slowdown()
+ if(NAMEOF(src, slowdown))
+ . = ..()
+ if(. )
+ var/mob/living/L = worn_mob()
+ // check, as worn_mob() returns /mob, not /living
+ if(istype(L))
+ L.update_item_slowdown()
+ else
+ return ..()
diff --git a/code/game/objects/items/bodybag.dm b/code/game/objects/items/bodybag.dm
index 049c28f77898..a1c7f27e5480 100644
--- a/code/game/objects/items/bodybag.dm
+++ b/code/game/objects/items/bodybag.dm
@@ -7,14 +7,20 @@
icon_state = "bodybag_folded"
w_class = ITEMSIZE_SMALL
+ var/bag_type = /obj/structure/closet/body_bag
+
/obj/item/bodybag/attack_self(mob/user)
. = ..()
if(.)
return
- var/obj/structure/closet/body_bag/R = new /obj/structure/closet/body_bag(user.loc)
- R.add_fingerprint(user)
+ add_fingerprint(user)
+ create_bag(user.drop_location())
qdel(src)
+/obj/item/bodybag/proc/create_bag(atom/where)
+ var/obj/structure/closet/body_bag/bag = new bag_type(where)
+ transfer_fingerprints_to(bag)
+ return bag
/obj/item/storage/box/bodybags
name = "body bags"
@@ -31,7 +37,6 @@
new /obj/item/bodybag(src)
new /obj/item/bodybag(src)
-
/obj/structure/closet/body_bag
name = "body bag"
desc = "A plastic bag designed for the storage and transportation of cadavers."
@@ -127,18 +132,17 @@
icon_state = "bodybag_folded"
item_state = "bodybag_cryo_folded"
origin_tech = list(TECH_BIO = 4)
+
var/obj/item/reagent_containers/syringe/syringe
-/obj/item/bodybag/cryobag/attack_self(mob/user)
- . = ..()
- if(.)
+/obj/item/bodybag/cryobag/create_bag(atom/where)
+ var/obj/structure/closet/body_bag/cryobag/bag = ..()
+ if(!istype(bag))
return
- var/obj/structure/closet/body_bag/cryobag/R = new /obj/structure/closet/body_bag/cryobag(user.loc)
- R.add_fingerprint(user)
- if(syringe)
- R.syringe = syringe
+ if(!isnull(syringe))
+ bag.syringe = syringe
syringe = null
- qdel(src)
+ return bag
/obj/structure/closet/body_bag/cryobag
name = "stasis bag"
@@ -148,7 +152,6 @@
item_path = /obj/item/bodybag/cryobag
store_misc = 0
store_items = 0
- var/used = 0
var/obj/item/tank/tank = null
var/tank_type = /obj/item/tank/stasis/oxygen
var/stasis_level = 3 //Every 'this' life ticks are applied to the mob (when life_ticks%stasis_level == 1)
@@ -163,24 +166,6 @@
QDEL_NULL(tank)
return ..()
-/obj/structure/closet/body_bag/cryobag/attack_hand(mob/user, list/params)
- if(used)
- var/confirm = tgui_alert(user, "Are you sure you want to open \the [src]? \The [src] will expire upon opening it.", "Confirm Opening", list("No", "Yes"))
- if(confirm == "Yes")
- ..() // Will call `toggle()` and open the bag.
- else
- ..()
-
-/obj/structure/closet/body_bag/cryobag/open()
- . = ..()
- if(used)
- var/obj/item/O = new/obj/item(src.loc)
- O.name = "used [name]"
- O.icon = src.icon
- O.icon_state = "bodybag_used"
- O.desc = "Pretty useless now..."
- qdel(src)
-
/obj/structure/closet/body_bag/cryobag/OnMouseDropLegacy(over_object, src_location, over_location)
. = ..()
if(. && syringe)
@@ -192,7 +177,6 @@
if(ishuman(AM))
var/mob/living/carbon/human/H = AM
H.Stasis(stasis_level)
- src.used = 1
inject_occupant(H)
if(istype(AM, /obj/item/organ))
@@ -256,12 +240,9 @@
else if(W.is_screwdriver())
if(syringe)
- if(used)
- to_chat(user,"The injector cannot be removed now that the stasis bag has been used!")
- else
- syringe.forceMove(src.loc)
- to_chat(user,"You pry \the [syringe] out of \the [src].")
- syringe = null
+ syringe.forceMove(src.loc)
+ to_chat(user,"You pry \the [syringe] out of \the [src].")
+ syringe = null
else
..()
diff --git a/code/game/objects/items/devices/body_snatcher_vr.dm b/code/game/objects/items/devices/body_snatcher_vr.dm
index a89be30cd710..1d90d5dea57b 100644
--- a/code/game/objects/items/devices/body_snatcher_vr.dm
+++ b/code/game/objects/items/devices/body_snatcher_vr.dm
@@ -5,7 +5,7 @@
icon = 'icons/obj/device_alt.dmi'
icon_state = "sleevemate" //Give this a fancier sprite later.
item_state = "healthanalyzer"
- item_flags = ITEM_NOBLUDGEON
+ item_flags = ITEM_NOBLUDGEON | ITEM_ENCUMBERS_WHILE_HELD
slot_flags = SLOT_BELT
w_class = ITEMSIZE_SMALL
materials = list(MAT_STEEL = 200)
diff --git a/code/game/objects/items/devices/communicator/communicator.dm b/code/game/objects/items/devices/communicator/communicator.dm
index f1a4ea328e8e..fe74a7a448a4 100644
--- a/code/game/objects/items/devices/communicator/communicator.dm
+++ b/code/game/objects/items/devices/communicator/communicator.dm
@@ -351,7 +351,7 @@ var/global/list/obj/item/communicator/all_communicators = list()
communications across different stations, planets, or even star systems. You can wear this one on your wrist!"
icon = 'icons/obj/device.dmi'
icon_state = "commwatch"
- item_flags = CLOTHING_ALLOW_SINGLE_LIMB
+ item_flags = CLOTHING_ALLOW_SINGLE_LIMB | ITEM_ENCUMBERS_WHILE_HELD
slot_flags = SLOT_GLOVES
/obj/item/communicator/watch/update_icon_state()
diff --git a/code/game/objects/items/devices/holowarrant.dm b/code/game/objects/items/devices/holowarrant.dm
index d4caf4057537..3713cbfcc7fc 100644
--- a/code/game/objects/items/devices/holowarrant.dm
+++ b/code/game/objects/items/devices/holowarrant.dm
@@ -4,7 +4,7 @@
desc = "The practical paperwork replacement for the officer on the go."
icon_state = "holowarrant"
item_state = "flashtool"
- item_flags = ITEM_NOBLUDGEON
+ item_flags = ITEM_NOBLUDGEON | ITEM_ENCUMBERS_WHILE_HELD
throw_force = 5
w_class = ITEMSIZE_SMALL
throw_speed = 4
diff --git a/code/game/objects/items/glassjar.dm b/code/game/objects/items/glassjar.dm
index 5b5e9ca52c11..7b2eb3d858a3 100644
--- a/code/game/objects/items/glassjar.dm
+++ b/code/game/objects/items/glassjar.dm
@@ -5,7 +5,7 @@
icon_state = "jar"
w_class = ITEMSIZE_SMALL
materials = list(MAT_GLASS = 200)
- item_flags = ITEM_NOBLUDGEON
+ item_flags = ITEM_NOBLUDGEON | ITEM_ENCUMBERS_WHILE_HELD
var/list/accept_mobs = list(/mob/living/simple_mob/animal/passive/lizard, /mob/living/simple_mob/animal/passive/mouse, /mob/living/simple_mob/animal/sif/leech, /mob/living/simple_mob/animal/sif/frostfly, /mob/living/simple_mob/animal/sif/glitterfly)
var/contains = 0 // 0 = nothing, 1 = money, 2 = animal, 3 = spiderling
drop_sound = 'sound/items/drop/glass.ogg'
diff --git a/code/game/objects/items/holosign_creator.dm b/code/game/objects/items/holosign_creator.dm
index 12c53c4f2d8a..74fb53fece44 100644
--- a/code/game/objects/items/holosign_creator.dm
+++ b/code/game/objects/items/holosign_creator.dm
@@ -9,7 +9,7 @@
throw_force = 0
throw_speed = 3
throw_range = 7
- item_flags = ITEM_NOBLUDGEON
+ item_flags = ITEM_NOBLUDGEON | ITEM_ENCUMBERS_WHILE_HELD
var/list/signs = list()
var/max_signs = 10
var/creation_time = 0 //time to create a holosign in deciseconds.
diff --git a/code/game/objects/items/offhand.dm b/code/game/objects/items/offhand.dm
index 2cd8c8eec887..e19c0fa67f0a 100644
--- a/code/game/objects/items/offhand.dm
+++ b/code/game/objects/items/offhand.dm
@@ -6,7 +6,7 @@
/obj/item/offhand
name = "broken offhand"
desc = "fire coderbus"
- item_flags = ITEM_DROPDEL | ITEM_ABSTRACT | ITEM_NOBLUDGEON
+ item_flags = ITEM_DROPDEL | ITEM_ABSTRACT | ITEM_NOBLUDGEON | ITEM_ENCUMBERS_WHILE_HELD
icon = 'icons/obj/item/abstract.dmi'
icon_state = "offhand"
drop_sound = null
diff --git a/code/game/objects/items/robobag.dm b/code/game/objects/items/robobag.dm
index 6b67f589540e..c6de643dd277 100644
--- a/code/game/objects/items/robobag.dm
+++ b/code/game/objects/items/robobag.dm
@@ -7,17 +7,7 @@
icon_state = "bodybag_folded"
item_state = "bodybag_cryo_folded"
origin_tech = list(TECH_ENGINEERING = 3)
-
-/obj/item/bodybag/cryobag/robobag/attack_self(mob/user)
- . = ..()
- if(.)
- return
- var/obj/structure/closet/body_bag/cryobag/robobag/R = new /obj/structure/closet/body_bag/cryobag/robobag(user.loc)
- R.add_fingerprint(user)
- if(syringe)
- R.syringe = syringe
- syringe = null
- qdel(src)
+ bag_type = /obj/structure/closet/body_bag/cryobag/robobag
/obj/structure/closet/body_bag/cryobag/robobag
name = "synthmorph bag"
@@ -76,10 +66,7 @@
if(ishuman(AM))
var/mob/living/carbon/human/H = AM
if(H.isSynthetic())
- if(H.getToxLoss() == 0) // We don't exactly care about the bag being 'used' when containing a synth, unless it's got work.
- used = FALSE
- else
- H.add_modifier(/datum/modifier/fbp_debug/robobag)
+ H.add_modifier(/datum/modifier/fbp_debug/robobag)
/obj/structure/closet/body_bag/cryobag/robobag/attackby(obj/item/W, mob/user)
if(opened)
diff --git a/code/game/objects/items/robot/gripper.dm b/code/game/objects/items/robot/gripper.dm
index e3a3e6c5e392..804f19880000 100644
--- a/code/game/objects/items/robot/gripper.dm
+++ b/code/game/objects/items/robot/gripper.dm
@@ -7,7 +7,7 @@
Using an object on the gripper will interact with the item inside it, if it exists, instead."
icon = 'icons/obj/device.dmi'
icon_state = "gripper"
- item_flags = ITEM_NOBLUDGEON
+ item_flags = ITEM_NOBLUDGEON | ITEM_ENCUMBERS_WHILE_HELD
//Has a list of items that it can hold.
var/list/can_hold = list(
diff --git a/code/game/objects/items/stacks/sheets/leather.dm b/code/game/objects/items/stacks/sheets/leather.dm
index 4622ff7543b0..61d6a5f4077c 100644
--- a/code/game/objects/items/stacks/sheets/leather.dm
+++ b/code/game/objects/items/stacks/sheets/leather.dm
@@ -140,7 +140,6 @@
desc = "Pieces of a goliath's rocky hide, these might be able to make your suit a bit more durable to attack from the local fauna."
icon_state = "sheet-goliath_hide"
singular_name = "hide plate"
- item_flags = ITEM_NOBLUDGEON
w_class = WEIGHT_CLASS_NORMAL
layer = MOB_LAYER
@@ -164,7 +163,6 @@
icon_state = "sheet-dragon_hide"
singular_name = "drake plate"
max_amount = 10
- item_flags = ITEM_NOBLUDGEON
w_class = WEIGHT_CLASS_NORMAL
layer = MOB_LAYER
diff --git a/code/game/objects/items/stock_parts/_stock_parts.dm b/code/game/objects/items/stock_parts/_stock_parts.dm
index 5a275cdef4de..f09075921157 100644
--- a/code/game/objects/items/stock_parts/_stock_parts.dm
+++ b/code/game/objects/items/stock_parts/_stock_parts.dm
@@ -4,7 +4,7 @@
gender = PLURAL
icon = 'icons/obj/stock_parts.dmi'
w_class = ITEMSIZE_SMALL
- item_flags = ITEM_EASY_LATHE_DECONSTRUCT
+ item_flags = ITEM_EASY_LATHE_DECONSTRUCT | ITEM_ENCUMBERS_WHILE_HELD
var/rating = 1
/obj/item/stock_parts/Initialize(mapload)
diff --git a/code/game/objects/items/storage/_storage.dm b/code/game/objects/items/storage/_storage.dm
index 811c90be8cb8..2dbda152e487 100644
--- a/code/game/objects/items/storage/_storage.dm
+++ b/code/game/objects/items/storage/_storage.dm
@@ -38,6 +38,73 @@
var/last_message = 0
+ /// carry weight in us
+ var/weight_cached = 0
+ /// carry weight mitigation, static. applied after multiplicative
+ var/weight_mitigation = 0
+ /// carry weight mitigation, multiplicative.
+ var/weight_multiply = 1
+
+/obj/item/storage/Initialize(mapload)
+ . = ..()
+
+ if(allow_quick_empty)
+ add_obj_verb(src, /obj/item/storage/verb/quick_empty)
+ else
+ remove_obj_verb(src, /obj/item/storage/verb/quick_empty)
+
+ if(allow_quick_gather)
+ add_obj_verb(src, /obj/item/storage/verb/toggle_gathering_mode)
+ else
+ remove_obj_verb(src, /obj/item/storage/verb/toggle_gathering_mode)
+
+ src.boxes = new /atom/movable/screen/storage( )
+ src.boxes.name = "storage"
+ src.boxes.master = src
+ src.boxes.icon_state = "block"
+ src.boxes.screen_loc = storage_ui_default
+
+ src.storage_start = new /atom/movable/screen/storage( )
+ src.storage_start.name = "storage"
+ src.storage_start.master = src
+ src.storage_start.icon_state = "storage_start"
+ src.storage_start.screen_loc = storage_ui_default
+
+ src.storage_continue = new /atom/movable/screen/storage( )
+ src.storage_continue.name = "storage"
+ src.storage_continue.master = src
+ src.storage_continue.icon_state = "storage_continue"
+ src.storage_continue.screen_loc = storage_ui_default
+
+ src.storage_end = new /atom/movable/screen/storage( )
+ src.storage_end.name = "storage"
+ src.storage_end.master = src
+ src.storage_end.icon_state = "storage_end"
+ src.storage_end.screen_loc = storage_ui_default
+
+ src.stored_start = new /atom/movable //we just need these to hold the icon
+ src.stored_start.icon_state = "stored_start"
+
+ src.stored_continue = new /atom/movable
+ src.stored_continue.icon_state = "stored_continue"
+
+ src.stored_end = new /atom/movable
+ src.stored_end.icon_state = "stored_end"
+
+ src.closer = new /atom/movable/screen/close( )
+ src.closer.master = src
+ src.closer.icon_state = "storage_close"
+ src.closer.hud_layerise()
+ orient2hud()
+
+ populate_contents_legacy()
+
+ PopulateContents()
+
+ //calibrate_size() //Let's not!
+
+ reset_weight()
+
/obj/item/storage/Destroy()
close_all()
QDEL_NULL(boxes)
@@ -50,7 +117,34 @@
QDEL_NULL(closer)
return ..()
+/obj/item/storage/get_weight()
+ . = ..()
+ . += max(0, (weight_cached * weight_multiply) - weight_mitigation)
+/obj/item/storage/proc/reset_weight()
+ var/old_weight_cached = weight_cached
+ weight_cached = 0
+ for(var/obj/item/I in contents)
+ weight_cached += I.get_weight()
+ propagate_weight(old_weight_cached, weight_cached)
+ update_weight()
+
+/obj/item/storage/proc/stored_weight_changed(obj/item/I, old_weight, new_weight)
+ var/diff = new_weight - old_weight
+ var/old = weight_cached
+ weight_cached += diff
+ propagate_weight(old, weight_cached)
+ update_weight()
+
+/obj/item/storage/proc/reset_weight_recursive()
+ do_reset_weight_recursive(200)
+
+/obj/item/storage/proc/do_reset_weight_recursive(safety)
+ if(!(safety - 1))
+ CRASH("out of safety")
+ for(var/obj/item/storage/S in contents)
+ S.do_reset_weight_recursive(safety - 1)
+ reset_weight()
/obj/item/storage/AltClick(mob/user)
if(user in is_seeing)
@@ -359,6 +453,9 @@
W.forceMove(src)
W.on_enter_storage(src)
W.item_flags |= ITEM_IN_STORAGE
+ var/old_weight = weight_cached
+ weight_cached += W.get_weight()
+ propagate_weight(old_weight, weight_cached)
if(user)
if(!prevent_warning)
for(var/mob/M in viewers(user))
@@ -407,6 +504,9 @@
W.maptext = ""
W.on_exit_storage(src)
W.item_flags &= ~ITEM_IN_STORAGE
+ var/old_weight = weight_cached
+ weight_cached -= W.get_weight()
+ propagate_weight(old_weight, weight_cached)
update_icon()
return 1
@@ -518,64 +618,6 @@
for(var/obj/item/I in contents)
remove_from_storage(I, T)
-/obj/item/storage/Initialize(mapload)
- . = ..()
-
- if(allow_quick_empty)
- add_obj_verb(src, /obj/item/storage/verb/quick_empty)
- else
- remove_obj_verb(src, /obj/item/storage/verb/quick_empty)
-
- if(allow_quick_gather)
- add_obj_verb(src, /obj/item/storage/verb/toggle_gathering_mode)
- else
- remove_obj_verb(src, /obj/item/storage/verb/toggle_gathering_mode)
-
- src.boxes = new /atom/movable/screen/storage( )
- src.boxes.name = "storage"
- src.boxes.master = src
- src.boxes.icon_state = "block"
- src.boxes.screen_loc = storage_ui_default
-
- src.storage_start = new /atom/movable/screen/storage( )
- src.storage_start.name = "storage"
- src.storage_start.master = src
- src.storage_start.icon_state = "storage_start"
- src.storage_start.screen_loc = storage_ui_default
-
- src.storage_continue = new /atom/movable/screen/storage( )
- src.storage_continue.name = "storage"
- src.storage_continue.master = src
- src.storage_continue.icon_state = "storage_continue"
- src.storage_continue.screen_loc = storage_ui_default
-
- src.storage_end = new /atom/movable/screen/storage( )
- src.storage_end.name = "storage"
- src.storage_end.master = src
- src.storage_end.icon_state = "storage_end"
- src.storage_end.screen_loc = storage_ui_default
-
- src.stored_start = new /atom/movable //we just need these to hold the icon
- src.stored_start.icon_state = "stored_start"
-
- src.stored_continue = new /atom/movable
- src.stored_continue.icon_state = "stored_continue"
-
- src.stored_end = new /atom/movable
- src.stored_end.icon_state = "stored_end"
-
- src.closer = new /atom/movable/screen/close( )
- src.closer.master = src
- src.closer.icon_state = "storage_close"
- src.closer.hud_layerise()
- orient2hud()
-
- populate_contents_legacy()
-
- PopulateContents()
-
- //calibrate_size() //Let's not!
-
/obj/item/storage/proc/populate_contents_legacy()
if(LAZYLEN(starts_with) && !empty)
for(var/newtype in starts_with)
diff --git a/code/game/objects/items/storage/backpack.dm b/code/game/objects/items/storage/backpack.dm
index 6501a2467937..41956980ca93 100644
--- a/code/game/objects/items/storage/backpack.dm
+++ b/code/game/objects/items/storage/backpack.dm
@@ -10,6 +10,8 @@
w_class = ITEMSIZE_LARGE
slot_flags = SLOT_BACK
max_w_class = ITEMSIZE_LARGE
+ weight = ITEM_WEIGHT_STORAGE_BACKPACK
+ encumbrance = ITEM_ENCUMBRANCE_STORAGE_BACKPACK
max_storage_space = INVENTORY_STANDARD_SPACE
var/flippable = 0
var/side = 0 //0 = right, 1 = left
@@ -49,6 +51,8 @@
/obj/item/storage/backpack/holding/duffle
name = "dufflebag of holding"
icon_state = "holdingduffle"
+ encumbrance = ITEM_ENCUMBRANCE_STORAGE_DUFFLEBAG
+ weight = ITEM_WEIGHT_STORAGE_DUFFLEBAG
/obj/item/storage/backpack/holding/attackby(obj/item/W as obj, mob/user as mob)
if(istype(W, /obj/item/storage/backpack/holding))
@@ -163,7 +167,11 @@
desc = "A large dufflebag for holding extra things."
icon_state = "duffle"
item_state_slots = list(SLOT_ID_RIGHT_HAND = "duffle", SLOT_ID_LEFT_HAND = "duffle")
- slowdown = 1
+ weight = ITEM_WEIGHT_STORAGE_DUFFLEBAG
+ encumbrance = ITEM_ENCUMBRANCE_STORAGE_DUFFLEBAG
+ flat_encumbrance = ITEM_FLAT_ENCUMBRANCE_DUFFLEBAG
+ // todo: remove when weight system is used
+ slowdown = 0.25
max_storage_space = INVENTORY_DUFFLEBAG_SPACE
/obj/item/storage/backpack/dufflebag/syndie
@@ -171,7 +179,7 @@
desc = "A large dufflebag for holding extra tactical supplies. This one appears to be made out of lighter material than usual."
icon_state = "duffle-syndie"
item_state_slots = list(SLOT_ID_RIGHT_HAND = "duffle_syndie", SLOT_ID_LEFT_HAND = "duffle_syndie")
- slowdown = 0
+ weight = ITEM_WEIGHT_BASELINE
/obj/item/storage/backpack/dufflebag/syndie/med
name = "medical dufflebag"
@@ -588,8 +596,8 @@
item_state = "saddlebag"
icon_state = "saddlebag"
var/icon_base = "saddlebag"
+ encumbrance = ITEM_ENCUMBRANCE_STORAGE_DUFFLEBAG
max_storage_space = INVENTORY_DUFFLEBAG_SPACE //Saddlebags can hold more, like dufflebags
- slowdown = 1 //And are slower, too...Unless you're a macro, that is.
var/no_message = "You aren't the appropriate taur type to wear this!"
/obj/item/storage/backpack/saddlebag_common/can_equip(mob/M, slot, mob/user, flags)
@@ -600,59 +608,27 @@
var/datum/sprite_accessory/tail/taur/TT = H.tail_style
if(istype(H) && istype(TT, /datum/sprite_accessory/tail/taur/horse))
item_state = "[icon_base]_horse"
- if(H.size_multiplier >= RESIZE_BIG) //Are they a macro?
- slowdown = 0
- else
- slowdown = initial(slowdown)
return 1
if(istype(H) && istype(TT, /datum/sprite_accessory/tail/taur/wolf))
item_state = "[icon_base]_wolf"
- if(H.size_multiplier >= RESIZE_BIG) //Are they a macro?
- slowdown = 0
- else
- slowdown = initial(slowdown)
return 1
if(istype(H) && istype(TT, /datum/sprite_accessory/tail/taur/cow))
item_state = "[icon_base]_cow"
- if(H.size_multiplier >= RESIZE_BIG) //Are they a macro?
- slowdown = 0
- else
- slowdown = initial(slowdown)
return 1
if(istype(H) && istype(TT, /datum/sprite_accessory/tail/taur/lizard))
item_state = "[icon_base]_lizard"
- if(H.size_multiplier >= RESIZE_BIG) //Are they a macro?
- slowdown = 0
- else
- slowdown = initial(slowdown)
return 1
if(istype(H) && istype(TT, /datum/sprite_accessory/tail/taur/feline))
item_state = "[icon_base]_feline"
- if(H.size_multiplier >= RESIZE_BIG) //Are they a macro?
- slowdown = 0
- else
- slowdown = initial(slowdown)
return 1
if(istype(H) && istype(TT, /datum/sprite_accessory/tail/taur/drake))
item_state = "[icon_base]_drake"
- if(H.size_multiplier >= RESIZE_BIG) //Are they a macro?
- slowdown = 0
- else
- slowdown = initial(slowdown)
return 1
if(istype(H) && istype(TT, /datum/sprite_accessory/tail/taur/otie))
item_state = "[icon_base]_otie"
- if(H.size_multiplier >= RESIZE_BIG) //Are they a macro?
- slowdown = 0
- else
- slowdown = initial(slowdown)
return 1
if(istype(H) && istype(TT, /datum/sprite_accessory/tail/taur/deer))
item_state = "[icon_base]_deer"
- if(H.size_multiplier >= RESIZE_BIG) //Are they a macro?
- slowdown = 0
- else
- slowdown = initial(slowdown)
return 1
else
to_chat(H, "[no_message]")
@@ -676,7 +652,7 @@
icon_state = "taurvest"
icon_base = "taurvest"
max_storage_space = INVENTORY_STANDARD_SPACE
- slowdown = 0
+ encumbrance = ITEM_ENCUMBRANCE_STORAGE_BACKPACK
/obj/item/storage/backpack/dufflebag/fluff //Black dufflebag without syndie buffs.
name = "plain black dufflebag"
diff --git a/code/game/objects/items/storage/bags.dm b/code/game/objects/items/storage/bags.dm
index 0a86bd3e4385..da126f8105bd 100644
--- a/code/game/objects/items/storage/bags.dm
+++ b/code/game/objects/items/storage/bags.dm
@@ -386,7 +386,6 @@
desc = "A bag for storing pills, patches, bottles, and hypovials."
max_storage_space = 200
w_class = ITEMSIZE_LARGE
- slowdown = 1
can_hold = list(
/obj/item/reagent_containers/pill,
/obj/item/reagent_containers/glass/beaker,
@@ -404,7 +403,6 @@
desc = "A bag for storing slime extracts, slime potions, monkey cubes, and beakers."
max_storage_space = 200
w_class = ITEMSIZE_LARGE
- slowdown = 1
can_hold = list(
/obj/item/reagent_containers/glass/beaker,
/obj/item/reagent_containers/food/snacks/monkeycube,
diff --git a/code/game/objects/items/tools/screwdriver.dm b/code/game/objects/items/tools/screwdriver.dm
index 2ab66c31d2d8..23677846cb63 100644
--- a/code/game/objects/items/tools/screwdriver.dm
+++ b/code/game/objects/items/tools/screwdriver.dm
@@ -113,15 +113,13 @@
icon_state = "hybscrewdriver"
item_state = "screwdriver_black"
origin_tech = list(TECH_MATERIAL = 3, TECH_ENGINEERING = 3)
- slowdown = 0.1
+ weight = ITEM_WEIGHT_HYBRID_TOOLS
w_class = ITEMSIZE_NORMAL
tool_sound = 'sound/effects/uncloak.ogg'
tool_speed = 0.4
random_color = FALSE
reach = 2
-
-
/obj/item/tool/screwdriver/cyborg
name = "powered screwdriver"
desc = "An electrical screwdriver, designed to be both precise and quick."
diff --git a/code/game/objects/items/tools/weldingtool.dm b/code/game/objects/items/tools/weldingtool.dm
index 56273803514e..d38cc6803c39 100644
--- a/code/game/objects/items/tools/weldingtool.dm
+++ b/code/game/objects/items/tools/weldingtool.dm
@@ -453,7 +453,7 @@
icon_state = "hybwelder"
max_fuel = 80
eye_safety_modifier = -2 // Brighter than the sun. Literally, you can look at the sun with a welding mask of proper grade, this will burn through that.
- slowdown = 0.1
+ weight = ITEM_WEIGHT_HYBRID_TOOLS
tool_speed = 0.25
w_class = ITEMSIZE_LARGE
flame_intensity = 5
diff --git a/code/game/objects/items/tools/wirecutters.dm b/code/game/objects/items/tools/wirecutters.dm
index f2c4f501d63a..aad6ae7ee72b 100644
--- a/code/game/objects/items/tools/wirecutters.dm
+++ b/code/game/objects/items/tools/wirecutters.dm
@@ -107,7 +107,7 @@
catalogue_data = list(/datum/category_item/catalogue/anomalous/precursor_a/alien_wirecutters)
icon_state = "hybcutters"
w_class = ITEMSIZE_NORMAL
- slowdown = 0.1
+ weight = ITEM_WEIGHT_HYBRID_TOOLS
origin_tech = list(TECH_MATERIAL = 3, TECH_ENGINEERING = 3, TECH_PHORON = 2)
attack_verb = list("pinched", "nipped", "warped", "blasted")
tool_sound = 'sound/effects/stealthoff.ogg'
diff --git a/code/game/objects/items/tools/wrench.dm b/code/game/objects/items/tools/wrench.dm
index acabc9ac3d7b..c05c30db45d8 100644
--- a/code/game/objects/items/tools/wrench.dm
+++ b/code/game/objects/items/tools/wrench.dm
@@ -81,7 +81,7 @@
damage_force = 8
throw_force = 10
w_class = ITEMSIZE_NORMAL
- slowdown = 0.1
+ weight = ITEM_WEIGHT_HYBRID_TOOLS
origin_tech = list(TECH_MATERIAL = 3, TECH_ENGINEERING = 3, TECH_PHORON = 2)
attack_verb = list("bashed", "battered", "bludgeoned", "whacked", "warped", "blasted")
tool_sound = 'sound/effects/stealthoff.ogg'
diff --git a/code/game/objects/items/weapons/RCD.dm b/code/game/objects/items/weapons/RCD.dm
index da304f685f5e..3b1a72e99cd6 100644
--- a/code/game/objects/items/weapons/RCD.dm
+++ b/code/game/objects/items/weapons/RCD.dm
@@ -11,7 +11,7 @@
SLOT_ID_LEFT_HAND = 'icons/mob/items/lefthand.dmi',
SLOT_ID_RIGHT_HAND = 'icons/mob/items/righthand.dmi',
)
- item_flags = ITEM_NOBLUDGEON
+ item_flags = ITEM_NOBLUDGEON | ITEM_ENCUMBERS_WHILE_HELD
damage_force = 10
throw_force = 10
throw_speed = 1
diff --git a/code/game/objects/items/weapons/RPD.dm b/code/game/objects/items/weapons/RPD.dm
index c8fc53f016af..43bdfd5dfc0b 100644
--- a/code/game/objects/items/weapons/RPD.dm
+++ b/code/game/objects/items/weapons/RPD.dm
@@ -17,7 +17,7 @@
SLOT_ID_LEFT_HAND = 'icons/mob/items/lefthand.dmi',
SLOT_ID_RIGHT_HAND = 'icons/mob/items/righthand.dmi',
)
- item_flags = ITEM_NOBLUDGEON
+ item_flags = ITEM_NOBLUDGEON | ITEM_ENCUMBERS_WHILE_HELD
damage_force = 10
throw_force = 10
throw_speed = 1
diff --git a/code/game/objects/items/weapons/duct_tape.dm b/code/game/objects/items/weapons/duct_tape.dm
index d4e320a954ee..b39b7533f664 100644
--- a/code/game/objects/items/weapons/duct_tape.dm
+++ b/code/game/objects/items/weapons/duct_tape.dm
@@ -162,7 +162,7 @@
icon_state = "tape"
w_class = ITEMSIZE_TINY
plane = MOB_PLANE
- item_flags = ITEM_NOBLUDGEON
+ item_flags = ITEM_NOBLUDGEON | ITEM_ENCUMBERS_WHILE_HELD
anchored = FALSE
var/obj/item/stuck = null
diff --git a/code/game/objects/items/weapons/explosives.dm b/code/game/objects/items/weapons/explosives.dm
index 754dc9468d0b..7ece8ebc95e2 100644
--- a/code/game/objects/items/weapons/explosives.dm
+++ b/code/game/objects/items/weapons/explosives.dm
@@ -5,7 +5,7 @@
icon = 'icons/obj/assemblies.dmi'
icon_state = "plastic-explosive0"
item_state = "plasticx"
- item_flags = ITEM_NOBLUDGEON
+ item_flags = ITEM_NOBLUDGEON | ITEM_ENCUMBERS_WHILE_HELD
w_class = ITEMSIZE_SMALL
origin_tech = list(TECH_ILLEGAL = 2)
var/datum/wires/explosive/c4/wires = null
diff --git a/code/game/objects/items/weapons/material/material_armor.dm b/code/game/objects/items/weapons/material/material_armor.dm
index 6418facb2ca7..69a74661fba2 100644
--- a/code/game/objects/items/weapons/material/material_armor.dm
+++ b/code/game/objects/items/weapons/material/material_armor.dm
@@ -192,7 +192,9 @@ Protectiveness | Armor %
if(!isnull(material.conductivity))
siemens_coefficient = clamp( material.conductivity / 10, 0, 10)
- slowdown = clamp(0, round(material.weight / 10, 0.1) * material_weight_factor, 6)
+ var/legacy_whatever = clamp(0, round(material.weight / 10, 0.1) * material_weight_factor, 6) * 10
+ set_weight(legacy_whatever * 2)
+ set_encumbrance(legacy_whatever * 4)
/obj/item/clothing/suit/armor/material
name = "armor"
diff --git a/code/game/objects/items/weapons/material/twohanded.dm b/code/game/objects/items/weapons/material/twohanded.dm
index 7237c7e83ede..2c85cc4bfa21 100644
--- a/code/game/objects/items/weapons/material/twohanded.dm
+++ b/code/game/objects/items/weapons/material/twohanded.dm
@@ -219,7 +219,7 @@
fragile = 1 //It's a haphazard thing of glass, wire, and steel
reach = 2 // Spears are long.
attackspeed = 20
- slowdown = 1.05
+ weight = ITEM_WEIGHT_MELEE_SPEAR
var/obj/item/grenade/explosive = null
var/war_cry = "AAAAARGH!!!"
@@ -302,7 +302,7 @@
force_divisor = 0.6 // 9/36 with hardness 60 (steel) and 0.25 unwielded divisor
hitsound = 'sound/weapons/heavysmash.ogg'
w_class = ITEMSIZE_HUGE
- slowdown = 1.5
+ encumbrance = ITEM_ENCUMBRANCE_MELEE_SLEDGEHAMMER
dulled_divisor = 0.95 //Still metal on a stick
sharp = 0
edge = 1
diff --git a/code/game/objects/items/weapons/melee/misc.dm b/code/game/objects/items/weapons/melee/misc.dm
index 0d3690d06861..1b88198c6a26 100644
--- a/code/game/objects/items/weapons/melee/misc.dm
+++ b/code/game/objects/items/weapons/melee/misc.dm
@@ -387,7 +387,7 @@
edge = 1
attack_verb = list("attacked", "smashed", "crushed", "wacked", "pounded")
armor_penetration = 50
- slowdown = 0
+ weight = ITEM_WEIGHT_BASELINE
//This currently just kills the user. lol
/*
diff --git a/code/game/objects/items/weapons/nullrod.dm b/code/game/objects/items/weapons/nullrod.dm
index fdaf09c32e86..7775babacd52 100644
--- a/code/game/objects/items/weapons/nullrod.dm
+++ b/code/game/objects/items/weapons/nullrod.dm
@@ -412,8 +412,9 @@
hitsound = 'sound/weapons/bladeslice.ogg'
attack_verb = list("attacked", "slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut")
-/obj/item/nullrod/tribal_knife/process(delta_time)
- slowdown = rand(-2, 2)
+// no this is hrp
+// /obj/item/nullrod/tribal_knife/process(delta_time)
+// slowdown = rand(-2, 2)
/obj/item/nullrod/pitchfork
icon_state = "pitchfork0"
diff --git a/code/game/objects/items/weapons/shields.dm b/code/game/objects/items/weapons/shields.dm
index 3262bc35c412..fd46d2d26634 100644
--- a/code/game/objects/items/weapons/shields.dm
+++ b/code/game/objects/items/weapons/shields.dm
@@ -191,7 +191,7 @@
item_state = "metal"
icon_state = "metal"
damage_force = 16
- slowdown = 2
+ encumbrance = ITEM_ENCUMBRANCE_SHIELD_TOWER
throw_force = 15 //Massive piece of metal
w_class = ITEMSIZE_HUGE
diff --git a/code/game/objects/items/weapons/surgery_tools.dm b/code/game/objects/items/weapons/surgery_tools.dm
index 7b57ee6337de..59e1a1a7fff3 100644
--- a/code/game/objects/items/weapons/surgery_tools.dm
+++ b/code/game/objects/items/weapons/surgery_tools.dm
@@ -13,7 +13,7 @@
desc = "This shouldn't be here, ahelp it."
icon = 'icons/obj/surgery.dmi'
w_class = ITEMSIZE_SMALL
- item_flags = ITEM_CAREFUL_BLUDGEON
+ item_flags = ITEM_CAREFUL_BLUDGEON | ITEM_ENCUMBERS_WHILE_HELD
var/helpforce = 0 //For help intent things
drop_sound = 'sound/items/drop/weldingtool.ogg'
pickup_sound = 'sound/items/pickup/weldingtool.ogg'
diff --git a/code/game/objects/items/weapons/tanks/tanks.dm b/code/game/objects/items/weapons/tanks/tanks.dm
index 7b8e2af04dbd..40bf736e4c34 100644
--- a/code/game/objects/items/weapons/tanks/tanks.dm
+++ b/code/game/objects/items/weapons/tanks/tanks.dm
@@ -25,6 +25,8 @@ var/list/global/tank_gauge_cache = list()
throw_speed = 1
throw_range = 4
+ weight = ITEM_WEIGHT_GAS_TANK
+
var/datum/gas_mixture/air_contents = null
var/distribute_pressure = ONE_ATMOSPHERE
integrity = 20
diff --git a/code/game/objects/structures/inflatable.dm b/code/game/objects/structures/inflatable.dm
index ce3ecc965f61..9cab554c8085 100644
--- a/code/game/objects/structures/inflatable.dm
+++ b/code/game/objects/structures/inflatable.dm
@@ -252,10 +252,7 @@
icon = 'icons/obj/inflatable.dmi'
icon_state = "folded_wall_torn"
-/obj/item/inflatable/torn/attack_self(mob/user)
- . = ..()
- if(.)
- return
+/obj/item/inflatable/torn/inflate(user,location)
to_chat(user, "The inflatable wall is too torn to be inflated!")
add_fingerprint(user)
@@ -265,10 +262,7 @@
icon = 'icons/obj/inflatable.dmi'
icon_state = "folded_door_torn"
-/obj/item/inflatable/door/torn/attack_self(mob/user)
- . = ..()
- if(.)
- return
+/obj/item/inflatable/door/torn/inflate(user,location)
to_chat(user, "The inflatable door is too torn to be inflated!")
add_fingerprint(user)
diff --git a/code/game/rendering/legacy/alert.dm b/code/game/rendering/legacy/alert.dm
index 70753c7d6293..f5a70ffeac90 100644
--- a/code/game/rendering/legacy/alert.dm
+++ b/code/game/rendering/legacy/alert.dm
@@ -1,6 +1,23 @@
//A system to manage and display alerts on screen without needing you to do it yourself
-//PUBLIC - call these wherever you want
+/mob/var/list/alerts = list() // contains /atom/movable/screen/alert only // On /mob so clientless mobs will throw alerts properly
+
+/atom/movable/screen/alert/Click(location, control, params)
+ if(!usr || !usr.client)
+ return
+ var/paramslist = params2list(params)
+ if(paramslist["shift"]) // screen objects don't do the normal Click() stuff so we'll cheat
+ to_chat(usr,"[name] - [desc]")
+ return
+ if(master)
+ return usr.client.Click(master, location, control, params)
+
+/atom/movable/screen/alert/Destroy()
+ ..()
+ severity = 0
+ master = null
+ screen_loc = ""
+ return QDEL_HINT_QUEUE
/mob/proc/throw_alert(category, type, severity, obj/new_master)
@@ -80,6 +97,10 @@
name = "Alert"
desc = "Something seems to have gone wrong with this alert, so report this bug please"
mouse_opacity = 1
+ /// background to render
+ var/icon/background_icon = 'icons/screen/alerts/backgrounds.dmi'
+ /// background state to render; null to not render
+ var/background_state
var/timeout = 0 //If set to a number, this alert will clear itself after that many deciseconds
var/severity = 0
var/alerttooltipstyle = ""
@@ -87,6 +108,16 @@
/// mob that owns us
var/mob/owner
+/atom/movable/screen/alert/Initialize(mapload)
+ . = ..()
+ update_icon()
+
+/atom/movable/screen/alert/update_icon(updates)
+ . = ..()
+ underlays.len = 0
+ if(background_icon && background_state)
+ underlays += image(background_icon, background_state)
+
/atom/movable/screen/alert/Destroy()
owner = null
return ..()
@@ -446,6 +477,8 @@ so as to remain in compliance with the most up-to-date laws."
// Re-render all alerts - also called in /datum/hud/show_hud() because it's needed there
/datum/hud/proc/reorganize_alerts()
+ if(!mymob)
+ return
var/list/alerts = mymob.alerts
if(!hud_shown)
for(var/i = 1, i <= alerts.len, i++)
@@ -480,21 +513,36 @@ so as to remain in compliance with the most up-to-date laws."
mymob?.client?.screen |= alert
return 1
-/mob/var/list/alerts = list() // contains /atom/movable/screen/alert only // On /mob so clientless mobs will throw alerts properly
+//? Encumbrance
-/atom/movable/screen/alert/Click(location, control, params)
- if(!usr || !usr.client)
- return
- var/paramslist = params2list(params)
- if(paramslist["shift"]) // screen objects don't do the normal Click() stuff so we'll cheat
- to_chat(usr,"[name] - [desc]")
- return
- if(master)
- return usr.client.Click(master, location, control, params)
+/atom/movable/screen/alert/encumbered
+ abstract_type = /atom/movable/screen/alert/encumbered
+ icon = 'icons/screen/alerts/encumbered.dmi'
+ background_state = "default"
+ desc = "Carrying more than you can comfortably bear. Movement slowed."
-/atom/movable/screen/alert/Destroy()
- ..()
- severity = 0
- master = null
- screen_loc = ""
- return QDEL_HINT_QUEUE
+/atom/movable/screen/alert/encumbered/Click(location, control, params)
+ if(!isliving(owner))
+ return
+ var/mob/living/L = owner
+ to_chat(usr, jointext(list(
+ "[usr == L? "You are" : "[L] is"] [lowertext(name)].",
+ "Encumbrance: [L.cached_carry_encumbrance] / [L.physiology.carry_strength]",
+ "Weight: [L.cached_carry_weight] / [L.physiology.carry_strength]",
+ ), "
"))
+
+/atom/movable/screen/alert/encumbered/minor
+ name = "Lightly Encumbered"
+ icon_state = "1"
+
+/atom/movable/screen/alert/encumbered/moderate
+ name = "Moderately Encumbered"
+ icon_state = "2"
+
+/atom/movable/screen/alert/encumbered/severe
+ name = "Severely Encumbered"
+ icon_state = "3"
+
+/atom/movable/screen/alert/encumbered/extreme
+ name = "Extremely Encumbered"
+ icon_state = "4"
diff --git a/code/game/rendering/mob.dm b/code/game/rendering/mob.dm
index 0be56c97185f..70a30824f565 100644
--- a/code/game/rendering/mob.dm
+++ b/code/game/rendering/mob.dm
@@ -23,6 +23,7 @@
client.using_perspective?.reload(client, TRUE)
INVOKE_ASYNC(client, TYPE_PROC_REF(/client, init_viewport_blocking))
reload_fullscreen()
+ hud_used?.reorganize_alerts()
/**
* reloads rendering after screen viewport size change
diff --git a/code/modules/artifice/telecube.dm b/code/modules/artifice/telecube.dm
index 21056a7ed4fa..795dff6b7337 100644
--- a/code/modules/artifice/telecube.dm
+++ b/code/modules/artifice/telecube.dm
@@ -28,8 +28,6 @@
catalogue_data = list(/datum/category_item/catalogue/anomalous/precursor_a/telecube)
- slowdown = 5
-
throw_range = 2
var/obj/item/telecube/mate = null
diff --git a/code/modules/clothing/clothing.dm b/code/modules/clothing/clothing.dm
index 874236bbc727..cb6019645952 100644
--- a/code/modules/clothing/clothing.dm
+++ b/code/modules/clothing/clothing.dm
@@ -5,6 +5,7 @@
// todo: this is an awful way to do it but it works
unequip_sound = 'sound/items/drop/clothing.ogg'
pickup_sound = 'sound/items/pickup/cloth.ogg'
+ item_flags = NONE
//? equip
/// Inventory slot IDs where this is active for any effects. Used by subtypes, to be potentially refactored in the future.
@@ -61,6 +62,12 @@
/// full list of accessories, everything inside must be an /obj/item. *not* /obj/item/clothing.
var/list/accessories
+ //* Carry Weight
+ /// encumbrance compensation for accessories - flat.
+ var/accessory_encumbrance_mitigation = 0
+ /// encumbrance multiplier for accessories.
+ var/accessory_encumbrance_multiply = 1
+
/obj/item/clothing/Initialize(mapload)
. = ..()
if(islist(active_slots))
diff --git a/code/modules/clothing/clothing_accessories.dm b/code/modules/clothing/clothing_accessories.dm
index 783372887a7c..ceca5912638d 100644
--- a/code/modules/clothing/clothing_accessories.dm
+++ b/code/modules/clothing/clothing_accessories.dm
@@ -15,6 +15,25 @@
return accessory_host.update_worn_icon()
return ..()
+/obj/item/clothing/get_encumbrance()
+ . = ..()
+ if(!isnull(accessory_host))
+ . = max(0, . * accessory_host.accessory_encumbrance_multiply - accessory_host.accessory_encumbrance_mitigation)
+
+/obj/item/clothing/proc/set_accessory_encumbrance_mitigation(val, update)
+ accessory_encumbrance_mitigation = val
+ if(update)
+ update_accessory_encumbrance()
+
+/obj/item/clothing/proc/set_accessory_encumbrance_multiply(val, update)
+ accessory_encumbrance_multiply = val
+ if(update)
+ update_accessory_encumbrance()
+
+/obj/item/clothing/proc/update_accessory_encumbrance()
+ for(var/obj/item/I as anything in accessories)
+ I.update_encumbrance()
+
/obj/item/clothing/equipped(mob/user, slot, flags)
. = ..()
// propagate through accessories
@@ -210,22 +229,16 @@
LAZYADD(accessories,A)
A.on_attached(src, user)
add_obj_verb(src, /obj/item/clothing/proc/removetie_verb)
- update_accessory_slowdown()
update_worn_icon()
+ update_encumbrance()
/obj/item/clothing/proc/remove_accessory(mob/user, obj/item/clothing/accessory/A)
if(!LAZYLEN(accessories) || !(A in accessories))
return
-
A.on_removed(user)
accessories -= A
- update_accessory_slowdown()
update_worn_icon()
-
-/obj/item/clothing/proc/update_accessory_slowdown()
- slowdown = initial(slowdown)
- for(var/obj/item/clothing/accessory/A in accessories)
- slowdown += A.slowdown
+ update_encumbrance()
/obj/item/clothing/proc/removetie_verb()
set name = "Remove Accessory"
diff --git a/code/modules/clothing/head/helmet.dm b/code/modules/clothing/head/helmet.dm
index ec7773a18b4d..dc3b49e743b2 100644
--- a/code/modules/clothing/head/helmet.dm
+++ b/code/modules/clothing/head/helmet.dm
@@ -16,6 +16,8 @@
ear_protection = 1
drop_sound = 'sound/items/drop/helm.ogg'
pickup_sound = 'sound/items/pickup/helm.ogg'
+ encumbrance = ITEM_ENCUMBRANCE_ARMOR_MEDIUM_HELMET
+ weight = ITEM_WEIGHT_ARMOR_MEDIUM_HELMET
/obj/item/clothing/head/helmet/ntsec
name = "corpsec helmet"
@@ -130,6 +132,8 @@
cold_protection = HEAD
min_cold_protection_temperature = SPACE_HELMET_MIN_COLD_PROTECTION_TEMPERATURE
siemens_coefficient = 0.5
+ encumbrance = ITEM_ENCUMBRANCE_ARMOR_HEAVY_HELMET
+ weight = ITEM_WEIGHT_ARMOR_HEAVY_HELMET
/obj/item/clothing/head/helmet/alien
name = "alien helmet"
diff --git a/code/modules/clothing/shoes/_shoes.dm b/code/modules/clothing/shoes/_shoes.dm
index 212ed0ce8e11..a86df9ffd1ea 100644
--- a/code/modules/clothing/shoes/_shoes.dm
+++ b/code/modules/clothing/shoes/_shoes.dm
@@ -25,7 +25,6 @@
var/step_volume_mod = 1 //How quiet or loud footsteps in this shoe are
permeability_coefficient = 0.50
- slowdown = SHOES_SLOWDOWN
damage_force = 2
var/overshoes = 0
species_restricted = list("exclude",SPECIES_TESHARI, SPECIES_VOX)
diff --git a/code/modules/clothing/shoes/colour.dm b/code/modules/clothing/shoes/colour.dm
index 2ae6d1db50b9..664c2e9c60ad 100644
--- a/code/modules/clothing/shoes/colour.dm
+++ b/code/modules/clothing/shoes/colour.dm
@@ -97,7 +97,8 @@
if(!user.attempt_insert_item_for_installation(cuffs, src))
return
chained = cuffs
- slowdown = 15
+ // todo: refactor
+ set_encumbrance(ITEM_ENCUMBRANCE_SHOES_CUFFED)
icon_state = "orange1"
/obj/item/clothing/shoes/orange/proc/remove_cuffs(mob/user as mob)
@@ -107,7 +108,8 @@
user.put_in_hands_or_drop(chained)
chained.add_fingerprint(user)
- slowdown = initial(slowdown)
+ // todo: refactor
+ set_encumbrance(initial(encumbrance))
icon_state = "orange"
chained = null
diff --git a/code/modules/clothing/shoes/leg_guards.dm b/code/modules/clothing/shoes/leg_guards.dm
index fdef4c976a0d..6bdb4650acf0 100644
--- a/code/modules/clothing/shoes/leg_guards.dm
+++ b/code/modules/clothing/shoes/leg_guards.dm
@@ -2,7 +2,8 @@
name = "leg guards"
desc = "These will protect your legs and feet."
body_cover_flags = LEGS|FEET
- slowdown = SHOES_SLOWDOWN+0.5
+ weight = ITEM_WEIGHT_ARMOR_MEDIUM_BOOTS
+ encumbrance = ITEM_ENCUMBRANCE_ARMOR_MEDIUM_BOOTS
species_restricted = null //Unathi and Taj can wear leg armor now
w_class = ITEMSIZE_NORMAL
step_volume_mod = 1.3
@@ -68,7 +69,8 @@
icon_state = "leg_guards_flexitac"
item_state_slots = list(SLOT_ID_RIGHT_HAND = "jackboots", SLOT_ID_LEFT_HAND = "jackboots")
siemens_coefficient = 0.6
- slowdown = SHOES_SLOWDOWN+0.2
+ weight = ITEM_WEIGHT_ARMOR_LIGHT_BOOTS
+ encumbrance = ITEM_ENCUMBRANCE_ARMOR_LIGHT_BOOTS
armor_type = /datum/armor/station/tactical
min_cold_protection_temperature = T0C - 20
cold_protection = LEGS
diff --git a/code/modules/clothing/shoes/magboots.dm b/code/modules/clothing/shoes/magboots.dm
index 52b8110e09ad..6590ad1ad239 100644
--- a/code/modules/clothing/shoes/magboots.dm
+++ b/code/modules/clothing/shoes/magboots.dm
@@ -9,18 +9,18 @@
overshoes = 1
shoes_under_pants = -1 //These things are huge
preserve_item = 1
+ encumbrance = ITEM_ENCUMBRANCE_SHOES_MAGBOOTS
var/magpulse = 0
- var/slowdown_on = 3
var/icon_base = "magboots"
action_button_name = "Toggle Magboots"
step_volume_mod = 1.3
drop_sound = 'sound/items/drop/metalboots.ogg'
pickup_sound = 'sound/items/pickup/toolbox.ogg'
-/obj/item/clothing/shoes/magboots/proc/set_slowdown()
- slowdown = worn_over? max(SHOES_SLOWDOWN, worn_over.slowdown): SHOES_SLOWDOWN //So you can't put on magboots to make you walk faster.
- if (magpulse)
- slowdown += slowdown_on
+ var/encumbrance_on = ITEM_ENCUMBRANCE_SHOES_MAGBOOTS_PULSE
+
+/obj/item/clothing/shoes/magboots/proc/update_magboot_encumbrance()
+ set_encumbrance(initial(encumbrance) + (magpulse? encumbrance_on : 0))
/obj/item/clothing/shoes/magboots/attack_self(mob/user)
. = ..()
@@ -29,14 +29,14 @@
if(magpulse)
clothing_flags &= ~NOSLIP
magpulse = 0
- set_slowdown()
+ update_magboot_encumbrance()
damage_force = 3
if(icon_base) icon_state = "[icon_base]0"
to_chat(user, "You disable the mag-pulse traction system.")
else
clothing_flags |= NOSLIP
magpulse = 1
- set_slowdown()
+ update_magboot_encumbrance()
damage_force = 5
if(icon_base) icon_state = "[icon_base]1"
to_chat(user, "You enable the mag-pulse traction system.")
@@ -56,11 +56,11 @@
/obj/item/clothing/shoes/magboots/equipped(mob/user, slot, flags)
. = ..()
- set_slowdown()
+ update_magboot_encumbrance()
/obj/item/clothing/shoes/magboots/unequipped(mob/user, slot, flags)
. = ..()
- set_slowdown()
+ update_magboot_encumbrance()
/obj/item/clothing/shoes/magboots/examine(mob/user, dist)
. = ..()
@@ -118,7 +118,7 @@
/obj/item/clothing/shoes/magboots/advanced
name = "advanced magboots"
icon_state = "advmag0"
- slowdown_on = 0
+ encumbrance_on = 0
icon_base = "advmag"
/obj/item/clothing/shoes/magboots/syndicate
@@ -126,4 +126,4 @@
desc = "Prior to its dissolution, many Syndicate agents were tasked with stealing NanoTrasen's prototype advanced magboots. Reverse engineering these rare tactical boots was achieved shortly before the end of the conflict."
icon_state = "syndiemag0"
icon_base = "syndiemag"
- slowdown_on = 0
+ encumbrance_on = 0
diff --git a/code/modules/clothing/shoes/miscellaneous.dm b/code/modules/clothing/shoes/miscellaneous.dm
index 25e7d88650a6..247bb9b1c57b 100644
--- a/code/modules/clothing/shoes/miscellaneous.dm
+++ b/code/modules/clothing/shoes/miscellaneous.dm
@@ -24,12 +24,12 @@
permeability_coefficient = 0.05
siemens_coefficient = 0 //They're thick rubber boots! Of course they won't conduct electricity!
clothing_flags = NOSLIP
- slowdown = SHOES_SLOWDOWN+1
+ encumbrance = ITEM_ENCUMBRANCE_SHOES_GALOSHES
+ flat_encumbrance = ITEM_FLAT_ENCUMBRANCE_GALOSHES
species_restricted = null
drop_sound = 'sound/items/drop/rubber.ogg'
pickup_sound = 'sound/items/pickup/rubber.ogg'
-
/obj/item/clothing/shoes/dress
name = "dress shoes"
desc = "Sharp looking low quarters, perfect for a formal uniform."
@@ -65,7 +65,8 @@
desc = "The prankster's standard-issue clowning shoes. Damn they're huge!"
name = "clown shoes"
icon_state = "clown"
- slowdown = SHOES_SLOWDOWN+1
+ encumbrance = ITEM_ENCUMBRANCE_SHOES_CLOWN
+ flat_encumbrance = ITEM_FLAT_ENCUMBRANCE_SHOES_CLOWN
damage_force = 0
var/footstep = 1 //used for squeeks whilst walking
species_restricted = null
@@ -137,7 +138,8 @@
icon_state = "flippers"
item_state_slots = list(SLOT_ID_RIGHT_HAND = "galoshes", SLOT_ID_LEFT_HAND = "galoshes")
clothing_flags = NOSLIP
- slowdown = SHOES_SLOWDOWN+1
+ encumbrance = ITEM_ENCUMBRANCE_SHOES_FINS
+ flat_encumbrance = ITEM_FLAT_ENCUMBRANCE_SHOES_FINS
species_restricted = null
/obj/item/clothing/shoes/flipflop
@@ -271,6 +273,7 @@
name = "Antediluvian exposed heels alt"
desc = "A pair of a set of heels recovered with an odd design. This version has toes exposed, granting the wearer elegance, or unsightliness. This one has extra gold trimming."
icon_state = "aziru_heels_alt"
+
// The things folks do for fashion...
/obj/item/clothing/shoes/galoshes/black
name = "black galoshes"
@@ -281,7 +284,7 @@
name = "dark-purple semi-galoshes"
desc = "A dark-purple rubber boots. They obviously don't smell like a cotton candy, roses and fresh roasted peanuts."
icon_state = "galoshes_sc"
- slowdown = SHOES_SLOWDOWN
+ encumbrance = ITEM_ENCUMBRANCE_BASELINE
//More Warhammer Fun
/obj/item/clothing/shoes/utilitarian
diff --git a/code/modules/clothing/spacesuits/miscellaneous.dm b/code/modules/clothing/spacesuits/miscellaneous.dm
index 1825aea103b2..bb7a0a035882 100644
--- a/code/modules/clothing/spacesuits/miscellaneous.dm
+++ b/code/modules/clothing/spacesuits/miscellaneous.dm
@@ -11,6 +11,8 @@
min_cold_protection_temperature = SPACE_SUIT_MIN_COLD_PROTECTION_TEMPERATURE
min_pressure_protection = 0 * ONE_ATMOSPHERE
max_pressure_protection = 10 * ONE_ATMOSPHERE
+ weight = ITEM_WEIGHT_VOIDSUIT_HELMET
+ encumbrance = ITEM_ENCUMBRANCE_VOIDSUIT_HELMET
//Captain's space suit This is not the proper path but I don't currently know enough about how this all works to mess with it.
/obj/item/clothing/suit/armor/captain
@@ -23,7 +25,8 @@
clothing_flags = 0
body_cover_flags = UPPER_TORSO|LOWER_TORSO|LEGS|FEET|ARMS|HANDS
allowed = list(/obj/item/tank/emergency/oxygen, /obj/item/flashlight,/obj/item/gun/energy, /obj/item/gun/ballistic, /obj/item/ammo_magazine, /obj/item/ammo_casing, /obj/item/melee/baton,/obj/item/handcuffs)
- slowdown = 1.5
+ encumbrance = ITEM_ENCUMBRANCE_VOIDSUIT
+ weight = ITEM_WEIGHT_VOIDSUIT
armor_type = /datum/armor/station/tactical
inv_hide_flags = HIDEGLOVES|HIDESHOES|HIDEJUMPSUIT|HIDETAIL
cold_protection = UPPER_TORSO | LOWER_TORSO | LEGS | FEET | ARMS | HANDS
@@ -66,8 +69,9 @@
name = "Santa's suit"
desc = "Festive!"
icon_state = "santa"
- slowdown = 0
- clothing_flags = 0
+ weight = ITEM_WEIGHT_BASELINE
+ encumbrance = ITEM_ENCUMBRANCE_BASELINE
+ clothing_flags = NONE
allowed = list(/obj/item) //for stuffing exta special presents
//Space pirate outfit
@@ -76,9 +80,11 @@
desc = "Yarr."
icon_state = "pirate"
armor_type = /datum/armor/pirate/medium
- clothing_flags = 0
+ weight = ITEM_WEIGHT_BASELINE
+ encumbrance = ITEM_ENCUMBRANCE_BASELINE
+ clothing_flags = NONE
inv_hide_flags = BLOCKHAIR
- body_cover_flags = 0
+ body_cover_flags = NONE
siemens_coefficient = 0.9
/obj/item/clothing/suit/space/pirate //Whhhhyyyyyyy???
@@ -87,7 +93,8 @@
icon_state = "pirate"
w_class = ITEMSIZE_NORMAL
allowed = list(/obj/item/gun,/obj/item/ammo_magazine,/obj/item/ammo_casing,/obj/item/melee/baton,/obj/item/handcuffs,/obj/item/tank/emergency/oxygen)
- slowdown = 0
+ weight = ITEM_WEIGHT_BASELINE
+ encumbrance = ITEM_ENCUMBRANCE_BASELINE
armor_type = /datum/armor/pirate/medium
siemens_coefficient = 0.9
inv_hide_flags = HIDETAIL|HIDEHOLSTER
@@ -99,12 +106,15 @@
icon_state = "syndicate-helm-orange"
desc = "A simple helmet with a built in light, smells like mothballs."
flash_protection = FLASH_PROTECTION_NONE
+ encumbrance = ITEM_ENCUMBRANCE_EMERGENCY_SOFTSUIT_HELMET
+ weight = ITEM_WEIGHT_EMERGENCY_SOFTSUIT_HELMET
/obj/item/clothing/suit/space/emergency
name = "Emergency Softsuit"
icon_state = "syndicate-orange"
desc = "A thin, ungainly softsuit colored in blaze orange for rescuers to easily locate, looks pretty fragile."
- slowdown = 4
+ encumbrance = ITEM_ENCUMBRANCE_EMERGENCY_SOFTSUIT
+ weight = ITEM_WEIGHT_EMERGENCY_SOFTSUIT
//Russian Emergency Suit
/obj/item/clothing/head/helmet/space/emergency/russian
@@ -117,4 +127,3 @@
name = "Sovjet Emergency Softsuit"
icon_state = "russian"
desc = "A chunky antique softsuit distributed to members of the Indo-Russian Diaspora. After all this time, it looks pretty fragile."
- slowdown = 4
diff --git a/code/modules/clothing/spacesuits/plasman.dm b/code/modules/clothing/spacesuits/plasman.dm
index 1f4723332f84..c1e84360c7e8 100644
--- a/code/modules/clothing/spacesuits/plasman.dm
+++ b/code/modules/clothing/spacesuits/plasman.dm
@@ -6,7 +6,8 @@
icon_state = "plasmaman_suit"
icon_override = 'icons/mob/plasmeme/suits.dmi'
desc = "A suit designed by NT to keep phoronoids from coming into contact with incompatible atmosphere. Seems like it doesn't protect from much else."
- slowdown = 1
+ weight = ITEM_WEIGHT_PHORONOID_SUIT
+ encumbrance = ITEM_ENCUMBRANCE_PHORONOID_SUIT
clothing_flags = ALLOWINTERNALS
armor_type = /datum/armor/phoronoid
allowed = list(/obj/item/tank)
@@ -35,6 +36,8 @@
clothing_flags = ALLOWINTERNALS | FLEXIBLEMATERIAL
armor_type = /datum/armor/phoronoid
light_overlay = "plasmaman_overlay"
+ weight = ITEM_WEIGHT_PHORONOID_HELMET
+ encumbrance = ITEM_ENCUMBRANCE_PHORONOID_HELMET
//
// SEC
diff --git a/code/modules/clothing/spacesuits/spacesuits.dm b/code/modules/clothing/spacesuits/spacesuits.dm
index 78dc09161d17..45de5eee2684 100644
--- a/code/modules/clothing/spacesuits/spacesuits.dm
+++ b/code/modules/clothing/spacesuits/spacesuits.dm
@@ -21,7 +21,9 @@
preserve_item = 1
flash_protection = FLASH_PROTECTION_MAJOR
valid_accessory_slots = null
-
+ weight = ITEM_WEIGHT_SOFTSUIT_HELMET
+ encumbrance = ITEM_ENCUMBRANCE_SOFTSUIT_HELMET
+
var/obj/machinery/camera/camera
var/list/camera_networks
@@ -73,7 +75,6 @@
clothing_flags = CLOTHING_THICK_MATERIAL | CLOTHING_INJECTION_PORT
body_cover_flags = UPPER_TORSO|LOWER_TORSO|LEGS|FEET|ARMS|HANDS
allowed = list(/obj/item/flashlight,/obj/item/tank/emergency/oxygen,/obj/item/suit_cooling_unit)
- slowdown = 1
armor_type = /datum/armor/general/space
inv_hide_flags = HIDEGLOVES|HIDESHOES|HIDEJUMPSUIT|HIDETAIL|HIDETIE|HIDEHOLSTER
cold_protection = UPPER_TORSO | LOWER_TORSO | LEGS | FEET | ARMS | HANDS
@@ -84,6 +85,8 @@
species_restricted = list("exclude",SPECIES_DIONA)
preserve_item = 1
valid_accessory_slots = (ACCESSORY_SLOT_OVER | ACCESSORY_SLOT_ARMBAND | ACCESSORY_SLOT_DECOR)
+ weight = ITEM_WEIGHT_SOFTSUIT
+ encumbrance = ITEM_ENCUMBRANCE_SOFTSUIT
var/list/supporting_limbs //If not-null, automatically splints breaks. Checked when removing the suit.
/obj/item/clothing/suit/space/equipped(mob/M, slot, accessory, silent, creation)
diff --git a/code/modules/clothing/spacesuits/syndi.dm b/code/modules/clothing/spacesuits/syndi.dm
index 2f1a9d056053..aa7a625237fa 100644
--- a/code/modules/clothing/spacesuits/syndi.dm
+++ b/code/modules/clothing/spacesuits/syndi.dm
@@ -12,7 +12,6 @@
desc = "A crimson spacesuit sporting clean lines and durable plating. Robust, reliable, and slightly suspicious."
w_class = ITEMSIZE_NORMAL
allowed = list(/obj/item/gun,/obj/item/ammo_magazine,/obj/item/ammo_casing,/obj/item/melee/baton,/obj/item/melee/energy/sword,/obj/item/handcuffs,/obj/item/tank/emergency/oxygen)
- slowdown = 1
armor_type = /datum/armor/agent/space
siemens_coefficient = 0.6
diff --git a/code/modules/clothing/spacesuits/void/event.dm b/code/modules/clothing/spacesuits/void/event.dm
index 7524e74fa5fd..7dfd4866dd8a 100644
--- a/code/modules/clothing/spacesuits/void/event.dm
+++ b/code/modules/clothing/spacesuits/void/event.dm
@@ -11,13 +11,16 @@
item_state_slots = list(SLOT_ID_RIGHT_HAND = "syndicate-helm-black", SLOT_ID_LEFT_HAND = "syndicate-helm-black")
armor_type = /datum/armor/vintage/space
light_overlay = "helmet_light"
+ encumbrance = ITEM_ENCUMBRANCE_VOIDSUIT_HELMET_LIGHT
+ weight = ITEM_WEIGHT_VOIDSUIT_HELMET_LIGHT
/obj/item/clothing/suit/space/void/refurb
name = "vintage crewman's voidsuit"
desc = "A refurbished early contact era voidsuit of human design. These things aren't especially good against modern weapons but they're sturdy, incredibly easy to come by, and there are lots of spare parts for repairs. Many old-timer spacers swear by these old things, even if new powered hardsuits have more features and better armor. This one is devoid of any identifying markings or rank indicators."
icon_state = "rig-vintagecrew"
item_state_slots = list(SLOT_ID_RIGHT_HAND = "sec_voidsuitTG", SLOT_ID_LEFT_HAND = "sec_voidsuitTG")
- slowdown = 0.5
+ encumbrance = ITEM_ENCUMBRANCE_VOIDSUIT_LIGHT
+ weight = ITEM_WEIGHT_VOIDSUIT_LIGHT
armor_type = /datum/armor/vintage/space
allowed = list(/obj/item/flashlight,
/obj/item/tank,
@@ -47,7 +50,6 @@
desc = "A refurbished early contact era voidsuit of human design. These things aren't especially good against modern weapons but they're sturdy, incredibly easy to come by, and there are lots of spare parts for repairs. This one in particular seems to be an ode to the Ship of Theseus, but the insulation and radiation proofing are top-notch. The chestplate bears the logo of an old shipyard - though you don't recognize the name."
icon_state = "rig-vintageengi"
item_state_slots = list(SLOT_ID_RIGHT_HAND = "sec_voidsuitTG", SLOT_ID_LEFT_HAND = "sec_voidsuitTG")
- slowdown = 1
armor_type = /datum/armor/vintage/space/engi
min_pressure_protection = 0 * ONE_ATMOSPHERE
max_pressure_protection = 15 * ONE_ATMOSPHERE
@@ -93,7 +95,6 @@
desc = "A refurbished early contact era voidsuit of human design. These things aren't especially good against modern weapons but they're sturdy, incredibly easy to come by, and there are lots of spare parts for repairs. Many old-timer spacers swear by these old things, even if new powered hardsuits have more features and better armor. The green and white markings indicate this as a medic's suit."
icon_state = "rig-vintagemedic"
item_state_slots = list(SLOT_ID_RIGHT_HAND = "sec_voidsuitTG", SLOT_ID_LEFT_HAND = "sec_voidsuitTG")
- slowdown = 0.5
armor_type = /datum/armor/vintage/space/med
allowed = list(/obj/item/flashlight,
/obj/item/tank,
@@ -124,7 +125,6 @@
desc = "A refurbished early contact era voidsuit of human design. These things aren't especially good against modern weapons but they're sturdy, incredibly easy to come by, and there are lots of spare parts for repairs. Many old-timer marines swear by these old things, even if new powered hardsuits have more features and better armor. The blue markings indicate this as the marine/guard variant, likely from a merchant ship."
icon_state = "rig-vintagemarine"
item_state_slots = list(SLOT_ID_RIGHT_HAND = "sec_voidsuitTG", SLOT_ID_LEFT_HAND = "sec_voidsuitTG")
- slowdown = 1
armor_type = /datum/armor/vintage/space/marine
siemens_coefficient = 0.8
allowed = list(/obj/item/gun,
@@ -160,7 +160,6 @@
desc = "A refurbished early contact era voidsuit of human design. These things aren't especially good against modern weapons but they're sturdy, incredibly easy to come by, and there are lots of spare parts for repairs. Many old-timer spacers swear by these old things, even if new powered hardsuits have more features and better armor. This variant appears to be an officer's, and has the best protection of all the old models."
icon_state = "rig-vintageofficer"
item_state_slots = list(SLOT_ID_RIGHT_HAND = "sec_voidsuitTG", SLOT_ID_LEFT_HAND = "sec_voidsuitTG")
- slowdown = 1
armor_type = /datum/armor/vintage/space/officer
siemens_coefficient = 0.7
allowed = list(/obj/item/gun,
@@ -201,7 +200,6 @@
desc = "A refurbished early contact era voidsuit of human design. These things aren't especially good against modern weapons but they're sturdy, incredibly easy to come by, and there are lots of spare parts for repairs. Many old-timer spacers swear by these old things, even if new powered hardsuits have more features and better armor. The royal blue markings indicate this is the pilot's variant; low protection but ultra-lightweight."
icon_state = "rig-vintagepilot"
item_state_slots = list(SLOT_ID_RIGHT_HAND = "sec_voidsuitTG", SLOT_ID_LEFT_HAND = "sec_voidsuitTG")
- slowdown = 0.25
armor_type = /datum/armor/vintage/space/pilot
siemens_coefficient = 0.9
allowed = list(/obj/item/flashlight,
@@ -232,7 +230,6 @@
desc = "A refurbished early contact era voidsuit of human design. These things aren't especially good against modern weapons but they're sturdy, incredibly easy to come by, and there are lots of spare parts for repairs. Many old-timer spacers swear by these old things, even if new powered hardsuits have more features and better armor. The purple markings indicate this as a scientist's suit. Keep your eyes open for ropes."
icon_state = "rig-vintagescientist"
item_state_slots = list(SLOT_ID_RIGHT_HAND = "sec_voidsuitTG", SLOT_ID_LEFT_HAND = "sec_voidsuitTG")
- slowdown = 0.5
armor_type = /datum/armor/vintage/space/science
siemens_coefficient = 0.8
allowed = list(/obj/item/flashlight,
@@ -267,13 +264,16 @@
item_state_slots = list(SLOT_ID_RIGHT_HAND = "syndicate-helm-black", SLOT_ID_LEFT_HAND = "syndicate-helm-black")
armor_type = /datum/armor/vintage/space/merc
siemens_coefficient = 0.6
+ encumbrance = ITEM_ENCUMBRANCE_VOIDSUIT_HELMET_HEAVY
+ weight = ITEM_WEIGHT_VOIDSUIT_HELMET_HEAVY
/obj/item/clothing/suit/space/void/refurb/mercenary
name = "vintage mercenary voidsuit"
desc = "A refurbished early contact era voidsuit of human design. These things aren't especially good against modern weapons but they're sturdy, incredibly easy to come by, and there are lots of spare parts for repairs. Many old-timer mercs swear by these old things, even if new powered hardsuits have more features and better armor. The red markings indicate this as the mercenary variant. The company ID has been scratched off."
icon_state = "rig-vintagemerc"
item_state_slots = list(SLOT_ID_RIGHT_HAND = "sec_voidsuitTG", SLOT_ID_LEFT_HAND = "sec_voidsuitTG")
- slowdown = 1.5 //the tradeoff for being hot shit almost on par with a crimson suit is that it slows you down even more
+ encumbrance = ITEM_ENCUMBRANCE_VOIDSUIT_HEAVY
+ weight = ITEM_WEIGHT_VOIDSUIT_HEAVY
armor_type = /datum/armor/vintage/space/merc
siemens_coefficient = 0.6
allowed = list(/obj/item/gun,
diff --git a/code/modules/clothing/spacesuits/void/merc.dm b/code/modules/clothing/spacesuits/void/merc.dm
index ce0633dcfaa4..c9fb92ef5ed2 100644
--- a/code/modules/clothing/spacesuits/void/merc.dm
+++ b/code/modules/clothing/spacesuits/void/merc.dm
@@ -6,6 +6,8 @@
item_state_slots = list(SLOT_ID_RIGHT_HAND = "syndie_helm", SLOT_ID_LEFT_HAND = "syndie_helm")
armor_type = /datum/armor/merc/space
siemens_coefficient = 0.6
+ encumbrance = ITEM_ENCUMBRANCE_VOIDSUIT_HELMET
+ weight = ITEM_WEIGHT_VOIDSUIT_HELMET
camera_networks = list(NETWORK_MERCENARY)
light_overlay = "helmet_light_green" //todo: species-specific light overlays
@@ -14,7 +16,8 @@
name = "blood-red voidsuit"
desc = "An advanced suit that protects against injuries during special operations. Property of Gorlex Marauders."
item_state_slots = list(SLOT_ID_RIGHT_HAND = "syndie_voidsuit", SLOT_ID_LEFT_HAND = "syndie_voidsuit")
- slowdown = 1
+ encumbrance = ITEM_ENCUMBRANCE_VOIDSUIT
+ weight = ITEM_WEIGHT_VOIDSUIT
w_class = ITEMSIZE_NORMAL
armor_type = /datum/armor/merc/space
allowed = list(/obj/item/flashlight,/obj/item/tank,/obj/item/suit_cooling_unit,/obj/item/gun,/obj/item/ammo_magazine,/obj/item/ammo_casing,/obj/item/melee/baton,/obj/item/melee/energy/sword,/obj/item/handcuffs)
@@ -86,7 +89,6 @@
name = "clown commando voidsuit"
desc = "An advanced suit that protects against injuries during special operations. An intricate bananium wafer in the shape of a banana bears the crest of Columbina."
item_state_slots = list(SLOT_ID_RIGHT_HAND = "syndie_voidsuit", SLOT_ID_LEFT_HAND = "syndie_voidsuit")
- slowdown = 1
w_class = ITEMSIZE_NORMAL
armor_type = /datum/armor/merc/space/clown
allowed = list(/obj/item/flashlight,/obj/item/tank,/obj/item/suit_cooling_unit,/obj/item/gun,/obj/item/ammo_magazine,/obj/item/ammo_casing,/obj/item/melee/baton,/obj/item/melee/energy/sword,/obj/item/handcuffs)
@@ -107,7 +109,6 @@
icon_state = "odst"
name = "hephaestus icarus suit"
desc = "One of the few combat-grade suits avalible in the frontier, and the poster-child of Hephaestus Industries. Comes equipped with a wrist-bound oxygen timer."
- slowdown = 1
w_class = ITEMSIZE_NORMAL
armor_type = /datum/armor/station/secsuit
allowed = list(/obj/item/flashlight,/obj/item/tank,/obj/item/suit_cooling_unit,/obj/item/gun,/obj/item/ammo_magazine,/obj/item/ammo_casing,/obj/item/melee/baton,/obj/item/melee/energy/sword,/obj/item/handcuffs)
@@ -127,7 +128,6 @@
icon_state = "odst_corps"
name = "hephaestus icarus medic suit"
desc = "A standard Icarus line suit that has been repourposed to protect from heavier biohazards."
- slowdown = 1
w_class = ITEMSIZE_NORMAL
armor_type = /datum/armor/exploration/space
allowed = list(/obj/item/flashlight,/obj/item/tank,/obj/item/suit_cooling_unit,/obj/item/gun,/obj/item/ammo_magazine,/obj/item/ammo_casing,/obj/item/melee/baton,/obj/item/melee/energy/sword,/obj/item/handcuffs)
@@ -147,7 +147,6 @@
icon_state = "odst_orange"
name = "hephaestus icarus engineer suit"
desc = "Favoured suit of deep-space engineers, comfortable and comparable to suits avalible to NanoTrasen Engineers. Comes equipped with a wrist-bound oxygen timer."
- slowdown = 1
w_class = ITEMSIZE_NORMAL
armor_type = /datum/armor/engineering/space
allowed = list(/obj/item/flashlight,/obj/item/tank,/obj/item/suit_cooling_unit,/obj/item/gun,/obj/item/ammo_magazine,/obj/item/ammo_casing,/obj/item/melee/baton,/obj/item/melee/energy/sword,/obj/item/handcuffs)
@@ -167,7 +166,6 @@
icon_state = "odst_purple"
name = "hephaestus icarus frontier suit"
desc = "Cheaper version of the main Icarus line, often marketed to Frontier settlements. Perfect for Expeditions."
- slowdown = 1
w_class = ITEMSIZE_NORMAL
armor_type = /datum/armor/exploration/space
allowed = list(/obj/item/flashlight,/obj/item/tank,/obj/item/suit_cooling_unit,/obj/item/gun,/obj/item/ammo_magazine,/obj/item/ammo_casing,/obj/item/melee/baton,/obj/item/melee/energy/sword,/obj/item/handcuffs)
@@ -191,7 +189,6 @@
name = "necropolis operations suit"
desc = "The main suit used by Necropolis Industries security division, a heavily modified Hephaestus Icarus suit emblazoned with the Necropolis logo on the left shoulder. Equipped with direct connections to the user's implants and prosthetics, making it function as a second skin."
item_state_slots = list(SLOT_ID_RIGHT_HAND = "syndie_voidsuit", SLOT_ID_LEFT_HAND = "syndie_voidsuit")
- slowdown = 0.4
w_class = ITEMSIZE_NORMAL
armor_type = /datum/armor/merc/space
allowed = list(/obj/item/flashlight,/obj/item/tank,/obj/item/suit_cooling_unit,/obj/item/gun,/obj/item/ammo_magazine,/obj/item/ammo_casing,/obj/item/melee/baton,/obj/item/melee/energy/sword,/obj/item/handcuffs)
@@ -203,9 +200,8 @@
name = "necropolis field medic suit"
desc = "The main suit used by Necropolis Industries security division, a heavily modified Hephaestheus Icarus suit emblazoned with the Necropolis logo on the left shoulder and a blue cross on the right arm. Equipped with direct connections to the user's implants and prosthetics, making it function as a second skin."
item_state_slots = list(SLOT_ID_RIGHT_HAND = "syndie_voidsuit", SLOT_ID_LEFT_HAND = "syndie_voidsuit")
- slowdown = 0.4
w_class = ITEMSIZE_NORMAL
armor_type = /datum/armor/merc/space
allowed = list(/obj/item/flashlight,/obj/item/tank,/obj/item/suit_cooling_unit,/obj/item/gun,/obj/item/ammo_magazine,/obj/item/ammo_casing,/obj/item/melee/baton,/obj/item/melee/energy/sword,/obj/item/handcuffs)
siemens_coefficient = 0.6
- species_restricted = null
+ species_restricted = null
diff --git a/code/modules/clothing/spacesuits/void/station.dm b/code/modules/clothing/spacesuits/void/station.dm
index 007848b460a4..2f43860e0a64 100644
--- a/code/modules/clothing/spacesuits/void/station.dm
+++ b/code/modules/clothing/spacesuits/void/station.dm
@@ -14,7 +14,6 @@
desc = "A special suit that protects against hazardous, low pressure environments. Has radiation shielding."
icon_state = "rig-engineering"
item_state_slots = list(SLOT_ID_RIGHT_HAND = "eng_voidsuit", SLOT_ID_LEFT_HAND = "eng_voidsuit")
- slowdown = 1
armor_type = /datum/armor/engineering/space
allowed = list(/obj/item/flashlight,/obj/item/tank,/obj/item/suit_cooling_unit,/obj/item/storage/bag/ore,/obj/item/t_scanner,/obj/item/pickaxe, /obj/item/rcd)
min_pressure_protection = 0 * ONE_ATMOSPHERE
@@ -162,6 +161,8 @@
icon_state = "rig0-medicalalt"
armor_type = /datum/armor/medical/space
light_overlay = "helmet_light_dual_blue"
+ encumbrance = ITEM_ENCUMBRANCE_VOIDSUIT_HELMET_ULTRALIGHT
+ weight = ITEM_WEIGHT_VOIDSUIT_HELMET_ULTRALIGHT
/obj/item/clothing/head/helmet/space/void/medical/alt_plated
name = "streamlined medical voidsuit helmet"
@@ -169,19 +170,23 @@
icon_state = "rig0-medicalalt2"
armor_type = /datum/armor/medical/space/upgraded
light_overlay = "helmet_light_dual_blue"
+ encumbrance = ITEM_ENCUMBRANCE_VOIDSUIT_HELMET_ULTRALIGHT
+ weight = ITEM_WEIGHT_VOIDSUIT_HELMET_ULTRALIGHT
/obj/item/clothing/suit/space/void/medical/alt
icon_state = "rig-medicalalt"
name = "streamlined medical voidsuit"
desc = "A more recent model of Vey-Med voidsuit, exchanging physical protection for fully unencumbered movement and a complete range of motion."
- slowdown = 0
+ encumbrance = ITEM_ENCUMBRANCE_VOIDSUIT_ULTRALIGHT
+ weight = ITEM_WEIGHT_VOIDSUIT_ULTRALIGHT
armor_type = /datum/armor/medical/space
/obj/item/clothing/suit/space/void/medical/alt_plated
icon_state = "rig-medicalalt2"
name = "plated medical voidsuit"
desc = "An iteration of an existing Vey-Med voidsuit, allowing full biohazard, radiation and increased close-quarters protection, at the expense of projectile and ranged layers."
- slowdown = 0
+ encumbrance = ITEM_ENCUMBRANCE_VOIDSUIT_ULTRALIGHT
+ weight = ITEM_WEIGHT_VOIDSUIT_ULTRALIGHT
armor_type = /datum/armor/medical/space/upgraded
//Security
@@ -373,7 +378,6 @@
icon_state = "capsuit_void"
armor_type = /datum/armor/station/tactical
allowed = list(/obj/item/flashlight,/obj/item/tank,/obj/item/suit_cooling_unit,/obj/item/gun)
- slowdown = 1.5
//Head of Security - update to the snowflake suit
/obj/item/clothing/head/helmet/space/void/headofsecurity
@@ -382,6 +386,8 @@
icon_state = "hosproto"
armor_type = /datum/armor/security/hos/space
camera_networks = list(NETWORK_SEC_HELMETS)
+ encumbrance = ITEM_ENCUMBRANCE_VOIDSUIT_HELMET_HEAVY
+ weight = ITEM_WEIGHT_VOIDSUIT_HELMET_HEAVY
/obj/item/clothing/suit/space/void/headofsecurity
desc = "A customized security voidsuit. Has additional composite armor."
@@ -389,7 +395,8 @@
icon_state = "hosproto_void"
armor_type = /datum/armor/security/hos/space
allowed = list(/obj/item/flashlight,/obj/item/tank,/obj/item/suit_cooling_unit,/obj/item/gun)
- slowdown = 1.5
+ encumbrance = ITEM_ENCUMBRANCE_VOIDSUIT_HEAVY
+ weight = ITEM_WEIGHT_VOIDSUIT_HEAVY
//PARA
/obj/item/clothing/head/helmet/space/void/para
diff --git a/code/modules/clothing/spacesuits/void/void.dm b/code/modules/clothing/spacesuits/void/void.dm
index 1931d2d7e215..63edea0cc322 100644
--- a/code/modules/clothing/spacesuits/void/void.dm
+++ b/code/modules/clothing/spacesuits/void/void.dm
@@ -9,6 +9,9 @@
max_heat_protection_temperature = SPACE_SUIT_MAX_HEAT_PROTECTION_TEMPERATURE
min_pressure_protection = 0 * ONE_ATMOSPHERE
max_pressure_protection = 10 * ONE_ATMOSPHERE
+ encumbrance = ITEM_ENCUMBRANCE_VOIDSUIT_HELMET
+ weight = ITEM_WEIGHT_VOIDSUIT_HELMET
+
// inv_hide_flags = HIDEEARS|BLOCKHAIR
@@ -37,7 +40,8 @@
icon_state = "void"
item_state_slots = list(SLOT_ID_RIGHT_HAND = "space_suit_syndicate", SLOT_ID_LEFT_HAND = "space_suit_syndicate")
desc = "A high-tech dark red space suit. Used for AI satellite maintenance."
- slowdown = 1
+ encumbrance = ITEM_ENCUMBRANCE_VOIDSUIT
+ weight = ITEM_WEIGHT_VOIDSUIT
armor_type = /datum/armor/general/space/armored
allowed = list(/obj/item/flashlight,/obj/item/tank,/obj/item/suit_cooling_unit)
heat_protection = UPPER_TORSO|LOWER_TORSO|LEGS|FEET|ARMS|HANDS
@@ -81,6 +85,17 @@
action_button_name = "Toggle Helmet"
+/obj/item/clothing/suit/space/void/get_weight()
+ . = ..()
+ if(boots?.loc == src)
+ . += boots.get_weight()
+ if(helmet?.loc == src)
+ . += helmet.get_weight()
+ if(tank?.loc == src)
+ . += tank.get_weight()
+ if(cooler?.loc == src)
+ . += cooler.get_weight()
+
/obj/item/clothing/suit/space/void/examine(mob/user, dist)
. = ..()
var/list/part_list = new
diff --git a/code/modules/clothing/spacesuits/void/void_vr.dm b/code/modules/clothing/spacesuits/void/void_vr.dm
index fa35d972d674..756207f9efc4 100644
--- a/code/modules/clothing/spacesuits/void/void_vr.dm
+++ b/code/modules/clothing/spacesuits/void/void_vr.dm
@@ -115,7 +115,8 @@
icon_state = "autoloksuit"
item_state = "autoloksuit"
armor_type = /datum/armor/autolok/space
- slowdown = 0.5
+ encumbrance = ITEM_ENCUMBRANCE_VOIDSUIT_LIGHT
+ weight = ITEM_WEIGHT_VOIDSUIT_LIGHT
siemens_coefficient = 1
species_restricted = list("exclude",SPECIES_DIONA,SPECIES_VOX) //this thing can autoadapt
breach_threshold = 6 //this thing is basically tissue paper
diff --git a/code/modules/clothing/spacesuits/void/wizard.dm b/code/modules/clothing/spacesuits/void/wizard.dm
index 5072351338bf..14c307259942 100644
--- a/code/modules/clothing/spacesuits/void/wizard.dm
+++ b/code/modules/clothing/spacesuits/void/wizard.dm
@@ -16,7 +16,8 @@
name = "gem-encrusted voidsuit"
desc = "A bizarre gem-encrusted suit that radiates magical energies."
item_state_slots = list(SLOT_ID_RIGHT_HAND = "wiz_voidsuit", SLOT_ID_LEFT_HAND = "wiz_voidsuit")
- slowdown = 1
+ encumbrance = ITEM_ENCUMBRANCE_VOIDSUIT_LIGHT
+ weight = ITEM_WEIGHT_VOIDSUIT_LIGHT
w_class = ITEMSIZE_NORMAL
unacidable = 1
armor_type = /datum/armor/wizard
diff --git a/code/modules/clothing/spacesuits/void/zaddat.dm b/code/modules/clothing/spacesuits/void/zaddat.dm
index 61456871d7a8..3502ce939f7d 100644
--- a/code/modules/clothing/spacesuits/void/zaddat.dm
+++ b/code/modules/clothing/spacesuits/void/zaddat.dm
@@ -5,7 +5,6 @@
item_state_slots = list(SLOT_ID_RIGHT_HAND = "syndicate", SLOT_ID_LEFT_HAND = "syndicate")
heat_protection = HEAD
body_cover_flags = HEAD|FACE|EYES
- slowdown = 0.5
armor_type = /datum/armor/zaddat
siemens_coefficient = 1
@@ -14,7 +13,6 @@
/obj/item/clothing/suit/space/void/zaddat
name = "\improper Hegemony Shroud"
desc = "A Hegemony environment suit, still favored by the Spacer Zaddat because of its durability and ease of manufacture."
- slowdown = 1
armor_type = /datum/armor/zaddat
siemens_coefficient = 1
allowed = list(/obj/item/flashlight,/obj/item/tank)
diff --git a/code/modules/clothing/suits/aliens/tajara.dm b/code/modules/clothing/suits/aliens/tajara.dm
index e86caf3513be..cf87201c829d 100644
--- a/code/modules/clothing/suits/aliens/tajara.dm
+++ b/code/modules/clothing/suits/aliens/tajara.dm
@@ -30,7 +30,8 @@
inv_hide_flags = HIDEJUMPSUIT|HIDETAIL|HIDETIE|HIDEHOLSTER
species_restricted = list(SPECIES_TAJ)
armor_type = /datum/armor/general/medieval
- slowdown = 0.5
+ weight = ITEM_WEIGHT_TAJARAN_SWORDSMAN_ARMOR
+ encumbrance = ITEM_ENCUMBRANCE_TAJARAN_SWORDSMAN_ARMOR
siemens_coefficient = 0.35
//Coats no hoods
diff --git a/code/modules/clothing/suits/armor.dm b/code/modules/clothing/suits/armor.dm
index e6574f0ac896..bdbf8e89f213 100644
--- a/code/modules/clothing/suits/armor.dm
+++ b/code/modules/clothing/suits/armor.dm
@@ -69,7 +69,8 @@
icon_state = "bulletproof"
item_state_slots = list(SLOT_ID_RIGHT_HAND = "armor", SLOT_ID_LEFT_HAND = "armor")
blood_overlay_type = "armor"
- slowdown = 0.5
+ encumbrance = ITEM_ENCUMBRANCE_ARMOR_SPECIALIZED
+ weight = ITEM_WEIGHT_ARMOR_SPECIALIZED
armor_type = /datum/armor/station/ballistic
siemens_coefficient = 0.7
@@ -83,7 +84,6 @@
desc = "A vest that excels in protecting the wearer against energy projectiles."
icon_state = "armor_reflec"
blood_overlay_type = "armor"
- slowdown = 0.5
armor_type = /datum/armor/station/ablative
siemens_coefficient = 0.1
@@ -116,7 +116,8 @@
desc = "A vest that protects the wearer from several common types of ranged weaponry."
icon_state = "combat"
blood_overlay_type = "armor"
- slowdown = 0.5
+ encumbrance = ITEM_ENCUMBRANCE_ARMOR_MEDIUM
+ weight = ITEM_WEIGHT_ARMOR_MEDIUM
armor_type = /datum/armor/station/combat
siemens_coefficient = 0.6
@@ -127,7 +128,8 @@
item_state_slots = list(SLOT_ID_RIGHT_HAND = "swat", SLOT_ID_LEFT_HAND = "swat")
body_cover_flags = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS
inv_hide_flags = HIDETIE|HIDEHOLSTER
- slowdown = 1
+ encumbrance = ITEM_ENCUMBRANCE_ARMOR_LIGHT
+ weight = ITEM_WEIGHT_ARMOR_LIGHT
armor_type = /datum/armor/station/tactical
siemens_coefficient = 0.7
@@ -141,7 +143,8 @@
clothing_flags = CLOTHING_THICK_MATERIAL
body_cover_flags = UPPER_TORSO|LOWER_TORSO|LEGS|FEET|ARMS
allowed = list(/obj/item/gun,/obj/item/ammo_magazine,/obj/item/ammo_casing,/obj/item/melee/baton,/obj/item/handcuffs,/obj/item/tank/emergency/oxygen,/obj/item/clothing/head/helmet)
- slowdown = 1
+ encumbrance = ITEM_ENCUMBRANCE_ARMOR_HEAVY + ITEM_ENCUMBRANCE_ARMOR_HEAVY_BOOTS + ITEM_ENCUMBRANCE_ARMOR_HEAVY_GLOVES
+ weight = ITEM_WEIGHT_ARMOR_HEAVY + ITEM_WEIGHT_ARMOR_HEAVY_BOOTS + ITEM_WEIGHT_ARMOR_HEAVY_GLOVES
w_class = ITEMSIZE_HUGE
armor_type = /datum/armor/centcom/deathsquad
inv_hide_flags = HIDEGLOVES|HIDESHOES|HIDEJUMPSUIT|HIDETIE|HIDEHOLSTER
@@ -160,6 +163,8 @@
blood_overlay_type = "coat"
inv_hide_flags = 0
body_cover_flags = UPPER_TORSO|ARMS
+ encumbrance = ITEM_ENCUMBRANCE_ARMOR_HEAVY
+ weight = ITEM_WEIGHT_ARMOR_HEAVY
/obj/item/clothing/suit/armor/det_suit
name = "armor"
@@ -430,7 +435,8 @@
item_state = "flexitac"
cold_protection = UPPER_TORSO|LOWER_TORSO
min_cold_protection_temperature = T0C - 20
- slowdown = 0.3
+ encumbrance = ITEM_ENCUMBRANCE_ARMOR_MEDIUM
+ weight = ITEM_WEIGHT_ARMOR_MEDIUM
/obj/item/clothing/suit/storage/vest/detective
name = "detective armor vest"
@@ -453,7 +459,8 @@
icon_state = "webvest"
item_state_slots = list(SLOT_ID_RIGHT_HAND = "swat", SLOT_ID_LEFT_HAND = "swat")
armor_type = /datum/armor/station/heavy
- slowdown = 0.5
+ encumbrance = ITEM_ENCUMBRANCE_ARMOR_HEAVY
+ weight = ITEM_WEIGHT_ARMOR_HEAVY
/obj/item/clothing/suit/storage/vest/heavy/officer
name = "officer heavy armor vest"
@@ -494,7 +501,8 @@
icon_state = "mercwebvest"
item_state_slots = list(SLOT_ID_RIGHT_HAND = "swat", SLOT_ID_LEFT_HAND = "swat")
armor_type = /datum/armor/station/combat
- slowdown = 0
+ encumbrance = ITEM_ENCUMBRANCE_ARMOR_MEDIUM
+ weight = ITEM_WEIGHT_ARMOR_MEDIUM
/obj/item/clothing/suit/storage/vest/capcarapace
name = "captain's carapace"
@@ -566,9 +574,10 @@
w_class = ITEMSIZE_HUGE // Very bulky, very heavy.
gas_transfer_coefficient = 0.90
body_cover_flags = UPPER_TORSO|LOWER_TORSO|LEGS|FEET|ARMS|HANDS
- slowdown = 5 // If you're a tank you're gonna move like a tank.
inv_hide_flags = HIDEGLOVES|HIDESHOES|HIDEJUMPSUIT|HIDETIE|HIDEHOLSTER
siemens_coefficient = 0
+ encumbrance = ITEM_ENCUMBRANCE_ARMOR_SUPERHEAVY + ITEM_ENCUMBRANCE_ARMOR_SUPERHEAVY_GLOVES + ITEM_ENCUMBRANCE_ARMOR_SUPERHEAVY_BOOTS
+ weight = ITEM_WEIGHT_ARMOR_SUPERHEAVY + ITEM_ENCUMBRANCE_ARMOR_SUPERHEAVY_GLOVES + ITEM_ENCUMBRANCE_ARMOR_SUPERHEAVY_BOOTS
/obj/item/clothing/suit/armor/tdome
body_cover_flags = UPPER_TORSO|LOWER_TORSO|LEGS|FEET|ARMS|HANDS
diff --git a/code/modules/clothing/suits/bio.dm b/code/modules/clothing/suits/bio.dm
index 58777abcd83a..da3851ca62af 100644
--- a/code/modules/clothing/suits/bio.dm
+++ b/code/modules/clothing/suits/bio.dm
@@ -10,6 +10,7 @@
siemens_coefficient = 0.9
atom_flags = PHORONGUARD
clothing_flags = CLOTHING_THICK_MATERIAL | ALLOW_SURVIVALFOOD
+ encumbrance
/obj/item/clothing/suit/bio_suit
name = "bio suit"
@@ -19,7 +20,7 @@
gas_transfer_coefficient = 0.01
permeability_coefficient = 0.01
body_cover_flags = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS|HANDS|FEET
- slowdown = 1.0
+ weight = ITEM_WEIGHT_ARMOR_BIORAD_SUIT
allowed = list(/obj/item/tank/emergency/oxygen,/obj/item/pen,/obj/item/flashlight/pen)
armor_type = /datum/armor/general/biosuit
inv_hide_flags = HIDEGLOVES|HIDESHOES|HIDEJUMPSUIT|HIDETAIL|HIDETIE|HIDEHOLSTER
@@ -113,7 +114,7 @@
gas_transfer_coefficient = 0.01
permeability_coefficient = 0.01
body_cover_flags = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS|HANDS|FEET
- slowdown = 1.0
+ weight = ITEM_WEIGHT_ARMOR_BIORAD_SUIT
allowed = list(/obj/item/tank/emergency/oxygen,/obj/item/pen,/obj/item/flashlight/pen)
armor_type = /datum/armor/general/beekeeper
inv_hide_flags = HIDEGLOVES|HIDESHOES|HIDEJUMPSUIT|HIDETAIL|HIDETIE|HIDEHOLSTER
diff --git a/code/modules/clothing/suits/medieval_armor.dm b/code/modules/clothing/suits/medieval_armor.dm
index 87e188ceb33c..19235b21c59c 100644
--- a/code/modules/clothing/suits/medieval_armor.dm
+++ b/code/modules/clothing/suits/medieval_armor.dm
@@ -50,7 +50,8 @@
armor_type = /datum/armor/general/medieval
icon = 'icons/clothing/suit/armor/medieval/knight.dmi'
icon_state = "knight"
- slowdown = 1
+ encumbrance = ITEM_ENCUMBRANCE_ARMOR_MEDIEVAL_PLATE
+ weight = ITEM_WEIGHT_ARMOR_MEDIEVAL_PLATE
inv_hide_flags = HIDEGLOVES|HIDESHOES|HIDEJUMPSUIT|HIDETIE|HIDEHOLSTER
body_cover_flags = UPPER_TORSO|LOWER_TORSO|ARMS|HANDS|LEGS|FEET
worn_render_flags = WORN_RENDER_SLOT_ONE_FOR_ALL
@@ -79,7 +80,8 @@
armor_type = /datum/armor/general/medieval/light
icon = 'icons/clothing/suit/armor/medieval/bastard.dmi'
icon_state = "bastard"
- slowdown = 0
+ weight = ITEM_WEIGHT_ARMOR_MEDIEVAL_CHAIN
+ encumbrance = ITEM_ENCUMBRANCE_ARMOR_MEDIEVAL_CHAIN
/obj/item/clothing/suit/armor/medieval/paladin
name = "elite paladin plate"
@@ -87,7 +89,8 @@
armor_type = /datum/armor/general/medieval/mesh
icon = 'icons/clothing/suit/armor/medieval/paladin.dmi'
icon_state = "paladin"
- slowdown = 0
+ weight = ITEM_WEIGHT_ARMOR_MEDIEVAL_CHAIN
+ encumbrance = ITEM_ENCUMBRANCE_ARMOR_MEDIEVAL_CHAIN
//Crusader stuff
//Helmets
diff --git a/code/modules/clothing/suits/utility.dm b/code/modules/clothing/suits/utility.dm
index fe85ebfac383..41a5e2265d88 100644
--- a/code/modules/clothing/suits/utility.dm
+++ b/code/modules/clothing/suits/utility.dm
@@ -18,7 +18,8 @@
permeability_coefficient = 0.50
body_cover_flags = UPPER_TORSO|LOWER_TORSO|LEGS|FEET|ARMS|HANDS
allowed = list(/obj/item/flashlight,/obj/item/tank/emergency/oxygen,/obj/item/extinguisher)
- slowdown = 1.0
+ encumbrance = ITEM_ENCUMBRANCE_ARMOR_FIRE_SUIT
+ weight = ITEM_WEIGHT_ARMOR_FIRE_SUIT
inv_hide_flags = HIDEGLOVES|HIDESHOES|HIDEJUMPSUIT|HIDETAIL|HIDETIE|HIDEHOLSTER
clothing_flags = 0
heat_protection = UPPER_TORSO|LOWER_TORSO|LEGS|FEET|ARMS|HANDS
@@ -31,14 +32,6 @@
/obj/item/clothing/suit/fire/firefighter
icon_state = "firesuit"
-/obj/item/clothing/suit/fire/heavy //Is this even used?? -S2-
- name = "firesuit"
- desc = "A suit that protects against extreme fire and heat."
- //icon_state = "thermal"
- item_state_slots = list(SLOT_ID_RIGHT_HAND = "black_suit", SLOT_ID_LEFT_HAND = "black_suit")
- w_class = ITEMSIZE_LARGE//bulky item
- slowdown = 1.5
-
/*
* Bomb protection
*/
@@ -50,6 +43,8 @@
inv_hide_flags = HIDEMASK|HIDEEARS|HIDEEYES|BLOCKHAIR
body_cover_flags = HEAD|FACE|EYES
siemens_coefficient = 0
+ encumbrance = ITEM_ENCUMBRANCE_ARMOR_BOMB_HELMET
+ weight = ITEM_WEIGHT_ARMOR_BOMB_HELMET
/obj/item/clothing/suit/bomb_suit
name = "bomb suit"
@@ -58,7 +53,8 @@
w_class = ITEMSIZE_LARGE//bulky item
gas_transfer_coefficient = 0.01
permeability_coefficient = 0.01
- slowdown = 2
+ encumbrance = ITEM_ENCUMBRANCE_ARMOR_BOMB_SUIT
+ weight = ITEM_WEIGHT_ARMOR_BOMB_SUIT
armor_type = /datum/armor/station/bomb
inv_hide_flags = HIDEJUMPSUIT|HIDETAIL|HIDETIE|HIDEHOLSTER
heat_protection = UPPER_TORSO|LOWER_TORSO
@@ -85,6 +81,8 @@
clothing_flags = CLOTHING_THICK_MATERIAL
body_cover_flags = HEAD|FACE|EYES
armor_type = /datum/armor/general/radsuit
+ weight = ITEM_WEIGHT_ARMOR_BIORAD_SUIT_HELMET
+ encumbrance = ITEM_ENCUMBRANCE_ARMOR_BIORAD_HELMET
/obj/item/clothing/suit/radiation
name = "Radiation suit"
@@ -95,7 +93,8 @@
permeability_coefficient = 0.50
body_cover_flags = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS|HANDS|FEET
allowed = list(/obj/item/flashlight,/obj/item/tank/emergency/oxygen,/obj/item/clothing/head/radiation,/obj/item/clothing/mask/gas)
- slowdown = 1.5
+ weight = ITEM_WEIGHT_ARMOR_BIORAD_SUIT
armor_type = /datum/armor/general/radsuit
inv_hide_flags = HIDEJUMPSUIT|HIDETAIL|HIDETIE|HIDEHOLSTER
clothing_flags = CLOTHING_THICK_MATERIAL
+ encumbrance = ITEM_ENCUMBRANCE_ARMOR_BIORAD_SUIT
diff --git a/code/modules/clothing/under/accessories/armor.dm b/code/modules/clothing/under/accessories/armor.dm
index dbdadcb1fbd7..c0c12bc5cdbd 100644
--- a/code/modules/clothing/under/accessories/armor.dm
+++ b/code/modules/clothing/under/accessories/armor.dm
@@ -63,7 +63,8 @@
desc = "A collection of black pouches that can be attached to a plate carrier. Carries up to four items."
icon_state = "lpouches"
slots = 4
- slowdown = 0.25
+ weight = ITEM_WEIGHT_STORAGE_POUCH_LARGE
+ encumbrance = ITEM_ENCUMBRANCE_STORAGE_POUCH_LARGE
/obj/item/clothing/accessory/storage/pouches/large/blue
desc = "A collection of blue pouches that can be attached to a plate carrier. Carries up to four items."
@@ -162,14 +163,16 @@
name = "ballistic armor plate"
desc = "A hefty silicon carbide armor plate with a layer of heavy tungsten, followed by a second coating of a polyurethane elastomeric to mitigate spalling from lower calibers as they're deflected. It's design is state of of the art when it comes to ballistics, and as a concequence the material is rather heavy, and is not as capable of dispersing laser fire as other armor varients. Fits within a plate carrier."
icon_state = "armor_ballistic"
- slowdown = 0.65
+ weight = ITEM_WEIGHT_ARMOR_SPECIALIZED
+ encumbrance = ITEM_ENCUMBRANCE_ARMOR_SPECIALIZED
armor_type = /datum/armor/station/ballistic
/obj/item/clothing/accessory/armor/armorplate/riot
name = "riot armor plate"
desc = "A synthetic mesh armor insert made of densely woven aromatic polyamide fibers, coated in malleable ballistic gelatin, and finally tight-jacketed with woven steel-polyethylene filaments. This provides excellent protection against low-velocity trauma, but most modern projectiles could tear through it with ease. Fits within a plate carrier."
icon_state = "armor_riot"
- slowdown = 0.65
+ weight = ITEM_WEIGHT_ARMOR_SPECIALIZED
+ encumbrance = ITEM_ENCUMBRANCE_ARMOR_SPECIALIZED
armor_type = /datum/armor/station/riot
siemens_coefficient = 0.5
@@ -177,7 +180,8 @@
name = "ablative armor plate"
desc = "A highly reflective cobalt-chromium-tungsten alloy forms the seemingly jagged surface of the armor plate, which is adorned in perfectly cut and fitted glass prisms that form a smooth low-poly surface. When the ablative armor plate is working as designed, the glass prisms reflect laser fire inwards towards the innermost vertex for subsequent 'ablation', and sometimes reflection. There is a warning label on the back that warns you. It reads: Attempting to use this ablative armor plate to deflect ballistics and/or non-standard energy beams could result in 'rapid deconstruction' of the armor plate and its user. Fits within a plate carrier."
icon_state = "armor_ablative"
- slowdown = 0.65
+ weight = ITEM_WEIGHT_ARMOR_SPECIALIZED
+ encumbrance = ITEM_ENCUMBRANCE_ARMOR_SPECIALIZED
armor_type = /datum/armor/station/ablative
siemens_coefficient = 0.2
diff --git a/code/modules/clothing/under/nanotrasen_vr.dm b/code/modules/clothing/under/nanotrasen_vr.dm
index fa8d2a9217aa..273643cd59e0 100644
--- a/code/modules/clothing/under/nanotrasen_vr.dm
+++ b/code/modules/clothing/under/nanotrasen_vr.dm
@@ -52,4 +52,4 @@
icon_state = "webvest"
item_state_slots = list(SLOT_ID_RIGHT_HAND = "swat", SLOT_ID_LEFT_HAND = "swat")
armor_type = /datum/armor/station/tactical
- slowdown = 0.5
+ weight = ITEM_WEIGHT_ARMOR_LIGHT
diff --git a/code/modules/detectivework/tools/rag.dm b/code/modules/detectivework/tools/rag.dm
index dcb7dc037677..a6556eb4522d 100644
--- a/code/modules/detectivework/tools/rag.dm
+++ b/code/modules/detectivework/tools/rag.dm
@@ -23,7 +23,7 @@
possible_transfer_amounts = list(3)
volume = 4
can_be_placed_into = null
- item_flags = ITEM_NOBLUDGEON
+ item_flags = ITEM_NOBLUDGEON | ITEM_ENCUMBERS_WHILE_HELD
atom_flags = OPENCONTAINER
unacidable = 0
drop_sound = 'sound/items/drop/cloth.ogg'
diff --git a/code/modules/detectivework/tools/scanner.dm b/code/modules/detectivework/tools/scanner.dm
index d0f67ac5b7fa..dfe4070a7fb3 100644
--- a/code/modules/detectivework/tools/scanner.dm
+++ b/code/modules/detectivework/tools/scanner.dm
@@ -6,7 +6,7 @@
var/list/stored = list()
w_class = ITEMSIZE_SMALL
item_state = "electronic"
- item_flags = ITEM_NOBLUDGEON
+ item_flags = ITEM_NOBLUDGEON | ITEM_ENCUMBERS_WHILE_HELD
slot_flags = SLOT_BELT
var/reveal_fingerprints = TRUE
diff --git a/code/modules/economy/items/retail_scanner.dm b/code/modules/economy/items/retail_scanner.dm
index d6729be41c36..511b95c6d559 100644
--- a/code/modules/economy/items/retail_scanner.dm
+++ b/code/modules/economy/items/retail_scanner.dm
@@ -3,7 +3,7 @@
desc = "Swipe your ID card to make purchases electronically."
icon = 'icons/obj/device.dmi'
icon_state = "retail_idle"
- item_flags = ITEM_NOBLUDGEON
+ item_flags = ITEM_NOBLUDGEON | ITEM_ENCUMBERS_WHILE_HELD
slot_flags = SLOT_BELT
req_access = list(ACCESS_COMMAND_BRIDGE)
w_class = ITEMSIZE_SMALL
diff --git a/code/modules/fishing/fish.dm b/code/modules/fishing/fish.dm
index 8d4a4068424a..8f96c42bf57f 100644
--- a/code/modules/fishing/fish.dm
+++ b/code/modules/fishing/fish.dm
@@ -14,8 +14,8 @@
/// Average size for this fish type in centimeters. Will be used as gaussian distribution with 20% deviation for fishing, bought fish are always standard size
var/average_size = 50
/// Weight in grams
- var/weight = 1000
- /// Average weight for this fish type in grams
+ var/fish_weight = 1000
+ /// Average fish_weight for this fish type in grams
var/average_weight = 1000
//? icon
@@ -114,13 +114,13 @@
START_PROCESSING(SSobj, src)
size = average_size
- weight = average_weight
+ fish_weight = average_weight
/obj/item/fish/examine(mob/user, dist)
. = ..()
- // All spacemen have magic eyes of fish weight perception until fish scale (get it?) is implemented.
+ // All spacemen have magic eyes of fish fish_weight perception until fish scale (get it?) is implemented.
. += SPAN_NOTICE("It's [size] cm long.")
- . += SPAN_NOTICE("It weighs [weight] g.")
+ . += SPAN_NOTICE("It weighs [fish_weight] g.")
/obj/item/fish/proc/randomize_weight_and_size(modifier = 0)
var/size_deviation = 0.2 * average_size
@@ -129,7 +129,7 @@
var/weight_deviation = 0.2 * average_weight
var/weight_mod = modifier * average_weight
- weight = max(1,gaussian(average_weight + weight_mod, weight_deviation))
+ fish_weight = max(1,gaussian(average_weight + weight_mod, weight_deviation))
/obj/item/fish/Moved(atom/old_loc, movement_dir, forced, list/old_locs, momentum_change)
. = ..()
diff --git a/code/modules/hardsuits/_rig.dm b/code/modules/hardsuits/_rig.dm
index e7535c476e5f..4f2dc6574899 100644
--- a/code/modules/hardsuits/_rig.dm
+++ b/code/modules/hardsuits/_rig.dm
@@ -32,6 +32,11 @@
unacidable = 1
preserve_item = 1
+ weight = ITEM_WEIGHT_BASELINE
+ encumbrance = ITEM_ENCUMBRANCE_LEGACY_RIG
+ var/online_encumbrance
+ var/offline_encumbrance = ITEM_WEIGHT_LEGACY_RIG * 2
+
// Activation
/// activation state
var/activation_state = RIG_ACTIVATION_OFF
@@ -93,7 +98,6 @@
var/locked_down = 0
var/seal_delay = SEAL_DELAY
- var/offline_slowdown = 3 // If the suit is deployed and unpowered, it sets slowdown to this.
var/vision_restriction
var/offline_vision_restriction = 1 // 0 - none, 1 - welder vision, 2 - blind. Maybe move this to helmets.
var/airtight = 1 //If set, will adjust ALLOWINTERNALS flag and pressure protections on components. Otherwise it should leave them untouched.
@@ -562,13 +566,10 @@
last_online = FALSE
for(var/obj/item/hardsuit_module/module in installed_modules)
module.deactivate()
- slowdown = offline_slowdown
+ set_encumbrance(offline_encumbrance)
if(istype(wearer))
if(is_activated())
- if (offline_slowdown < 3)
- to_chat(wearer, "Your suit beeps stridently, and suddenly goes dead.")
- else
- to_chat(wearer, "Your suit beeps stridently, and suddenly you're wearing a leaden mass of metal and plastic composites instead of a powered suit.")
+ to_chat(wearer, "Your suit beeps stridently, and suddenly you're wearing a leaden mass of metal and plastic composites instead of a powered suit.")
if(offline_vision_restriction == 1)
to_chat(wearer, "The suit optics flicker and die, leaving you with restricted vision.")
else if(offline_vision_restriction == 2)
@@ -581,7 +582,8 @@
last_online = TRUE
if(istype(wearer) && !wearer.wearing_rig)
wearer.wearing_rig = src
- slowdown = initial(slowdown) + sprint_slowdown_modifier
+ set_encumbrance(isnull(online_encumbrance)? initial(encumbrance) : online_encumbrance)
+ set_slowdown(initial(slowdown) + sprint_slowdown_modifier)
if(cell && cell.charge > 0 && electrified > 0)
electrified--
diff --git a/code/modules/hardsuits/modules/utility.dm b/code/modules/hardsuits/modules/utility.dm
index 86d1f9d36926..107fa2e5c84b 100644
--- a/code/modules/hardsuits/modules/utility.dm
+++ b/code/modules/hardsuits/modules/utility.dm
@@ -647,7 +647,7 @@
to_chat(H, "You activate the suit's sprint mode.")
- holder.slowdown -= sprint_speed
+ holder.set_slowdown(holder.slowdown - sprint_speed)
holder.sprint_slowdown_modifier = -sprint_speed
/obj/item/hardsuit_module/sprinter/deactivate()
@@ -659,7 +659,7 @@
to_chat(H, "Your hardsuit returns to normal speed.")
- holder.slowdown += sprint_speed
+ holder.set_slowdown(holder.slowdown + sprint_speed)
holder.sprint_slowdown_modifier = 0
/obj/item/hardsuit_module/device/hand_defib
diff --git a/code/modules/hardsuits/rig_pieces.dm b/code/modules/hardsuits/rig_pieces.dm
index f06fd025829c..c4070fef4f73 100644
--- a/code/modules/hardsuits/rig_pieces.dm
+++ b/code/modules/hardsuits/rig_pieces.dm
@@ -16,6 +16,9 @@
min_pressure_protection = null
damage_force = 3 // if you're headbutting someone with something meant to protect you from space...
+ weight = 0
+ encumbrance = 0
+
species_restricted = list(
SPECIES_AKULA,
SPECIES_ALRAUNE,
@@ -50,6 +53,9 @@
heat_protection = HANDS
cold_protection = HANDS
+ weight = 0
+ encumbrance = 0
+
species_restricted = list(
SPECIES_AKULA,
SPECIES_ALRAUNE,
@@ -87,6 +93,9 @@
icon_base = null
damage_force = 5 // if you're kicking someone with something meant to keep you locked on a hunk of metal...
+ weight = 0
+ encumbrance = 0
+
species_restricted = list(
SPECIES_AKULA,
SPECIES_ALRAUNE,
@@ -125,7 +134,8 @@
inv_hide_flags = HIDEJUMPSUIT|HIDETAIL
heat_protection = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS
- slowdown = NONE
+ weight = 0
+ encumbrance = 0
// Will reach 10 breach damage after 25 laser carbine blasts, 3 revolver hits, or ~1 PTR hit.
// Completely immune to smg or sts hits.
diff --git a/code/modules/hardsuits/suits/combat.dm b/code/modules/hardsuits/suits/combat.dm
index 6f0dcf4db3fc..ae94a2f3f158 100644
--- a/code/modules/hardsuits/suits/combat.dm
+++ b/code/modules/hardsuits/suits/combat.dm
@@ -16,8 +16,8 @@
icon_state = "security_rig"
suit_type = "combat hardsuit"
armor_type = /datum/armor/hardsuit/combat
- slowdown = 1
- offline_slowdown = 3
+ encumbrance = ITEM_ENCUMBRANCE_LEGACY_RIG_HEAVY
+ offline_encumbrance = ITEM_ENCUMBRANCE_LEGACY_RIG_HEAVY * 2
offline_vision_restriction = 1
helm_type = /obj/item/clothing/head/helmet/space/hardsuit/combat
@@ -65,8 +65,8 @@
icon_state = "military_rig"
suit_type = "military hardsuit"
armor_type = /datum/armor/hardsuit/military
- slowdown = 1
- offline_slowdown = 3
+ encumbrance = ITEM_ENCUMBRANCE_LEGACY_RIG_HEAVY
+ offline_encumbrance = ITEM_ENCUMBRANCE_LEGACY_RIG_HEAVY * 2
offline_vision_restriction = 1
allowed = list(
/obj/item/flashlight,
diff --git a/code/modules/hardsuits/suits/light.dm b/code/modules/hardsuits/suits/light.dm
index da0613ba8262..59c745e9e3f4 100644
--- a/code/modules/hardsuits/suits/light.dm
+++ b/code/modules/hardsuits/suits/light.dm
@@ -14,9 +14,9 @@
allowed = list(/obj/item/gun,/obj/item/ammo_magazine,/obj/item/ammo_casing,/obj/item/melee/baton,/obj/item/handcuffs,/obj/item/tank,/obj/item/suit_cooling_unit,/obj/item/cell)
armor_type = /datum/armor/hardsuit/light
emp_protection = 10
- slowdown = 0
+ encumbrance = ITEM_ENCUMBRANCE_LEGACY_RIG_LIGHT
+ offline_encumbrance = ITEM_ENCUMBRANCE_LEGACY_RIG_LIGHT * 2
clothing_flags = CLOTHING_THICK_MATERIAL
- offline_slowdown = 0
offline_vision_restriction = 0
chest_type = /obj/item/clothing/suit/space/hardsuit/light
@@ -88,7 +88,6 @@
desc = "A unique suit of nano-enhanced armor designed for covert operations."
icon_state = "ninja_rig"
emp_protection = 40 //change this to 30 if too high.
- slowdown = 0
chest_type = /obj/item/clothing/suit/space/hardsuit/light/ninja
glove_type = /obj/item/clothing/gloves/gauntlets/hardsuit/light/ninja
diff --git a/code/modules/hardsuits/suits/merc.dm b/code/modules/hardsuits/suits/merc.dm
index 5dd2f90d1e99..72e78c098c70 100644
--- a/code/modules/hardsuits/suits/merc.dm
+++ b/code/modules/hardsuits/suits/merc.dm
@@ -17,8 +17,8 @@
icon_state = "merc_rig"
suit_type = "crimson hardsuit"
armor_type = /datum/armor/hardsuit/merc
- slowdown = 1
- offline_slowdown = 3
+ encumbrance = ITEM_ENCUMBRANCE_LEGACY_RIG_HEAVY
+ offline_encumbrance = ITEM_ENCUMBRANCE_LEGACY_RIG_HEAVY * 2
offline_vision_restriction = 1
siemens_coefficient = 0.3
glove_type = /obj/item/clothing/gloves/gauntlets/hardsuit/eva
diff --git a/code/modules/hardsuits/suits/species/protean.dm b/code/modules/hardsuits/suits/species/protean.dm
index 4b3f412ec232..15e5eb356bfb 100644
--- a/code/modules/hardsuits/suits/species/protean.dm
+++ b/code/modules/hardsuits/suits/species/protean.dm
@@ -4,8 +4,8 @@
icon_state = "nanomachine_rig"
armor_type = /datum/armor/hardsuit/protean
siemens_coefficient = 0.5
- slowdown = 0
- offline_slowdown = 0
+ encumbrance = ITEM_ENCUMBRANCE_LEGACY_RIG_LIGHT
+ offline_encumbrance = ITEM_ENCUMBRANCE_LEGACY_RIG_LIGHT * 2
seal_delay = 1
var/mob/living/carbon/human/myprotean
initial_modules = list(
diff --git a/code/modules/hardsuits/suits/species/unathi.dm b/code/modules/hardsuits/suits/species/unathi.dm
index 90e804e7212d..6d0ca3859b96 100644
--- a/code/modules/hardsuits/suits/species/unathi.dm
+++ b/code/modules/hardsuits/suits/species/unathi.dm
@@ -5,8 +5,8 @@
icon_state = "breacher_hardsuit_cheap"
armor_type = /datum/armor/hardsuit/breacher
emp_protection = -20
- slowdown = 6
- offline_slowdown = 10
+ encumbrance = ITEM_ENCUMBRANCE_LEGACY_RIG_HEAVY * 2
+ offline_encumbrance = ITEM_ENCUMBRANCE_LEGACY_RIG_HEAVY * 4
vision_restriction = 1
offline_vision_restriction = 2
siemens_coefficient = 0.75
diff --git a/code/modules/hardsuits/suits/species/vox.dm b/code/modules/hardsuits/suits/species/vox.dm
index 900e92d94fec..ce02abf6e3e8 100644
--- a/code/modules/hardsuits/suits/species/vox.dm
+++ b/code/modules/hardsuits/suits/species/vox.dm
@@ -7,7 +7,6 @@
atom_flags = PHORONGUARD
clothing_flags = CLOTHING_THICK_MATERIAL
siemens_coefficient = 0.2
- offline_slowdown = 5
allowed = list(
/obj/item/gun,
/obj/item/flashlight,
diff --git a/code/modules/hardsuits/suits/station/cargo.dm b/code/modules/hardsuits/suits/station/cargo.dm
index df54f98bd0df..0ec49ab57534 100644
--- a/code/modules/hardsuits/suits/station/cargo.dm
+++ b/code/modules/hardsuits/suits/station/cargo.dm
@@ -4,8 +4,6 @@
desc = "A heavy, powerful hardsuit used by construction crews and mining corporations."
icon_state = "engineering_rig"
armor_type = /datum/armor/hardsuit/industrial
- slowdown = 1
- offline_slowdown = 10
offline_vision_restriction = 2
emp_protection = -20
siemens_coefficient= 0.75
diff --git a/code/modules/hardsuits/suits/station/engineering.dm b/code/modules/hardsuits/suits/station/engineering.dm
index 6b5424544aa2..7f9a19eb7c53 100644
--- a/code/modules/hardsuits/suits/station/engineering.dm
+++ b/code/modules/hardsuits/suits/station/engineering.dm
@@ -4,8 +4,8 @@
desc = "A light hardsuit for repairs and maintenance to the outside of habitats and vessels."
icon_state = "eva_rig"
armor_type = /datum/armor/hardsuit/eva
- slowdown = 0
- offline_slowdown = 1
+ encumbrance = ITEM_ENCUMBRANCE_LEGACY_RIG_LIGHT
+ offline_encumbrance = ITEM_ENCUMBRANCE_LEGACY_RIG_LIGHT * 2
offline_vision_restriction = 1
siemens_coefficient= 0.75
seal_delay = 24 //Should be slightly faster than other hardsuits, giving Engineering faster response time for emergencies.
@@ -57,8 +57,8 @@
desc = "An advanced voidsuit that protects against hazardous, low pressure environments. Shines with a high polish."
icon_state = "ce_rig"
armor_type = /datum/armor/hardsuit/ce
- slowdown = 0
- offline_slowdown = 0
+ encumbrance = ITEM_ENCUMBRANCE_LEGACY_RIG_LIGHT
+ offline_encumbrance = ITEM_ENCUMBRANCE_LEGACY_RIG_LIGHT * 2
offline_vision_restriction = 0
siemens_coefficient= 0.75
rigsuit_max_pressure = 20 * ONE_ATMOSPHERE // Max pressure the hardsuit protects against when sealed
@@ -97,7 +97,7 @@
siemens_coefficient = 0
/obj/item/clothing/shoes/magboots/hardsuit/ce
- slowdown_on = 0
+ encumbrance_on = ITEM_ENCUMBRANCE_SHOES_MAGBOOTS_PULSE_ADVANCED
/obj/item/hardsuit/ce/equipped
initial_modules = list(
diff --git a/code/modules/hardsuits/suits/station/medical.dm b/code/modules/hardsuits/suits/station/medical.dm
index c5e8403af5c7..95e83f2eeb4d 100644
--- a/code/modules/hardsuits/suits/station/medical.dm
+++ b/code/modules/hardsuits/suits/station/medical.dm
@@ -4,8 +4,8 @@
desc = "A durable suit designed for medical rescue in high risk areas."
icon_state = "medical_rig"
armor_type = /datum/armor/hardsuit/medical
- slowdown = 1
- offline_vision_restriction = 1
+ encumbrance = ITEM_ENCUMBRANCE_LEGACY_RIG_LIGHT
+ offline_encumbrance = ITEM_ENCUMBRANCE_LEGACY_RIG_LIGHT * 2
siemens_coefficient= 0.75
helm_type = /obj/item/clothing/head/helmet/space/hardsuit/medical
diff --git a/code/modules/hardsuits/suits/station/misc.dm b/code/modules/hardsuits/suits/station/misc.dm
index 83dca958b893..904a6bb22508 100644
--- a/code/modules/hardsuits/suits/station/misc.dm
+++ b/code/modules/hardsuits/suits/station/misc.dm
@@ -5,8 +5,8 @@
icon_state = "internalaffairs_rig"
armor_type = /datum/armor/none
siemens_coefficient = 0.9
- slowdown = 0
- offline_slowdown = 0
+ encumbrance = ITEM_ENCUMBRANCE_LEGACY_RIG_LIGHT
+ offline_encumbrance = ITEM_ENCUMBRANCE_LEGACY_RIG_LIGHT * 2
offline_vision_restriction = 0
allowed = list(
diff --git a/code/modules/hardsuits/suits/station/science.dm b/code/modules/hardsuits/suits/station/science.dm
index 55446554860c..f4320fc9592d 100644
--- a/code/modules/hardsuits/suits/station/science.dm
+++ b/code/modules/hardsuits/suits/station/science.dm
@@ -4,8 +4,8 @@
desc = "An Anomalous Material Interaction hardsuit that protects against the strangest energies the universe can throw at it."
icon_state = "science_rig"
armor_type = /datum/armor/hardsuit/ami
- slowdown = 1
- offline_vision_restriction = 1
+ encumbrance = ITEM_ENCUMBRANCE_LEGACY_RIG_LIGHT
+ offline_encumbrance = ITEM_ENCUMBRANCE_LEGACY_RIG_LIGHT * 2
siemens_coefficient= 0.75
helm_type = /obj/item/clothing/head/helmet/space/hardsuit/hazmat
diff --git a/code/modules/hardsuits/suits/station/security.dm b/code/modules/hardsuits/suits/station/security.dm
index 1f1b17fe1133..019155c5fd2e 100644
--- a/code/modules/hardsuits/suits/station/security.dm
+++ b/code/modules/hardsuits/suits/station/security.dm
@@ -4,8 +4,6 @@
desc = "A Security hardsuit designed for prolonged EVA in dangerous environments."
icon_state = "hazard_rig"
armor_type = /datum/armor/hardsuit/hazard
- slowdown = 1
- offline_slowdown = 3
offline_vision_restriction = 1
siemens_coefficient= 0.7
diff --git a/code/modules/hydroponics/trays/tray_reagents.dm b/code/modules/hydroponics/trays/tray_reagents.dm
index 851842f309fd..751d40acbfd5 100644
--- a/code/modules/hydroponics/trays/tray_reagents.dm
+++ b/code/modules/hydroponics/trays/tray_reagents.dm
@@ -1,7 +1,7 @@
/obj/item/plantspray
icon = 'icons/obj/hydroponics_machines.dmi'
item_state = "spraycan"
- item_flags = ITEM_NOBLUDGEON
+ item_flags = ITEM_NOBLUDGEON | ITEM_ENCUMBERS_WHILE_HELD
slot_flags = SLOT_BELT
throw_force = 4
w_class = ITEMSIZE_SMALL
diff --git a/code/modules/integrated_electronics/core/assemblies.dm b/code/modules/integrated_electronics/core/assemblies.dm
index 2f4f13d4d817..143735a609e6 100644
--- a/code/modules/integrated_electronics/core/assemblies.dm
+++ b/code/modules/integrated_electronics/core/assemblies.dm
@@ -7,7 +7,7 @@
w_class = ITEMSIZE_SMALL
icon = 'icons/obj/integrated_electronics/electronic_setups.dmi'
icon_state = "setup_small"
- item_flags = ITEM_NOBLUDGEON
+ item_flags = ITEM_NOBLUDGEON | ITEM_ENCUMBERS_WHILE_HELD
show_messages = TRUE
datum_flags = DF_USE_TAG
var/list/assembly_components = list()
diff --git a/code/modules/integrated_electronics/core/detailer.dm b/code/modules/integrated_electronics/core/detailer.dm
index e61b6cf9620d..85046f6c44d1 100644
--- a/code/modules/integrated_electronics/core/detailer.dm
+++ b/code/modules/integrated_electronics/core/detailer.dm
@@ -3,7 +3,7 @@
desc = "A combination autopainter and flash anodizer designed to give electronic assemblies a colorful, wear-resistant finish."
icon = 'icons/obj/integrated_electronics/electronic_tools.dmi'
icon_state = "detailer"
- item_flags = ITEM_NOBLUDGEON
+ item_flags = ITEM_NOBLUDGEON | ITEM_ENCUMBERS_WHILE_HELD
w_class = ITEMSIZE_SMALL
var/detail_color = COLOR_ASSEMBLY_WHITE
var/list/color_list = list(
diff --git a/code/modules/materials/material_sheets.dm b/code/modules/materials/material_sheets.dm
index 7ce1eaede2bc..11508f4bdbab 100644
--- a/code/modules/materials/material_sheets.dm
+++ b/code/modules/materials/material_sheets.dm
@@ -287,7 +287,6 @@
apply_colour = TRUE
/obj/item/stack/material/supermatter/proc/update_mass() // Due to how dangerous they can be, the item will get heavier and larger the more are in the stack.
- slowdown = amount / 10
w_class = min(5, round(amount / 10) + 1)
throw_range = round(amount / 7) + 1
diff --git a/code/modules/mining/vertibore.dm b/code/modules/mining/vertibore.dm
index bfc0b32e6fc9..ab7e20091ed5 100644
--- a/code/modules/mining/vertibore.dm
+++ b/code/modules/mining/vertibore.dm
@@ -3,9 +3,7 @@
name = "portable shaft excavation device"
desc = "A heavily modified shaft bore utilizing phorogenic blasts to tunnel vertically through rock. Much faster than a large industrial drill unit, but is very resource- and power-intensive."
description_fluff = "A phoron bore used for rapidly digging through rock that has been modified to allow it to fire straight down at a much higher power. However, this has resulted in a loss of power and resource efficiency, compactness, and modularity as the proprietary capacitor and manipulator cannot be swapped."
- w_class = ITEMSIZE_NO_CONTAINER //haha harold can't powergame itemsize with BoHs if it doesn't even fit in a BoH
- //he's just going to locker it isn't he
- slowdown = 1 //chonker bore is heavy boy
+ w_class = ITEMSIZE_NO_CONTAINER
icon = 'icons/obj/mining.dmi'
icon_state = "vertibore"
item_state = "vertibore"
diff --git a/code/modules/mob/grab.dm b/code/modules/mob/grab.dm
index 341b22107842..52c8362f2245 100644
--- a/code/modules/mob/grab.dm
+++ b/code/modules/mob/grab.dm
@@ -78,7 +78,7 @@
name = "grab"
icon = 'icons/mob/screen1.dmi'
icon_state = "reinforce"
- item_flags = ITEM_ABSTRACT | ITEM_DROPDEL
+ item_flags = ITEM_ABSTRACT | ITEM_DROPDEL | ITEM_ENCUMBERS_WHILE_HELD
atom_flags = ATOM_ABSTRACT
drop_sound = null
pickup_sound = null
diff --git a/code/modules/mob/inventory.dm b/code/modules/mob/inventory.dm
index 866f9c3df63a..42fce6a6208e 100644
--- a/code/modules/mob/inventory.dm
+++ b/code/modules/mob/inventory.dm
@@ -57,3 +57,11 @@
// todo: actual flag like BUCKLING_IS_CONSIDERED_RESTRICTING or something
if(buckled?.buckle_flags & (BUCKLING_NO_DEFAULT_RESIST | BUCKLING_NO_DEFAULT_UNBUCKLE))
unbuckle(BUCKLE_OP_FORCE)
+
+//* Carry Weight
+
+/mob/proc/update_carry_slowdown()
+ return
+
+/mob/proc/update_item_slowdown()
+ return
diff --git a/code/modules/mob/inventory/items.dm b/code/modules/mob/inventory/items.dm
index 2abb30e06e34..25c23a27d510 100644
--- a/code/modules/mob/inventory/items.dm
+++ b/code/modules/mob/inventory/items.dm
@@ -47,6 +47,16 @@
playsound(src, equip_sound, 30, ignore_walls = FALSE)
user.update_inv_hands()
+ // register carry
+ if(isliving(user))
+ var/mob/living/L = user
+ if((slot == SLOT_ID_HANDS)? (item_flags & ITEM_ENCUMBERS_WHILE_HELD) : !(item_flags & ITEM_ENCUMBERS_ONLY_HELD))
+ if(flat_encumbrance)
+ L.recalculate_carry()
+ else
+ encumbrance_registered = get_encumbrance()
+ L.adjust_current_carry_encumbrance(encumbrance_registered)
+
/**
* called when an item is unequipped from inventory or moved around in inventory
*
@@ -69,6 +79,15 @@
if(!(flags & INV_OP_DIRECTLY_DROPPING) && (slot != SLOT_ID_HANDS) && unequip_sound)
playsound(src, unequip_sound, 30, ignore_walls = FALSE)
+ // clear carry
+ if(isliving(user))
+ var/mob/living/L = user
+ if(flat_encumbrance)
+ L.recalculate_carry()
+ else if(!isnull(encumbrance_registered))
+ L.adjust_current_carry_encumbrance(-encumbrance_registered)
+ encumbrance_registered = null
+
/**
* called when a mob drops an item
*
@@ -101,6 +120,12 @@
if(zoom)
zoom() //binoculars, scope, etc
+ // clear carry
+ if(isliving(user))
+ var/mob/living/L = user
+ L.adjust_current_carry_weight(-weight_registered)
+ weight_registered = null
+
// close context menus
context_close()
@@ -123,11 +148,11 @@
if(isturf(oldLoc) && !(flags & (INV_OP_SILENT | INV_OP_DIRECTLY_EQUIPPING)))
playsound(src, pickup_sound, 20, ignore_walls = FALSE)
-/**
- * get the slowdown we incur when we're worn
- */
-/obj/item/proc/get_equipment_speed_mod()
- return slowdown
+ // register carry
+ weight_registered = get_weight()
+ if(isliving(user))
+ var/mob/living/L = user
+ L.adjust_current_carry_weight(weight_registered)
/**
* update our worn icon if we can
@@ -320,11 +345,20 @@
/**
* checks if we're in inventory. if so, returns mob we're in
+ *
* **hands count**
*/
/obj/item/proc/is_in_inventory(include_hands)
return (worn_slot && ((worn_slot != SLOT_ID_HANDS) || include_hands)) && worn_mob()
+/**
+ * checks if we're held in hand
+ *
+ * if so, returns mob we're in
+ */
+/obj/item/proc/is_held()
+ return (worn_slot == SLOT_ID_HANDS)? worn_mob() : null
+
/**
* checks if we're worn. if so, return mob we're in
*
diff --git a/code/modules/mob/living/carbon/cpr.dm b/code/modules/mob/living/carbon/cpr.dm
index 644f68539fe1..3aedb9610009 100644
--- a/code/modules/mob/living/carbon/cpr.dm
+++ b/code/modules/mob/living/carbon/cpr.dm
@@ -1,3 +1,6 @@
+//* This file is explicitly licensed under the MIT license. *//
+//* Copyright (c) 2023 Citadel Station developers. *//
+
// someday, we'll combine /carbon and /human to /complex
// let me believe.......
diff --git a/code/modules/mob/living/carbon/human/inventory.dm b/code/modules/mob/living/carbon/human/inventory.dm
index 2b73b38b1804..32d7e8a521be 100644
--- a/code/modules/mob/living/carbon/human/inventory.dm
+++ b/code/modules/mob/living/carbon/human/inventory.dm
@@ -1,3 +1,6 @@
+//* This file is explicitly licensed under the MIT license. *//
+//* Copyright (c) 2023 Citadel Station developers. *//
+
/mob/living/carbon/human/_slot_by_item(obj/item/I)
if(wear_suit == I)
return SLOT_ID_SUIT
@@ -267,79 +270,3 @@
if(!slot_meta)
return FALSE
return !(slot_meta.inventory_slot_flags & INV_SLOT_IS_INVENTORY) || !species || (id in species.hud.gear)
-
-//! old stuff below
-
-/mob/living/carbon/human/verb/quick_equip()
- set name = "quick-equip"
- set hidden = 1
-
- attempt_smart_equip()
-
-//! old behaviors that i can't be assed to rewrite for now
-
-/mob/living/carbon/human/proc/smart_equipbag() // take most recent item out of bag or place held item in bag
- if(incapacitated())
- return
- var/obj/item/thing = get_active_held_item()
- var/obj/item/equipped_back = item_by_slot(SLOT_ID_BACK)
- if(!equipped_back) // We also let you equip a backpack like this
- if(!thing)
- to_chat(src, "You have no backpack to take something out of!")
- return
- if(equip_to_slot_if_possible(thing, SLOT_ID_BACK))
- update_inv_hands()
- return
- if(!istype(equipped_back, /obj/item/storage)) // not a storage item
- if(!thing)
- equipped_back.attack_hand(src)
- else
- to_chat(src, "You can't fit anything in!")
- return
- if(thing) // put thing in backpack
- var/obj/item/storage/S = equipped_back
- if(!S.can_be_inserted(thing))
- to_chat(src, "You can't fit anything in!")
- return
- S.handle_item_insertion(thing, src)
- return
- if(!equipped_back.contents.len) // nothing to take out
- to_chat(src, "There's nothing in your backpack to take out!")
- return
- var/obj/item/stored = equipped_back.contents[equipped_back.contents.len]
- if(!stored || stored.on_found(src))
- return
- stored.attack_hand(src) // take out thing from backpack
-
-/mob/living/carbon/human/proc/smart_equipbelt() // put held thing in belt or take most recent item out of belt
- if(incapacitated())
- return
- var/obj/item/thing = get_active_held_item()
- var/obj/item/equipped_belt = item_by_slot(SLOT_ID_BELT)
- if(!equipped_belt) // We also let you equip a belt like this
- if(!thing)
- to_chat(src, "You have no belt to take something out of!")
- return
- if(equip_to_slot_if_possible(thing, SLOT_ID_BELT))
- update_inv_hands()
- return
- if(!istype(equipped_belt, /obj/item/storage)) // not a storage item
- if(!thing)
- equipped_belt.attack_hand(src)
- else
- to_chat(src, "You can't fit anything in!")
- return
- if(thing) // put thing in belt
- var/obj/item/storage/S = equipped_belt
- if(!S.can_be_inserted(thing))
- to_chat(src, "You can't fit anything in!")
- return
- S.handle_item_insertion(thing, src)
- return
- if(!equipped_belt.contents.len) // nothing to take out
- to_chat(src, "There's nothing in your belt to take out!")
- return
- var/obj/item/stored = equipped_belt.contents[equipped_belt.contents.len]
- if(!stored || stored.on_found(src))
- return
- stored.attack_hand(src) // take out thing from belt
diff --git a/code/modules/mob/living/carbon/human/inventory_legacy.dm b/code/modules/mob/living/carbon/human/inventory_legacy.dm
new file mode 100644
index 000000000000..60294ffee85f
--- /dev/null
+++ b/code/modules/mob/living/carbon/human/inventory_legacy.dm
@@ -0,0 +1,75 @@
+//! old stuff below
+
+/mob/living/carbon/human/verb/quick_equip()
+ set name = "quick-equip"
+ set hidden = 1
+
+ attempt_smart_equip()
+
+//! old behaviors that i can't be assed to rewrite for now
+
+/mob/living/carbon/human/proc/smart_equipbag() // take most recent item out of bag or place held item in bag
+ if(incapacitated())
+ return
+ var/obj/item/thing = get_active_held_item()
+ var/obj/item/equipped_back = item_by_slot(SLOT_ID_BACK)
+ if(!equipped_back) // We also let you equip a backpack like this
+ if(!thing)
+ to_chat(src, "You have no backpack to take something out of!")
+ return
+ if(equip_to_slot_if_possible(thing, SLOT_ID_BACK))
+ update_inv_hands()
+ return
+ if(!istype(equipped_back, /obj/item/storage)) // not a storage item
+ if(!thing)
+ equipped_back.attack_hand(src)
+ else
+ to_chat(src, "You can't fit anything in!")
+ return
+ if(thing) // put thing in backpack
+ var/obj/item/storage/S = equipped_back
+ if(!S.can_be_inserted(thing))
+ to_chat(src, "You can't fit anything in!")
+ return
+ S.handle_item_insertion(thing, src)
+ return
+ if(!equipped_back.contents.len) // nothing to take out
+ to_chat(src, "There's nothing in your backpack to take out!")
+ return
+ var/obj/item/stored = equipped_back.contents[equipped_back.contents.len]
+ if(!stored || stored.on_found(src))
+ return
+ stored.attack_hand(src) // take out thing from backpack
+
+/mob/living/carbon/human/proc/smart_equipbelt() // put held thing in belt or take most recent item out of belt
+ if(incapacitated())
+ return
+ var/obj/item/thing = get_active_held_item()
+ var/obj/item/equipped_belt = item_by_slot(SLOT_ID_BELT)
+ if(!equipped_belt) // We also let you equip a belt like this
+ if(!thing)
+ to_chat(src, "You have no belt to take something out of!")
+ return
+ if(equip_to_slot_if_possible(thing, SLOT_ID_BELT))
+ update_inv_hands()
+ return
+ if(!istype(equipped_belt, /obj/item/storage)) // not a storage item
+ if(!thing)
+ equipped_belt.attack_hand(src)
+ else
+ to_chat(src, "You can't fit anything in!")
+ return
+ if(thing) // put thing in belt
+ var/obj/item/storage/S = equipped_belt
+ if(!S.can_be_inserted(thing))
+ to_chat(src, "You can't fit anything in!")
+ return
+ S.handle_item_insertion(thing, src)
+ return
+ if(!equipped_belt.contents.len) // nothing to take out
+ to_chat(src, "There's nothing in your belt to take out!")
+ return
+ var/obj/item/stored = equipped_belt.contents[equipped_belt.contents.len]
+ if(!stored || stored.on_found(src))
+ return
+ stored.attack_hand(src) // take out thing from belt
diff --git a/code/modules/mob/living/carbon/human/movement.dm b/code/modules/mob/living/carbon/human/movement.dm
index 55ba626e7235..33450774b5a8 100644
--- a/code/modules/mob/living/carbon/human/movement.dm
+++ b/code/modules/mob/living/carbon/human/movement.dm
@@ -84,38 +84,15 @@
var/turf/T = get_turf(src)
tally += calculate_turf_slowdown(T, direct)
- // Item related slowdown.
- var/item_tally = calculate_item_encumbrance()
- if(item_tally > 0) // is it greater than 0? run the wacky shit
- item_tally *= species.item_slowdown_mod // your item slowdown kicks in, but
- if(!(CE_SPEEDBOOST in chem_effects)) // hyperzine users ignore item slow
- tally += item_tally // no hyperzine? slowed down by things
- else
- tally += item_tally // if it's less than 0 that means it speeds you up, theoretically, so, hit it
+ if(CE_SPEEDBOOST in chem_effects)
+ tally -= 0.5
if(CE_SLOWDOWN in chem_effects)
if (tally >= 0 )
tally = (tally + tally/4) //Add a quarter of penalties on top.
tally += chem_effects[CE_SLOWDOWN]
- return max(HUMAN_LOWEST_SLOWDOWN, tally + . + config_legacy.human_delay) // Minimum return should be the same as force_max_speed
-
-// This calculates the amount of slowdown to receive from items worn. This does NOT include species modifiers.
-// It is in a seperate place to avoid an infinite loop situation with dragging mobs dragging each other.
-// Also its nice to have these things seperated.
-/mob/living/carbon/human/proc/calculate_item_encumbrance()
- if(!buckled && shoes) // Shoes can make you go faster.
- . += shoes.slowdown
-
- // Loop through some slots, and add up their slowdowns.
- // Includes slots which can provide armor, the back slot, and suit storage.
- for(var/obj/item/I in list(wear_suit, w_uniform, back, gloves, head, s_store))
- . += I.slowdown
-
- // Hands are also included, to make the 'take off your armor instantly and carry it with you to go faster' trick no longer viable.
- // This is done seperately to disallow negative numbers (so you can't hold shoes in your hands to go faster).
- for(var/obj/item/I in list(r_hand, l_hand))
- . += max(I.slowdown, 0)
+ . = max(HUMAN_LOWEST_SLOWDOWN, tally + . + config_legacy.human_delay) // Minimum return should be the same as force_max_speed
// Similar to above, but for turf slowdown.
/mob/living/carbon/human/proc/calculate_turf_slowdown(turf/T, direct)
diff --git a/code/modules/mob/living/carbon/human/traits/negative.dm b/code/modules/mob/living/carbon/human/traits/negative.dm
index 03536c3aa4d6..393a3718085d 100644
--- a/code/modules/mob/living/carbon/human/traits/negative.dm
+++ b/code/modules/mob/living/carbon/human/traits/negative.dm
@@ -10,18 +10,6 @@
cost = -3
var_changes = list("slowdown" = 1.0)
-/datum/trait/negative/weakling
- name = "Weakling"
- desc = "Causes heavy equipment to slow you down more when carried."
- cost = -1
- var_changes = list("item_slowdown_mod" = 1.5)
-
-/datum/trait/negative/weakling_plus
- name = "Major Weakling"
- desc = "Allows you to carry heavy equipment with much more slowdown."
- cost = -2
- var_changes = list("item_slowdown_mod" = 2.0)
-
/datum/trait/negative/endurance_low
name = "Low Endurance"
desc = "Reduces your maximum total hitpoints to 75."
diff --git a/code/modules/mob/living/carbon/human/traits/positive.dm b/code/modules/mob/living/carbon/human/traits/positive.dm
index be9956f3b67e..5a1e05670cda 100644
--- a/code/modules/mob/living/carbon/human/traits/positive.dm
+++ b/code/modules/mob/living/carbon/human/traits/positive.dm
@@ -3,19 +3,6 @@
desc = "Allows you to move faster on average than baseline."
cost = 2
var_changes = list("slowdown" = -0.2)
- excludes = list(/datum/trait/positive/hardy, /datum/trait/positive/hardy_plus)
-
-/datum/trait/positive/hardy
- name = "Hardy"
- desc = "Allows you to carry heavy equipment with less slowdown."
- cost = 1
- var_changes = list("item_slowdown_mod" = 0.5)
-
-/datum/trait/positive/hardy_plus
- name = "Major Hardy"
- desc = "Allows you to carry heavy equipment with almost no slowdown."
- cost = 2
- var_changes = list("item_slowdown_mod" = 0.25)
/datum/trait/positive/endurance_plus
name = "Better Endurance"
diff --git a/code/modules/mob/living/carbon/inventory.dm b/code/modules/mob/living/carbon/inventory.dm
index 063704e5b4f8..1e404c1f17d0 100644
--- a/code/modules/mob/living/carbon/inventory.dm
+++ b/code/modules/mob/living/carbon/inventory.dm
@@ -1,3 +1,6 @@
+//* This file is explicitly licensed under the MIT license. *//
+//* Copyright (c) 2023 Citadel Station developers. *//
+
/mob/living/carbon/_slot_by_item(obj/item/I)
if(handcuffed == I)
return SLOT_ID_HANDCUFFED
@@ -44,3 +47,26 @@
SLOT_ID_HANDCUFFED,
SLOT_ID_LEGCUFFED
)
+
+//* carry weight
+
+/mob/living/carbon/carry_weight_to_penalty(amount)
+ // https://www.desmos.com/calculator/5o2cx7grbo
+ var/carry_strength = physiology.carry_strength + physiology.carry_weight_add
+ if(amount < carry_strength)
+ return 1
+ var/carry_factor = physiology.carry_factor * physiology.carry_weight_factor
+ return (1 / (1 + NUM_E ** (carry_factor * (CARRY_WEIGHT_SCALING / carry_strength) * (amount - carry_strength + CARRY_WEIGHT_BIAS * carry_strength) - 5))) * CARRY_WEIGHT_ASYMPTOTE + CARRY_WEIGHT_ASYMPTOTE
+
+/mob/living/carbon/carry_encumbrance_to_penalty(amount)
+ // https://www.desmos.com/calculator/5o2cx7grbo
+ var/carry_strength = physiology.carry_strength
+ if(amount < carry_strength)
+ return 1
+ var/carry_factor = physiology.carry_factor
+ return (1 / (1 + NUM_E ** (carry_factor * (CARRY_WEIGHT_SCALING / carry_strength) * (amount - carry_strength + CARRY_WEIGHT_BIAS * carry_strength) - 5))) * (1 - CARRY_WEIGHT_ASYMPTOTE) + CARRY_WEIGHT_ASYMPTOTE
+
+/mob/living/carbon/get_item_slowdown()
+ . = ..()
+ if(!isnull(species))
+ . *= species.item_slowdown_mod
diff --git a/code/modules/mob/living/carbon/perspective.dm b/code/modules/mob/living/carbon/perspective.dm
index d010e0257585..df90da7aebec 100644
--- a/code/modules/mob/living/carbon/perspective.dm
+++ b/code/modules/mob/living/carbon/perspective.dm
@@ -1,3 +1,6 @@
+//* This file is explicitly licensed under the MIT license. *//
+//* Copyright (c) 2023 Citadel Station developers. *//
+
//? Darksight
/mob/living/carbon/innate_vision()
diff --git a/code/modules/mob/living/inventory.dm b/code/modules/mob/living/inventory.dm
index 7369dc3608c3..9402e61f59ff 100644
--- a/code/modules/mob/living/inventory.dm
+++ b/code/modules/mob/living/inventory.dm
@@ -255,3 +255,94 @@
/mob/living/has_free_hand()
return !l_hand || !r_hand
+
+//* carry weight
+
+// don't call this you shouldn't need to
+/mob/living/update_carry_slowdown()
+ recalculate_carry()
+
+/mob/living/proc/recalculate_carry(update = TRUE)
+ var/tally_weight = 0
+ var/tally_encumbrance = 0
+ var/flat_encumbrance = 0
+ for(var/obj/item/I as anything in get_equipped_items())
+ tally_weight += (I.weight_registered = I.get_weight())
+ if(I.is_held())
+ if(!(I.item_flags & ITEM_ENCUMBERS_WHILE_HELD))
+ I.encumbrance_registered = null
+ continue
+ else
+ if(I.item_flags & ITEM_ENCUMBERS_ONLY_HELD)
+ I.encumbrance_registered = null
+ continue
+ var/encumbrance = I.get_encumbrance()
+ tally_encumbrance += encumbrance
+ I.encumbrance_registered = encumbrance
+ flat_encumbrance = max(flat_encumbrance, I.get_flat_encumbrance())
+ cached_carry_weight = tally_weight
+ cached_carry_encumbrance = tally_encumbrance
+ cached_carry_flat_encumbrance = flat_encumbrance
+ if(update)
+ update_carry()
+
+/mob/living/proc/adjust_current_carry_weight(amount)
+ if(!amount)
+ return
+ cached_carry_weight += amount
+ update_carry()
+
+/mob/living/proc/adjust_current_carry_encumbrance(amount)
+ if(!amount)
+ return
+ cached_carry_encumbrance += amount
+ update_carry()
+
+/**
+ * @return penalty as speed multiplier from 0 to 1
+ */
+/mob/living/proc/carry_weight_to_penalty(amount)
+ return 1
+
+/**
+ * @return penalty as speed multiplier from 0 to 1
+ */
+/mob/living/proc/carry_encumbrance_to_penalty(amount)
+ return 1
+
+/mob/living/proc/update_carry()
+ var/weight_penalty = carry_weight_to_penalty(cached_carry_weight)
+ var/encumbrance_penalty = carry_encumbrance_to_penalty(cached_carry_encumbrance)
+ var/flat_encumbrance_penalty = carry_encumbrance_to_penalty(cached_carry_flat_encumbrance)
+ var/penalty = min(weight_penalty, encumbrance_penalty, flat_encumbrance_penalty)
+ switch(round(min(weight_penalty, encumbrance_penalty) * 100))
+ if(85 to 99)
+ throw_alert("encumbered", /atom/movable/screen/alert/encumbered/minor)
+ if(65 to 84)
+ throw_alert("encumbered", /atom/movable/screen/alert/encumbered/moderate)
+ if(36 to 64)
+ throw_alert("encumbered", /atom/movable/screen/alert/encumbered/severe)
+ if(0 to 35)
+ throw_alert("encumbered", /atom/movable/screen/alert/encumbered/extreme)
+ else
+ clear_alert("encumbered")
+ /// do not slow down below 10% of base
+ penalty = max(penalty, 0.1)
+ if(penalty)
+ add_or_update_variable_movespeed_modifier(/datum/movespeed_modifier/mob_inventory_carry, params = list(MOVESPEED_PARAM_MULTIPLY_SPEED = penalty))
+ else
+ remove_movespeed_modifier(/datum/movespeed_modifier/mob_inventory_carry)
+
+//* hard movespeed slowdown
+
+/mob/living/update_item_slowdown()
+ var/tally = get_item_slowdown()
+ if(tally)
+ add_or_update_variable_movespeed_modifier(/datum/movespeed_modifier/mob_item_slowdown, params = list(MOVESPEED_PARAM_DELAY_MOD = tally))
+ else
+ remove_movespeed_modifier(/datum/movespeed_modifier/mob_item_slowdown)
+
+/mob/living/proc/get_item_slowdown()
+ . = 0
+ for(var/obj/item/I as anything in get_equipped_items())
+ . += I.slowdown
diff --git a/code/modules/mob/living/living_defines.dm b/code/modules/mob/living/living_defines.dm
index e4a55f48a387..9281567fb6f7 100644
--- a/code/modules/mob/living/living_defines.dm
+++ b/code/modules/mob/living/living_defines.dm
@@ -1,9 +1,8 @@
/**
- * # /mob/living
+ * living mobs
*
- * mob/living is the base type of mobs that have health
- * there's probably a better explanation we can type someday but for that, uh
- * yeah.
+ * living mobs are the subtype of mobs that are semantically what you'd think of as a true mob
+ * health, inventory carry weight simulations, etc.
*/
/mob/living
see_invisible = SEE_INVISIBLE_LIVING
@@ -127,6 +126,15 @@
/// Set to TRUE to enable the use of hands and the hands hud
var/has_hands = FALSE
+ //* Carry Weight
+ // todo: put all this on /datum/inventory after hand refactor
+ /// cached carry weight of all items
+ var/cached_carry_weight = 0
+ /// cached encumbrance of all items
+ var/cached_carry_encumbrance = 0
+ /// highest flat encumbrance of all items
+ var/cached_carry_flat_encumbrance = 0
+
//? movement
/// are we currently pushing (or trying to push) (or otherwise inside Bump() handling that deals with this crap) another atom?
var/pushing_bumped_atom = FALSE
diff --git a/code/modules/mob/living/silicon/robot/dogborg/dog_modules_vr.dm b/code/modules/mob/living/silicon/robot/dogborg/dog_modules_vr.dm
index 592dad83d961..8d56d771c268 100644
--- a/code/modules/mob/living/silicon/robot/dogborg/dog_modules_vr.dm
+++ b/code/modules/mob/living/silicon/robot/dogborg/dog_modules_vr.dm
@@ -57,7 +57,7 @@
icon_state = "nose"
desc = "The BOOP module, a simple reagent and atmosphere sniffer."
damage_force = 0
- item_flags = ITEM_NOBLUDGEON
+ item_flags = ITEM_NOBLUDGEON | ITEM_ENCUMBERS_WHILE_HELD
throw_force = 0
attack_verb = list("nuzzled", "nosed", "booped")
w_class = ITEMSIZE_TINY
@@ -181,7 +181,7 @@
icon = 'icons/mob/dogborg_vr.dmi'
icon_state = "synthtongue"
hitsound = 'sound/effects/attackblob.ogg'
- item_flags = ITEM_NOBLUDGEON
+ item_flags = ITEM_NOBLUDGEON | ITEM_ENCUMBERS_WHILE_HELD
var/emagged = 0
var/datum/matter_synth/water = null
@@ -300,7 +300,7 @@
desc = "Toggles floor scrubbing."
icon = 'icons/mob/dogborg_vr.dmi'
icon_state = "scrub0"
- item_flags = ITEM_NOBLUDGEON
+ item_flags = ITEM_NOBLUDGEON | ITEM_ENCUMBERS_WHILE_HELD
var/enabled = FALSE
/obj/item/pupscrubber/attack_self(mob/user)
@@ -379,7 +379,7 @@
icon_state = "pounce"
desc = "Leap at your target to momentarily stun them."
damage_force = 0
- item_flags = ITEM_NOBLUDGEON
+ item_flags = ITEM_NOBLUDGEON | ITEM_ENCUMBERS_WHILE_HELD
throw_force = 0
/obj/item/dogborg/pounce/attack_self(mob/user)
diff --git a/code/modules/mob/living/silicon/robot/dogborg/dog_sleeper_vr.dm b/code/modules/mob/living/silicon/robot/dogborg/dog_sleeper_vr.dm
index 60c78dbc91cd..1a7e1589504b 100644
--- a/code/modules/mob/living/silicon/robot/dogborg/dog_sleeper_vr.dm
+++ b/code/modules/mob/living/silicon/robot/dogborg/dog_sleeper_vr.dm
@@ -5,7 +5,7 @@
icon = 'icons/mob/dogborg_vr.dmi'
icon_state = "sleeper"
w_class = ITEMSIZE_TINY
- item_flags = ITEM_NOBLUDGEON
+ item_flags = ITEM_NOBLUDGEON | ITEM_ENCUMBERS_WHILE_HELD
var/mob/living/carbon/patient = null
var/mob/living/silicon/robot/hound = null
var/inject_amount = 10
diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm
index 70777dce0d63..f31ebce84b37 100644
--- a/code/modules/mob/mob.dm
+++ b/code/modules/mob/mob.dm
@@ -59,6 +59,9 @@
status_effects = null
// mob lists
mob_list_unregister(stat)
+ // physiology
+ QDEL_NULL(physiology)
+ physiology_modifiers = null
// movespeed
movespeed_modification = null
// actionspeed
diff --git a/code/modules/mob/mob_defines.dm b/code/modules/mob/mob_defines.dm
index 1bdeba507663..edbd657f2a8e 100644
--- a/code/modules/mob/mob_defines.dm
+++ b/code/modules/mob/mob_defines.dm
@@ -1,3 +1,6 @@
+/**
+ * base BYOND type for an actor, if the game world is a scene.
+ */
/mob
datum_flags = DF_USE_TAG
density = 1
@@ -54,6 +57,9 @@
var/list/movespeed_mod_immunities //Lazy list, see mob_movespeed.dm
/// The calculated mob speed slowdown based on the modifiers list
var/cached_multiplicative_slowdown
+ /// cached legacy movespeed multiplier -_-
+ // todo: remove
+ var/cached_movespeed_multiply
/// Next world.time we will be able to move.
var/move_delay = 0
/// Last world.time we finished a normal, non relay/intercepted move
@@ -63,7 +69,7 @@
//? Physiology
/// overall physiology - see physiology.dm
- var/datum/physiology/physiology
+ var/datum/global_physiology/physiology
/// physiology modifiers - see physiology.dm; set to list of paths at init to initialize into instances.
var/list/datum/physiology_modifier/physiology_modifiers
@@ -72,8 +78,6 @@
var/list/actionspeed_modification //Lazy list, see mob_movespeed.dm
/// List of action speed modifiers ignored by this mob. List -> List (id) -> List (sources)
var/list/actionspeed_mod_immunities //Lazy list, see mob_movespeed.dm
- /// The calculated mob action speed slowdown based on the modifiers list
- var/cached_multiplicative_actions_slowdown
//? Pixel Offsets
/// are we shifted by the user?
diff --git a/code/modules/mob/movement.dm b/code/modules/mob/movement.dm
index a1d8a8784a62..9efbfb593477 100644
--- a/code/modules/mob/movement.dm
+++ b/code/modules/mob/movement.dm
@@ -257,6 +257,9 @@
// get additional delay from this move
var/add_delay = mob.movement_delay()
+ //! TODO: REMOVE ; COMPATABILITY LAYER TO USE NEW MOVESPEED.
+ add_delay = min(10 / ((10 / add_delay) * (1 * mob.cached_movespeed_multiply)), 10 / MOVESPEED_ABSOLUTE_MINIMUM_TILES_PER_SECOND)
+ //! END
// for grabs (legacy code moment)
var/add_delay_grab = 0
diff --git a/code/modules/mob/physiology.dm b/code/modules/mob/physiology.dm
index 776af71edb3b..8c548254a78c 100644
--- a/code/modules/mob/physiology.dm
+++ b/code/modules/mob/physiology.dm
@@ -3,15 +3,103 @@
*
* todo: on biologies update, we might need to lazy-cache this, and have different physiologies for each biology.
*/
-/datum/physiology
- // todo: /datum/physiology should hold global body physiology, limbs should hold modifiers/whatever themselves.
+/datum/global_physiology
+ // back-reference to mob, for vv purposes.
+ var/mob/ownership
+
+ // todo: /datum/global_physiology should hold global body physiology, limbs should hold modifiers/whatever themselves.
// this way biologies can be supported as efficiently as possible.
-/datum/physiology/proc/apply(datum/physiology_modifier/modifier)
- // todo: modifier/apply_global, modifier/apply_bodypart
+ /// carry baseline modify
+ var/carry_strength = CARRY_STRENGTH_BASELINE
+ /// carry penalty modifier
+ var/carry_factor = CARRY_FACTOR_BASELINE
+ /// carry bias modify
+ var/carry_bias = 1
+ /// carry weight add - added to carry_strength for carry weight only, not encumbrance.
+ var/carry_weight_add = 0
+ /// carry weight factor - multiplied to carry_factor for carry weight only, not encumbrance.
+ var/carry_weight_factor = 1
+ /// carry weight bias - multipled to carry_bias for carry weight only, not encumbrance
+ var/carry_weight_bias = 1
+
+/datum/global_physiology/Destroy()
+ ownership = null
+ return ..()
+
+/datum/global_physiology/proc/reset()
+ carry_strength = initial(carry_strength)
+ carry_factor = initial(carry_factor)
+ carry_weight_add = initial(carry_weight_add)
+ carry_weight_factor = initial(carry_weight_factor)
+ carry_bias = initial(carry_bias)
+ carry_weight_bias = initial(carry_weight_bias)
+
+/datum/global_physiology/proc/apply(datum/physiology_modifier/modifier)
+ if(!isnull(modifier.carry_strength_add))
+ carry_strength += modifier.carry_strength_add
+ if(!isnull(modifier.carry_strength_factor))
+ carry_factor *= modifier.carry_strength_factor
+ if(!isnull(modifier.carry_weight_add))
+ carry_weight_add += modifier.carry_weight_add
+ if(!isnull(modifier.carry_weight_factor))
+ carry_weight_factor *= modifier.carry_weight_factor
+ if(!isnull(modifier.carry_strength_bias))
+ carry_bias *= modifier.carry_strength_bias
+ if(!isnull(modifier.carry_weight_bias))
+ carry_weight_bias *= modifier.carry_weight_bias
+
+/**
+ * return FALSE if we need to reset due to non-canonical operations
+ */
+/datum/global_physiology/proc/revert(datum/physiology_modifier/modifier)
+ . = TRUE
+ if(!isnull(modifier.carry_strength_add))
+ carry_strength -= modifier.carry_strength_add
+ if(!isnull(modifier.carry_strength_factor))
+ carry_factor /= modifier.carry_strength_factor
+ if(!isnull(modifier.carry_weight_add))
+ carry_weight_add -= modifier.carry_weight_add
+ if(!isnull(modifier.carry_weight_factor))
+ carry_weight_factor /= modifier.carry_weight_factor
+ if(!isnull(modifier.carry_strength_bias))
+ carry_bias /= modifier.carry_strength_bias
+ if(!isnull(modifier.carry_weight_bias))
+ carry_weight_bias /= modifier.carry_weight_bias
-/datum/physiology/proc/revert(datum/physiology_modifier/modifier)
- // todo: modifier/apply_global, modifier/apply_bodypart
+/datum/global_physiology/vv_edit_var(var_name, var_value, mass_edit, raw_edit)
+ // we automatically hook varedits and change the admin varedit holder so rebuilds take it into account
+ // this is not necessarily the best of ideas,
+ // because things like multiplicative factors don't scale as admins usually would expect
+ // but having this is better than not having it, as otherwise things would silently be wiped.
+ if(raw_edit)
+ return ..()
+ if(isnull(ownership))
+ return ..()
+ var/datum/physiology_modifier/varedit/varedit_modifier = ownership.get_varedit_physiology_modifier()
+ switch(var_name)
+ if(NAMEOF(src, carry_strength))
+ if(!isnum(var_value))
+ if(!mass_edit)
+ to_chat(usr, SPAN_WARNING("Invalid value [var_value] for [var_name] physiology edit rejected."))
+ return FALSE
+ . = ..()
+ if(!.)
+ return
+ varedit_modifier.carry_strength_add = var_value - carry_strength
+ if(NAMEOF(src, carry_factor))
+ if(!isnum(var_value))
+ if(!mass_edit)
+ to_chat(usr, SPAN_WARNING("Invalid value [var_value] for [var_name] physiology edit rejected."))
+ return FALSE
+ . = ..()
+ if(!.)
+ return
+ varedit_modifier.carry_strength_factor = var_value / carry_factor
+ else
+ return ..()
+ if(!mass_edit)
+ to_chat(usr, SPAN_NOTICE("Committing change to [var_name] on [ownership] ([REF(ownership)]) to physiology modifiers automatically."))
/**
* physiology modifier
@@ -19,17 +107,59 @@
/datum/physiology_modifier
abstract_type = /datum/physiology_modifier
+ /// our name
+ var/name = "Some Modifier"
/// is this a globally cached modifier?
var/is_globally_cached = FALSE
// todo: on biologies update, we need to specify what biologies this applies to
+ //? global modifiers
+ var/carry_strength_add = 0
+ var/carry_strength_factor = 1
+ var/carry_strength_bias = 1
+ var/carry_weight_add = 0
+ var/carry_weight_factor = 1
+ var/carry_weight_bias = 1
+
+/datum/physiology_modifier/serialize()
+ . = ..()
+ if(name != initial(name))
+ .["name"] = name
+ if(carry_strength_add != initial(carry_strength_add))
+ .["carry_strength_add"] = carry_strength_add
+ if(carry_strength_factor != initial(carry_strength_factor))
+ .["carry_strength_factor"] = carry_strength_factor
+
+/datum/physiology_modifier/deserialize(list/data)
+ . = ..()
+ if(istext(data["name"]))
+ name = data["name"]
+ if(isnum(data["carry_strength_add"]))
+ carry_strength_add = data["carry_strength_add"]
+ if(isnum(data["carry_strength_factor"]))
+ carry_strength_factor = data["carry_strength_factor"]
+ if(isnum(data["carry_strength_bias"]))
+ carry_strength_bias = data["carry_strength_bias"]
+ if(isnum(data["carry_weight_add"]))
+ carry_weight_add = data["carry_weight_add"]
+ if(isnum(data["carry_weight_factor"]))
+ carry_weight_factor = data["carry_weight_factor"]
+ if(isnum(data["carry_weight_bias"]))
+ carry_weight_bias = data["carry_Weight_bias"]
+
/**
* subtype for hardcoded physiology modifiers
*/
/datum/physiology_modifier/intrinsic
abstract_type = /datum/physiology_modifier/intrinsic
+/**
+ * subtype for admin varedit tracking
+ */
+/datum/physiology_modifier/varedit
+ name = "Admin Varedits"
+
GLOBAL_LIST_EMPTY(cached_physiology_modifiers)
/proc/cached_physiology_modifier(datum/physiology_modifier/path)
@@ -62,7 +192,7 @@ GLOBAL_LIST_EMPTY(cached_physiology_modifiers)
if(ispath(modifier))
modifier = cached_physiology_modifier(modifier)
ASSERT(!(modifier in physiology_modifiers))
- physiology_modifiers += modifier
+ LAZYADD(physiology_modifiers, modifier)
physiology.apply(modifier)
/**
@@ -74,18 +204,86 @@ GLOBAL_LIST_EMPTY(cached_physiology_modifiers)
if(ispath(modifier))
modifier = cached_physiology_modifier(modifier)
ASSERT(modifier in physiology_modifiers)
- physiology_modifiers -= modifier
- physiology.revert(modifier)
+ LAZYREMOVE(physiology_modifiers, modifier)
+ if(!physiology.revert(modifier))
+ // todo: optimize with reset().
+ rebuild_physiology()
/**
* completely rebuilds physiology from our modifiers
*/
/mob/proc/rebuild_physiology()
physiology = new
+ physiology.ownership = src
for(var/datum/physiology_modifier/modifier as anything in physiology_modifiers)
if(!istype(modifier))
physiology_modifiers -= modifier
continue
physiology.apply(modifier)
-// todo: admin vv verb via tgui to input new modifier
+/mob/vv_get_dropdown()
+ . = ..()
+ VV_DROPDOWN_OPTION(null, "-----")
+ VV_DROPDOWN_OPTION(VV_HK_ADD_PHYSIOLOGY_MODIFIER, "Add Physiology Modifier")
+ VV_DROPDOWN_OPTION(VV_HK_REMOVE_PHYSIOLOGY_MODIFIER, "Remove Physiology Modifier")
+
+/mob/vv_do_topic(list/href_list)
+ . = ..()
+ if(href_list[VV_HK_ADD_PHYSIOLOGY_MODIFIER])
+ // todo: this should be able to be done globally via admin panel and then added to mobs
+
+ var/datum/tgui_dynamic_query/query = new
+ query.string("name", "Name", "Name your modifier.", 64, FALSE, "Custom Modifier")
+ query.number("carry_strength_add", "Carry Strength - Add", "Modify the person's base carry strength. Higher is better.", default = 0)
+ query.number("carry_strength_factor", "Carry Factor - Multiply", "Multiply the person's carry weight/encumbrance to slowdown effect when carrying over their limit. Lower is better.", default = 1)
+ query.number("carry_strength_bias", "Carry Bias - Multiply", "Multiply the person's carry weight/encumbrance to slowdown bias when carrying over their limit. Lower is better.", default = 1)
+ query.number("carry_weight_add", "Carry Weight - Add", "Modify the person's base carry weight. Higher is better. This only applies to weight, not encumbrance.", default = 0)
+ query.number("carry_weight_factor", "Carry Weight - Multiply", "Multiply the person's weight to slowdown effect when carrying over their limit. Lower is better. This only applies to weight, not encumbrance.", default = 1)
+ query.number("carry_weight_bias", "Carry Weight - Bias", "Multiply the person's weight to slowdown calculation bias; lower is better.", default = 1)
+
+ var/list/choices = tgui_dynamic_input(usr, "Add a physiology modifier", "Add Physiology Modifier", query)
+
+ if(isnull(choices))
+ return
+ if(QDELETED(src))
+ return
+
+ var/datum/physiology_modifier/modifier = new
+
+ // we manually deserialize because we might have custom datatypes
+ // in the future that won't be serialized by the ui necessarily in the same way
+ // we would serialize it via json.
+
+ modifier.name = choices["name"]
+ modifier.carry_strength_add = choices["carry_strength_add"]
+ modifier.carry_strength_factor = choices["carry_strength_factor"]
+ modifier.carry_strength_bias = choices["carry_strength_bias"]
+ modifier.carry_weight_add = choices["carry_weight_add"]
+ modifier.carry_weight_factor = choices["carry_weight_factor"]
+ modifier.carry_weight_bias = choices["carry_weight_bias"]
+
+ log_admin("[key_name(usr)] --> [key_name(src)] - added physiology modifier [json_encode(modifier.serialize())]")
+ add_physiology_modifier(modifier)
+ return TRUE
+
+ if(href_list[VV_HK_REMOVE_PHYSIOLOGY_MODIFIER])
+ var/list/assembled = list()
+ var/i = 0
+ for(var/datum/physiology_modifier/modifier as anything in physiology_modifiers)
+ assembled["[modifier.name] (#[++i])"] = modifier
+ var/picked = input(usr, "Which modifier to remove? Please do not do this unless you know what you are doing.", "Remove Physiology Modifier") as null|anything in assembled
+ var/datum/physiology_modifier/removing = assembled[picked]
+ if(!(removing in physiology_modifiers))
+ return TRUE
+ log_admin("[key_name(usr)] --> [key_name(src)] - removed physiology modifier [json_encode(removing.serialize())]")
+ remove_physiology_modifier(removing)
+ return TRUE
+
+/mob/proc/get_varedit_physiology_modifier()
+ RETURN_TYPE(/datum/physiology_modifier)
+ . = locate(/datum/physiology_modifier/varedit) in physiology_modifiers
+ if(!isnull(.))
+ return
+ var/datum/physiology_modifier/varedit/new_holder = new
+ add_physiology_modifier(new_holder)
+ return new_holder
diff --git a/code/modules/movespeed/modifiers/mob.dm b/code/modules/movespeed/modifiers/mob.dm
index 77c8fe51864a..e47e309ee594 100644
--- a/code/modules/movespeed/modifiers/mob.dm
+++ b/code/modules/movespeed/modifiers/mob.dm
@@ -3,3 +3,11 @@
/datum/movespeed_modifier/mob_staggered
variable = TRUE
+
+/datum/movespeed_modifier/mob_inventory_carry
+ priority = MOVESPEED_PRIORITY_CARRY_WEIGHT
+ calculation_type = MOVESPEED_CALCULATION_LEGACY_MULTIPLY
+ variable = TRUE
+
+/datum/movespeed_modifier/mob_item_slowdown
+ variable = TRUE
diff --git a/code/modules/movespeed/movespeed_modifier.dm b/code/modules/movespeed/movespeed_modifier.dm
index 859326fa88ba..c8a9204223e7 100644
--- a/code/modules/movespeed/movespeed_modifier.dm
+++ b/code/modules/movespeed/movespeed_modifier.dm
@@ -33,13 +33,22 @@ Key procs
var/id
/// Determines order. Lower priorities are applied first.
- var/priority = 0
- var/flags = NONE
+ var/priority = MOVESPEED_PRIORITY_DEFAULT
+ /// flags
+ var/movespeed_modifier_flags = NONE
+ /// calculation type
+ var/calculation_type = MOVESPEED_CALCULATION_HYPERBOLIC
+
+ //* HYPERBOLIC, HYPERBOLIC_BOOST calculations
/// Multiplicative slowdown
var/multiplicative_slowdown = 0
- /// Next two variables depend on this: Should we do advanced calculations?
- var/complex_calculation = FALSE
+
+ //* MULTIPLY calculations
+ /// multiply resulting speed by
+ var/multiply_speed = 1
+
+ //* HYPERBOLIC_BOOST, MULTIPLY calculations
/// Absolute max tiles we can boost to
var/absolute_max_tiles_per_second = INFINITY
/// Max tiles per second we can boost
@@ -51,7 +60,8 @@ Key procs
/// Movetypes this never applies to
var/blacklisted_movetypes = NONE
- /// Other modification datums this conflicts with.
+ /// Other modification datums this conflicts with. Enum string.
+ /// If there is, it prioritizes the highest slow *or* the highest speedup, with abs().
var/conflicts_with
/datum/movespeed_modifier/New()
@@ -61,15 +71,61 @@ Key procs
/**
* Returns new multiplicative movespeed after modification.
+ *
+ * The minimum move delay is always world.tick_lag. Attempting to go lower will result in the excess being cut.
+ * This is so math doesn't break down when something attempts to break through the asymptote at 0 for move delay to speed.
*/
/datum/movespeed_modifier/proc/apply_multiplicative(existing, mob/target)
- if(!complex_calculation || (multiplicative_slowdown > 0)) // we aren't limiting how much things can slowdown.. yet.
- return existing + multiplicative_slowdown
- var/current_tiles = 10 / max(existing, world.tick_lag)
- // multiplicative_slowdown is negative due to our first check
- var/max_buff_to = max(existing + multiplicative_slowdown, 10 / absolute_max_tiles_per_second, 10 / (current_tiles + max_tiles_per_second_boost))
- // never slow the user
- return min(existing, max_buff_to)
+ // todo: we should max/min to ticklag rather than 0, but, we can't until everything is moved to modifiers.
+ switch(calculation_type)
+ /*
+ if(MOVESPEED_CALCULATION_HYPERBOLIC)
+ return max(world.tick_lag, existing + multiplicative_slowdown)
+ if(MOVESPEED_CALCULATION_HYPERBOLIC_BOOST)
+ var/current_tiles = 10 / max(existing, world.tick_lag)
+ var/max_buff_to = max(existing + multiplicative_slowdown, 10 / absolute_max_tiles_per_second, 10 / (current_tiles + max_tiles_per_second_boost))
+ return clamp(max_buff_to, world.tick_lag, existing)
+ if(MOVESPEED_CALCULATION_MULTIPLY)
+ var/current_tiles = 10 / max(world.tick_lag, existing)
+ return 10 / (current_tiles * multiply_speed)
+ */
+ if(MOVESPEED_CALCULATION_HYPERBOLIC)
+ // going below 0 would fuck multipliers up pretty badly
+ return max(0, existing + multiplicative_slowdown)
+ if(MOVESPEED_CALCULATION_HYPERBOLIC_BOOST)
+ var/current_tiles = 10 / max(existing, world.tick_lag)
+ var/max_buff_to = max(existing + multiplicative_slowdown, 10 / absolute_max_tiles_per_second, 10 / (current_tiles + max_tiles_per_second_boost))
+ return min(existing, max_buff_to)
+ if(MOVESPEED_CALCULATION_MULTIPLY)
+ if(existing > 0)
+ var/current_tiles = 10 / existing
+ return 10 / (current_tiles * multiply_speed)
+ else
+ var/current_tiles = 10 / config_legacy.run_speed
+ return 10 / (current_tiles * multiply_speed)
+ if(MOVESPEED_CALCULATION_LEGACY_MULTIPLY)
+ target.cached_movespeed_multiply *= multiply_speed
+ return existing
+ else
+ return existing
+
+/**
+ * applies from params
+ */
+/datum/movespeed_modifier/proc/parse(list/params)
+ . = FALSE
+ if(!isnull(params[MOVESPEED_PARAM_DELAY_MOD]))
+ . = TRUE
+ multiplicative_slowdown = params[MOVESPEED_PARAM_DELAY_MOD]
+ if(!isnull(params[MOVESPEED_PARAM_MULTIPLY_SPEED]))
+ . = TRUE
+ multiply_speed = params[MOVESPEED_PARAM_MULTIPLY_SPEED]
+ if(!isnull(params[MOVESPEED_PARAM_MAX_TILE_ABSOLUTE]))
+ . = TRUE
+ absolute_max_tiles_per_second = params[MOVESPEED_PARAM_MAX_TILE_ABSOLUTE]
+ if(!isnull(params[MOVESPEED_PARAM_MAX_TILE_BOOST]))
+ . = TRUE
+ max_tiles_per_second_boost = params[MOVESPEED_PARAM_MAX_TILE_BOOST]
GLOBAL_LIST_EMPTY(movespeed_modification_cache)
@@ -120,15 +176,16 @@ GLOBAL_LIST_EMPTY(movespeed_modification_cache)
update_movespeed(FALSE)
return TRUE
-/*! Used for variable slowdowns like hunger/health loss/etc, works somewhat like the old list-based modification adds. Returns the modifier datum if successful
- How this SHOULD work is:
- 1. Ensures type_id_datum one way or another refers to a /variable datum. This makes sure it can't be cached. This includes if it's already in the modification list.
- 2. Instantiate a new datum if type_id_datum isn't already instantiated + in the list, using the type. Obviously, wouldn't work for ID only.
- 3. Add the datum if necessary using the regular add proc
- 4. If any of the rest of the args are not null (see: multiplicative slowdown), modify the datum
- 5. Update if necessary
-*/
-/mob/proc/add_or_update_variable_movespeed_modifier(datum/movespeed_modifier/type_id_datum, update = TRUE, multiplicative_slowdown)
+/**
+ * Used for variable slowdowns like hunger/health loss/etc, works somewhat like the old list-based modification adds. Returns the modifier datum if successful
+ * How this SHOULD work is:
+ * 1. Ensures type_id_datum one way or another refers to a /variable datum. This makes sure it can't be cached. This includes if it's already in the modification list.
+ * 2. Instantiate a new datum if type_id_datum isn't already instantiated + in the list, using the type. Obviously, wouldn't work for ID only.
+ * 3. Add the datum if necessary using the regular add proc
+ * 4. If any of the rest of the args are not null (see: multiplicative slowdown), modify the datum
+ * 5. Update if necessary
+ */
+/mob/proc/add_or_update_variable_movespeed_modifier(datum/movespeed_modifier/type_id_datum, update = TRUE, list/params)
var/modified = FALSE
var/inject = FALSE
var/datum/movespeed_modifier/final
@@ -151,8 +208,7 @@ GLOBAL_LIST_EMPTY(movespeed_modification_cache)
if(!LAZYACCESS(movespeed_modification, final.id))
inject = TRUE
modified = TRUE
- if(!isnull(multiplicative_slowdown))
- final.multiplicative_slowdown = multiplicative_slowdown
+ if(final.parse(params))
modified = TRUE
if(inject)
add_movespeed_modifier(final, FALSE)
@@ -169,7 +225,7 @@ GLOBAL_LIST_EMPTY(movespeed_modification_cache)
diff = var_value - cached_multiplicative_slowdown
. = ..()
if(. && slowdown_edit && isnum(diff))
- add_or_update_variable_movespeed_modifier(/datum/movespeed_modifier/admin_varedit, multiplicative_slowdown = diff)
+ add_or_update_variable_movespeed_modifier(/datum/movespeed_modifier/admin_varedit, params = list(MOVESPEED_PARAM_DELAY_MOD = diff))
///Is there a movespeed modifier for this mob
/mob/proc/has_movespeed_modifier(datum/movespeed_modifier/datum_type_id)
@@ -206,6 +262,9 @@ GLOBAL_LIST_EMPTY(movespeed_modification_cache)
/mob/proc/update_movespeed()
. = 0
var/list/conflict_tracker = list()
+ //! TODO: LEGACY
+ cached_movespeed_multiply = 1
+ //! END
for(var/datum/movespeed_modifier/M in get_movespeed_modifiers())
if(!(M.movement_type & movement_type)) // We don't affect any of these move types, skip
continue
@@ -221,12 +280,12 @@ GLOBAL_LIST_EMPTY(movespeed_modification_cache)
else
continue
. = M.apply_multiplicative(., src)
- // your delay decreases, "give" the delay back to the client
- cached_multiplicative_slowdown = .
+ cached_multiplicative_slowdown = min(., 10 / MOVESPEED_ABSOLUTE_MINIMUM_TILES_PER_SECOND)
if(!client)
return
var/diff = (last_move_time - move_delay) - cached_multiplicative_slowdown
if(diff > 0)
+ // your delay decreases, "give" the delay back to the client
if(move_delay > world.time + 1.5)
move_delay -= diff
#ifdef SMOOTH_MOVEMENT
diff --git a/code/modules/photography/camera.dm b/code/modules/photography/camera.dm
index c20953a79a1a..fbff55491976 100644
--- a/code/modules/photography/camera.dm
+++ b/code/modules/photography/camera.dm
@@ -7,7 +7,7 @@
worn_state = "camera"
worn_render_flags = NONE
desc = "A polaroid camera. 10 photos left."
- item_flags = ITEM_NOBLUDGEON
+ item_flags = ITEM_NOBLUDGEON | ITEM_ENCUMBERS_WHILE_HELD
w_class = ITEMSIZE_SMALL
slot_flags = SLOT_BELT
materials = list(MAT_STEEL = 2000)
diff --git a/code/modules/projectiles/ammunition/ammo_casing.dm b/code/modules/projectiles/ammunition/ammo_casing.dm
index cb3a53a228dc..9b79f0b5738b 100644
--- a/code/modules/projectiles/ammunition/ammo_casing.dm
+++ b/code/modules/projectiles/ammunition/ammo_casing.dm
@@ -4,7 +4,7 @@
icon = 'icons/obj/ammo.dmi'
icon_state = "s-casing"
slot_flags = SLOT_BELT | SLOT_EARS
- item_flags = ITEM_EASY_LATHE_DECONSTRUCT
+ item_flags = ITEM_EASY_LATHE_DECONSTRUCT | ITEM_ENCUMBERS_WHILE_HELD
throw_force = 1
w_class = ITEMSIZE_TINY
preserve_item = 1
diff --git a/code/modules/projectiles/gun.dm b/code/modules/projectiles/gun.dm
index 1490cfbff748..f7c9c1afac6d 100644
--- a/code/modules/projectiles/gun.dm
+++ b/code/modules/projectiles/gun.dm
@@ -38,6 +38,7 @@
)
icon_state = "detective"
item_state = "gun"
+ item_flags = ITEM_ENCUMBERS_WHILE_HELD | ITEM_ENCUMBERS_ONLY_HELD
slot_flags = SLOT_BELT|SLOT_HOLSTER
materials = list(MAT_STEEL = 2000)
rad_flags = RAD_BLOCK_CONTENTS
diff --git a/code/modules/projectiles/guns/magnetic/magnetic_railgun.dm b/code/modules/projectiles/guns/magnetic/magnetic_railgun.dm
index a42dac66fe66..73aaa29d0c20 100644
--- a/code/modules/projectiles/guns/magnetic/magnetic_railgun.dm
+++ b/code/modules/projectiles/guns/magnetic/magnetic_railgun.dm
@@ -12,13 +12,12 @@
heavy = TRUE
slot_flags = SLOT_BELT
loaded = /obj/item/rcd_ammo/large
- slowdown = 1 // Slowdown equals slowdown_worn, until we decide to import the system to differentiate between held and worn items
+ weight = ITEM_WEIGHT_GUN_BULKY
+ encumbrance = ITEM_ENCUMBRANCE_GUN_BULKY
fire_delay = 1
var/initial_cell_type = /obj/item/cell/hyper
var/initial_capacitor_type = /obj/item/stock_parts/capacitor/adv
- var/slowdown_held = 2
- var/slowdown_worn = 1
var/empty_sound = 'sound/machines/twobeep.ogg'
/obj/item/gun/magnetic/railgun/Initialize(mapload)
@@ -64,9 +63,8 @@
initial_capacitor_type = /obj/item/stock_parts/capacitor/super
fire_delay = 0
- slowdown = 2
- slowdown_held = 3
- slowdown_worn = 2
+ weight = ITEM_WEIGHT_GUN_RIDICULOUS
+ encumbrance = ITEM_ENCUMBRANCE_GUN_RIDICULOUS
slot_flags = SLOT_BACK
w_class = ITEMSIZE_NO_CONTAINER
@@ -95,9 +93,8 @@
slot_flags = SLOT_BACK
- slowdown = 0
- slowdown_held = 0
- slowdown_worn = 0
+ weight = ITEM_WEIGHT_GUN_LIGHT
+ encumbrance = ITEM_ENCUMBRANCE_GUN_LIGHT
power_cost = 100
load_type = /obj/item/magnetic_ammo
@@ -127,9 +124,8 @@
slot_flags = SLOT_BACK
- slowdown = 0
- slowdown_held = 0
- slowdown_worn = 0
+ weight = ITEM_WEIGHT_GUN_LIGHT
+ encumbrance = ITEM_ENCUMBRANCE_GUN_LIGHT
power_cost = 400
projectile_type = /obj/projectile/bullet/magnetic/heated
@@ -185,7 +181,8 @@
slot_flags = SLOT_BACK
- slowdown = 0.3
+ weight = ITEM_WEIGHT_GUN_NORMAL
+ encumbrance = ITEM_ENCUMBRANCE_GUN_NORMAL
power_cost = 200
projectile_type = /obj/projectile/bullet/magnetic/flechette/hunting
diff --git a/code/modules/projectiles/guns/projectile/automatic.dm b/code/modules/projectiles/guns/projectile/automatic.dm
index b4783605f4ab..9601f63211da 100644
--- a/code/modules/projectiles/guns/projectile/automatic.dm
+++ b/code/modules/projectiles/guns/projectile/automatic.dm
@@ -549,7 +549,6 @@
slot_flags = SLOT_BACK
load_method = SPEEDLOADER
ammo_type = /obj/item/ammo_casing/a762
- slowdown = 0.5
max_shells = 15
burst = 3
fire_delay = 7.2
diff --git a/code/modules/projectiles/magazines/magazine.dm b/code/modules/projectiles/magazines/magazine.dm
index d50d31301ad1..fbfc27cdb404 100644
--- a/code/modules/projectiles/magazines/magazine.dm
+++ b/code/modules/projectiles/magazines/magazine.dm
@@ -4,7 +4,7 @@
desc = "A magazine for some kind of gun."
icon_state = ".357"
icon = 'icons/obj/ammo.dmi'
- item_flags = ITEM_EASY_LATHE_DECONSTRUCT
+ item_flags = ITEM_EASY_LATHE_DECONSTRUCT | ITEM_ENCUMBERS_WHILE_HELD
slot_flags = SLOT_BELT
item_state = "syringe_kit"
materials = list(MAT_STEEL = 500)
diff --git a/code/modules/reagents/reagent_containers/spray.dm b/code/modules/reagents/reagent_containers/spray.dm
index 727bd9a6c7af..3c691c49fa01 100644
--- a/code/modules/reagents/reagent_containers/spray.dm
+++ b/code/modules/reagents/reagent_containers/spray.dm
@@ -4,7 +4,7 @@
icon = 'icons/obj/janitor.dmi'
icon_state = "cleaner"
item_state = "cleaner"
- item_flags = ITEM_NOBLUDGEON
+ item_flags = ITEM_NOBLUDGEON | ITEM_ENCUMBERS_WHILE_HELD
atom_flags = OPENCONTAINER
slot_flags = SLOT_BELT | SLOT_HOLSTER
throw_force = 3
diff --git a/code/modules/reagents/reagent_containers/syringes.dm b/code/modules/reagents/reagent_containers/syringes.dm
index 4e87d47b3ae8..cb293dd571aa 100644
--- a/code/modules/reagents/reagent_containers/syringes.dm
+++ b/code/modules/reagents/reagent_containers/syringes.dm
@@ -17,7 +17,7 @@
sharp = 1
unacidable = 1 //glass
rad_flags = RAD_NO_CONTAMINATE
- item_flags = ITEM_NOBLUDGEON
+ item_flags = ITEM_NOBLUDGEON | ITEM_ENCUMBERS_WHILE_HELD
var/mode = SYRINGE_DRAW
var/image/filling //holds a reference to the current filling overlay
var/visible_name = "a syringe"
diff --git a/code/modules/resleeving/mirror.dm b/code/modules/resleeving/mirror.dm
index 11e96ebbdae4..0bad24f9dd3b 100644
--- a/code/modules/resleeving/mirror.dm
+++ b/code/modules/resleeving/mirror.dm
@@ -10,7 +10,8 @@
icon_state = "mirror_implant_f"
var/stored_mind = null
var/tmp/mob/living/carbon/human/human
- item_flags = ITEM_NOBLUDGEON
+ item_flags = ITEM_NOBLUDGEON | ITEM_ENCUMBERS_WHILE_HELD
+
//holder to prevent having to find it each time
/mob/living/carbon/human/var/obj/item/implant/mirror/mirror
@@ -106,7 +107,7 @@
throw_range = 10
materials = list(MAT_STEEL = 200)
origin_tech = list(TECH_MAGNET = 2, TECH_BIO = 2)
- item_flags = ITEM_NOBLUDGEON
+ item_flags = ITEM_NOBLUDGEON | ITEM_ENCUMBERS_WHILE_HELD
/obj/item/mirrortool
name = "Mirror Installation Tool"
@@ -121,7 +122,7 @@
throw_range = 10
materials = list(MAT_STEEL = 200)
origin_tech = list(TECH_MAGNET = 2, TECH_BIO = 2)
- item_flags = ITEM_NOBLUDGEON
+ item_flags = ITEM_NOBLUDGEON | ITEM_ENCUMBERS_WHILE_HELD
var/obj/item/implant/mirror/imp = null
/obj/item/mirrortool/afterattack(atom/target, mob/user, clickchain_flags, list/params)
diff --git a/code/modules/species/physiology.dm b/code/modules/species/physiology.dm
new file mode 100644
index 000000000000..f32b69464ea7
--- /dev/null
+++ b/code/modules/species/physiology.dm
@@ -0,0 +1,4 @@
+//* This file is explicitly licensed under the MIT license. *//
+//* Copyright (c) 2023 Citadel Station developers. *//
+
+/datum/physiology_modifier/intrinsic/species
diff --git a/code/modules/species/protean/protean.dm b/code/modules/species/protean/protean.dm
index cf7518fcf1bf..f20b7b98266b 100644
--- a/code/modules/species/protean/protean.dm
+++ b/code/modules/species/protean/protean.dm
@@ -1,6 +1,10 @@
#define DAM_SCALE_FACTOR 0.01
#define METAL_PER_TICK 100
+/datum/physiology_modifier/intrinsic/species/protean
+ carry_strength_add = CARRY_STRENGTH_ADD_PROTEAN
+ carry_strength_factor = CARRY_FACTOR_MOD_PROTEAN
+
/datum/species/protean
uid = SPECIES_ID_PROTEAN
name = SPECIES_PROTEAN
@@ -13,6 +17,7 @@
death_message = "rapidly loses cohesion, dissolving into a cloud of gray dust..."
knockout_message = "collapses inwards, forming a disordered puddle of gray goo."
remains_type = /obj/effect/debris/cleanable/ash
+ mob_physiology_modifier = /datum/physiology_modifier/intrinsic/species/protean
unarmed_types = list(/datum/unarmed_attack/stomp, /datum/unarmed_attack/kick, /datum/unarmed_attack/punch, /datum/unarmed_attack/bite) // Regular human attack verbs are enough.
@@ -347,7 +352,7 @@
if(istype(back, /obj/item/hardsuit/protean))
var/obj/item/hardsuit/protean/suit = back
- if(suit.myprotean == src)
+ if(suit.myprotean == src)
suit.reset()
suit.forceMove(src)
to_chat(src, SPAN_WARNING("You retract your nanosuit."))
diff --git a/code/modules/species/species.dm b/code/modules/species/species.dm
index e5b398ead756..549e5ef765c2 100644
--- a/code/modules/species/species.dm
+++ b/code/modules/species/species.dm
@@ -43,7 +43,8 @@
//? Traits / Physiology
/// Intrinsic datum traits to apply to the mob
var/list/mob_traits
- // todo: list of physiologies to add. list, incase we want to have separate ones for separate biology flags.
+ /// physiology modifier to add - path or instance
+ var/datum/physiology_modifier/mob_physiology_modifier
//? Additional info
/// what you see on tooltip/examine
@@ -527,6 +528,9 @@
H.maxHealth = total_health
+ if(!isnull(mob_physiology_modifier))
+ H.add_physiology_modifier(mob_physiology_modifier)
+
add_inherent_verbs(H)
for(var/name in traits)
@@ -553,6 +557,9 @@
remove_inherent_verbs(H)
H.holder_type = null
+ if(!isnull(mob_physiology_modifier))
+ H.remove_physiology_modifier(mob_physiology_modifier)
+
for(var/name in traits)
var/datum/trait/T = all_traits[name]
T.remove(src, H)
diff --git a/code/modules/species/station/standard/human.dm b/code/modules/species/station/standard/human.dm
index 3c5413971319..72defa90b66f 100644
--- a/code/modules/species/station/standard/human.dm
+++ b/code/modules/species/station/standard/human.dm
@@ -1,3 +1,7 @@
+/datum/physiology_modifier/intrinsic/species/human
+ carry_strength_add = CARRY_STRENGTH_ADD_HUMAN
+ carry_strength_factor = CARRY_FACTOR_MOD_HUMAN
+
/datum/species/human
id = SPECIES_ID_HUMAN
uid = SPECIES_ID_HUMAN
@@ -15,6 +19,7 @@
interests, rampant cyber and bio-augmentation initiatives, and secretive factions make life on most human \
worlds tumultous at best."
catalogue_data = list(/datum/category_item/catalogue/fauna/humans)
+ mob_physiology_modifier = /datum/physiology_modifier/intrinsic/species/human
max_additional_languages = 3
intrinsic_languages = list(
diff --git a/code/modules/species/station/standard/moth.dm b/code/modules/species/station/standard/moth.dm
index c224674a65a2..9e416179ea4d 100644
--- a/code/modules/species/station/standard/moth.dm
+++ b/code/modules/species/station/standard/moth.dm
@@ -4,6 +4,8 @@ GLOBAL_LIST_INIT(moth_lore_data, init_moth_lore())
/proc/init_moth_lore()
return json_decode(file2text('strings/misc/moth_species.json'))
+/datum/physiology_modifier/intrinsic/species/nepid
+
/datum/species/moth
name = SPECIES_MOTH
uid = SPECIES_ID_MOTH
@@ -157,20 +159,30 @@ GLOBAL_LIST_INIT(moth_lore_data, init_moth_lore())
"}
value = CATALOGUER_REWARD_TRIVIAL
+/datum/physiology_modifier/intrinsic/species/nepid/dark
+ carry_strength_add = CARRY_STRENGTH_ADD_MOTH_DARK
+ carry_strength_factor = CARRY_FACTOR_MOD_MOTH_DARK
+
/datum/species/moth/dark
name = SPECIES_MOTH_DARK
uid = SPECIES_ID_MOTH_DARK
species_spawn_flags = SPECIES_SPAWN_CHARACTER
+ mob_physiology_modifier = /datum/physiology_modifier/intrinsic/species/nepid/dark
// darksight, but weak to light
vision_innate = /datum/vision/baseline/species_tier_2
flash_burn = 5
flash_mod = 1.2
+/datum/physiology_modifier/intrinsic/species/nepid/light
+ carry_strength_add = CARRY_STRENGTH_ADD_MOTH_LIGHT
+ carry_strength_factor = CARRY_FACTOR_MOD_MOTH_LIGHT
+
/datum/species/moth/light
name = SPECIES_MOTH_LIGHT
uid = SPECIES_ID_MOTH_LIGHT
species_spawn_flags = SPECIES_SPAWN_CHARACTER
+ mob_physiology_modifier = /datum/physiology_modifier/intrinsic/species/nepid/light
// hardy, but no darksight
vision_innate = /datum/vision/baseline/species_tier_0
diff --git a/code/modules/species/station/standard/tajaran.dm b/code/modules/species/station/standard/tajaran.dm
index da2949b6ef7a..f87fa59449ba 100644
--- a/code/modules/species/station/standard/tajaran.dm
+++ b/code/modules/species/station/standard/tajaran.dm
@@ -1,3 +1,7 @@
+/datum/physiology_modifier/intrinsic/species/tajaran
+ carry_strength_add = CARRY_STRENGTH_ADD_TAJARAN
+ carry_strength_factor = CARRY_FACTOR_MOD_TAJARAN
+
/datum/species/tajaran
uid = SPECIES_ID_TAJARAN
id = SPECIES_ID_TAJARAN
@@ -5,6 +9,7 @@
name_plural = "Tajaran"
category = "Tajaran"
default_bodytype = BODYTYPE_TAJARAN
+ mob_physiology_modifier = /datum/physiology_modifier/intrinsic/species/tajaran
icobase = 'icons/mob/species/tajaran/body_greyscale.dmi'
deform = 'icons/mob/species/tajaran/deformed_body_greyscale.dmi'
diff --git a/code/modules/species/station/standard/teshari.dm b/code/modules/species/station/standard/teshari.dm
index 48d92f38c5e4..27a319c4b071 100644
--- a/code/modules/species/station/standard/teshari.dm
+++ b/code/modules/species/station/standard/teshari.dm
@@ -1,3 +1,7 @@
+/datum/physiology_modifier/intrinsic/species/teshari
+ carry_strength_add = CARRY_STRENGTH_ADD_TESHARI
+ carry_strength_factor = CARRY_FACTOR_MOD_TESHARI
+
/datum/species/teshari
uid = SPECIES_ID_TESHARI
id = SPECIES_ID_TESHARI
@@ -6,6 +10,7 @@
category = "Teshari"
name_plural = "Tesharii"
uid = SPECIES_ID_TESHARI
+ mob_physiology_modifier = /datum/physiology_modifier/intrinsic/species/teshari
blurb = {"
A race of feathered raptors who developed alongside the Skrell, inhabiting
diff --git a/code/modules/species/station/standard/unathi.dm b/code/modules/species/station/standard/unathi.dm
index dd491e80d0be..51b906ec8009 100644
--- a/code/modules/species/station/standard/unathi.dm
+++ b/code/modules/species/station/standard/unathi.dm
@@ -1,3 +1,7 @@
+/datum/physiology_modifier/intrinsic/species/unathi
+ carry_strength_add = CARRY_STRENGTH_ADD_UNATHI
+ carry_strength_factor = CARRY_FACTOR_MOD_UNATHI
+
/datum/species/unathi
uid = SPECIES_ID_UNATHI
id = SPECIES_ID_UNATHI
@@ -7,6 +11,8 @@
primitive_form = SPECIES_MONKEY_UNATHI
default_bodytype = BODYTYPE_UNATHI
+ mob_physiology_modifier = /datum/physiology_modifier/intrinsic/species/unathi
+
// icon_template = 'icons/mob/species/template_tall.dmi' //TODO: Tall Unathi :D
icobase = 'icons/mob/species/unathi/body_greyscale.dmi'
deform = 'icons/mob/species/unathi/deformed_body_greyscale.dmi'
diff --git a/code/modules/species/station/xenochimera.dm b/code/modules/species/station/xenochimera.dm
index 31c5acc12e89..70c42b5e68fd 100644
--- a/code/modules/species/station/xenochimera.dm
+++ b/code/modules/species/station/xenochimera.dm
@@ -1,3 +1,7 @@
+/datum/physiology_modifier/intrinsic/species/xenochimera
+ carry_strength_add = CARRY_STRENGTH_ADD_XENOCHIMERA
+ carry_strength_factor = CARRY_FACTOR_MOD_XENOCHIMERA
+
/datum/species/shapeshifter/xenochimera //Scree's race.
uid = SPECIES_ID_XENOCHIMERA
id = SPECIES_ID_XENOCHIMERA
@@ -5,6 +9,7 @@
name_plural = "Xenochimeras"
base_species = SPECIES_XENOCHIMERA
category = "Special"
+ mob_physiology_modifier = /datum/physiology_modifier/intrinsic/species/xenochimera
selects_bodytype = TRUE
diff --git a/code/modules/species/station/xenomorph_hybrids/xeno_hybrids.dm b/code/modules/species/station/xenomorph_hybrids/xeno_hybrids.dm
index a80036c40593..94983c04321c 100644
--- a/code/modules/species/station/xenomorph_hybrids/xeno_hybrids.dm
+++ b/code/modules/species/station/xenomorph_hybrids/xeno_hybrids.dm
@@ -1,9 +1,14 @@
+/datum/physiology_modifier/intrinsic/species/xenohybrid
+ carry_strength_add = CARRY_STRENGTH_ADD_XENOHYBRID
+ carry_strength_factor = CARRY_FACTOR_MOD_XENOHYBRID
+
/datum/species/xenohybrid
name = SPECIES_XENOHYBRID
name_plural = "Xenomorph Hybrids"
uid = SPECIES_ID_XENOHYBRID
id = SPECIES_ID_XENOHYBRID
default_bodytype = BODYTYPE_XENOHYBRID
+ mob_physiology_modifier = /datum/physiology_modifier/intrinsic/species/xenohybrid
icobase = 'icons/mob/species/xenohybrid/body.dmi'
deform = 'icons/mob/species/xenohybrid/deformed_body.dmi'
diff --git a/code/modules/tgui/modal_vr.dm b/code/modules/tgui/modal_vr_legacy.dm
similarity index 100%
rename from code/modules/tgui/modal_vr.dm
rename to code/modules/tgui/modal_vr_legacy.dm
diff --git a/code/modules/tgui/tgui_alert.dm b/code/modules/tgui/modals/tgui_alert.dm
similarity index 100%
rename from code/modules/tgui/tgui_alert.dm
rename to code/modules/tgui/modals/tgui_alert.dm
diff --git a/code/modules/tgui/modals/tgui_dynamic_input.dm b/code/modules/tgui/modals/tgui_dynamic_input.dm
new file mode 100644
index 000000000000..8fc7338ccc83
--- /dev/null
+++ b/code/modules/tgui/modals/tgui_dynamic_input.dm
@@ -0,0 +1,217 @@
+//* This file is explicitly licensed under the MIT license. *//
+//* Copyright (c) 2023 Citadel Station developers. *//
+
+/**
+ * Helper datum used to build a query for tgui_dynamic_input
+ * High overhead, technically not necessary, but, this is easy to use as an API.
+ */
+/datum/tgui_dynamic_query
+ /// options list
+ var/list/options = list()
+
+/datum/tgui_dynamic_query/proc/string(key, name, desc, max_length = 512, multi_line = FALSE, default)
+ RETURN_TYPE(/datum/tgui_dynamic_query)
+ options[key] = list(
+ "name" = name,
+ "desc" = desc,
+ "default" = default,
+ "type" = TGUI_INPUT_DATATYPE_TEXT,
+ "constraints" = list(max_length),
+ )
+ return src
+
+/datum/tgui_dynamic_query/proc/number(key, name, desc, min_value = -INFINITY, max_value = INFINITY, round_to, default)
+ RETURN_TYPE(/datum/tgui_dynamic_query)
+ options[key] = list(
+ "name" = name,
+ "desc" = desc,
+ "default" = default,
+ "type" = TGUI_INPUT_DATATYPE_NUM,
+ "constraints" = list(min_value, max_value, round_to),
+ )
+ return src
+
+/datum/tgui_dynamic_query/proc/toggle(key, name, desc, default)
+ RETURN_TYPE(/datum/tgui_dynamic_query)
+ options[key] = list(
+ "name" = name,
+ "desc" = desc,
+ "default" = default,
+ "type" = TGUI_INPUT_DATATYPE_TOGGLE,
+ "constraints" = list(),
+ )
+ return src
+
+/datum/tgui_dynamic_query/proc/pick_one(key, name, desc, list/choices = list(), default)
+ RETURN_TYPE(/datum/tgui_dynamic_query)
+ options[key] = list(
+ "name" = name,
+ "desc" = desc,
+ "default" = default,
+ "type" = TGUI_INPUT_DATATYPE_LIST_PICK,
+ "constraints" = choices,
+ )
+ return src
+
+/**
+ * builds return list of results
+ */
+/datum/tgui_dynamic_query/proc/get_results(list/choices)
+ . = list()
+ var/got
+ for(var/key in options)
+ var/list/params = options[key]
+ var/val = choices[key]
+ switch(params[TGUI_INPUT_DATA_TYPE])
+ if(TGUI_INPUT_DATATYPE_TEXT)
+ got = isnull(val) ? params[TGUI_INPUT_DATA_DEFAULT] : val
+ if(!isnull(got))
+ if(length(got) > params[TGUI_INPUT_DATA_CONSTRAINTS][1])
+ got = copytext_char(got, 1, params[TGUI_INPUT_DATA_CONSTRAINTS][1] + 1)
+ .[key] = got
+ if(TGUI_INPUT_DATATYPE_NUM)
+ got = isnull(val) ? params[TGUI_INPUT_DATA_DEFAULT] : text2num(val)
+ if(!isnull(got))
+ got = clamp(got, params[TGUI_INPUT_DATA_CONSTRAINTS][1], params[TGUI_INPUT_DATA_CONSTRAINTS][2])
+ if(!isnull(params[TGUI_INPUT_DATA_CONSTRAINTS][3]))
+ got = round(got, params[TGUI_INPUT_DATA_CONSTRAINTS][3])
+ .[key] = got
+ if(TGUI_INPUT_DATATYPE_LIST_PICK)
+ got = isnull(val) ? params[TGUI_INPUT_DATA_DEFAULT] : val
+ if(!isnull(got))
+ if(!(got in params[TGUI_INPUT_DATA_CONSTRAINTS]))
+ if(length(params[TGUI_INPUT_DATA_CONSTRAINTS]))
+ got = params[TGUI_INPUT_DATA_CONSTRAINTS][1]
+ else
+ got = null
+ .[key] = got
+ if(TGUI_INPUT_DATATYPE_TOGGLE)
+ got = isnull(val) ? params[TGUI_INPUT_DATA_DEFAULT] : val
+ if(!isnull(got))
+ got = !!got
+ .[key] = got
+
+/**
+ * returns list to be sent to UI
+ */
+/datum/tgui_dynamic_query/proc/get_query()
+ return options
+
+/**
+ * Creates a TGUI input window and returns the user's response
+ *
+ * This is used to grab a set of responses to various datatypes.
+ * This proc blocks until finished.
+ *
+ * @params
+ * * user - who to send this to
+ * * message - description in interface
+ * * title - self explanatory
+ * * query - built query
+ * * timeout - timeout before menu closes. if it times out, choices will be null.
+ *
+ * @return list of key-value pairs (the TGUI_INPUT_DATA_KEY's you put in) associated to values
+ */
+/proc/tgui_dynamic_input(mob/user, message, title = "Input", datum/tgui_dynamic_query/query, timeout = 0)
+ var/datum/tgui_dynamic_input/modal = new(user, message, title, query, timeout)
+ modal.block_on_finished()
+ return modal.query.get_results(modal.choices)
+
+/**
+ * Creates a TGUI input window and returns the user's response
+ *
+ * This is used to grab a set of responses to various datatypes.
+ * This proc immediately returns.
+ *
+ * @params
+ * * user - who to send this to
+ * * message - description in interface
+ * * title - self explanatory
+ * * query - built query
+ * * timeout - timeout before menu closes. if it times out, choices will be null.
+ * * callback - callback called with first arg being the picked list when we're done.
+ *
+ * @return the /datum/tgui_dynamic_input instance created. you should probably not touch this unless you know what you're doing.
+ */
+/proc/tgui_dynamic_input_async(mob/user, message, title = "Input", datum/tgui_dynamic_query/query, timeout = 0, datum/callback/callback)
+ return new /datum/tgui_dynamic_input(user, message, title, query, timeout, callback)
+
+/datum/tgui_dynamic_input
+ /// title of the windo
+ var/title
+ /// message that appears inside the window
+ var/message
+ /// query datum
+ var/datum/tgui_dynamic_query/query
+ /// list of user's choices; null if they haven't picked yet
+ var/list/choices
+ /// when we were opened
+ var/opened_time
+ /// how long our timeout is; null for infinite
+ var/timeout
+ /// did user close us yet? also set to true if we're qdeleted
+ var/closed
+ /// callback to invoke on finish
+ var/datum/callback/callback
+ /// are we finished? set to true on close, here to prevent double close.
+ var/finished = FALSE
+
+/datum/tgui_dynamic_input/New(mob/user, message, title, datum/tgui_dynamic_query/query, timeout, datum/callback/callback)
+ src.title = title
+ src.message = message
+ src.query = query
+ src.timeout = timeout
+ if(timeout)
+ QDEL_IN(src, timeout)
+ src.callback = callback
+ ui_interact(user)
+
+/datum/tgui_dynamic_input/Destroy()
+ // 'choices' and 'query' intentionally kept
+ if(!finished)
+ finish(null)
+ closed = TRUE
+ return ..()
+
+/datum/tgui_dynamic_input/ui_static_data(mob/user, datum/tgui/ui, datum/ui_state/state)
+ . = ..()
+ .["query"] = query.get_query()
+ .["title"] = title
+ .["message"] = message
+ .["timeout"] = timeout
+
+/datum/tgui_dynamic_input/ui_interact(mob/user, datum/tgui/ui, datum/tgui/parent_ui)
+ ui = SStgui.try_update_ui(user, src, ui)
+ if(!ui)
+ ui = new(user, src, "UIDynamicInputModal")
+ ui.set_autoupdate(FALSE)
+ ui.open()
+
+/datum/tgui_dynamic_input/ui_act(action, list/params, datum/tgui/ui)
+ . = ..()
+ if(.)
+ return
+ switch(action)
+ if("submit")
+ finish(params["choices"])
+ return TRUE
+ if("cancel")
+ closed = TRUE
+ SStgui.close_uis(src)
+ if(!finished)
+ finish(null)
+ return TRUE
+
+/datum/tgui_dynamic_input/ui_state(mob/user, datum/tgui_module/module)
+ return GLOB.always_state
+
+/datum/tgui_dynamic_input/proc/block_on_finished()
+ UNTIL(closed)
+ return choices
+
+/datum/tgui_dynamic_input/proc/finish(list/choices)
+ finished = TRUE
+ choices = query.get_results(choices)
+ callback?.InvokeAsync(choices)
+ if(!QDESTROYING(src))
+ qdel(src)
diff --git a/code/modules/tgui/tgui_input_list.dm b/code/modules/tgui/modals/tgui_input_list.dm
similarity index 100%
rename from code/modules/tgui/tgui_input_list.dm
rename to code/modules/tgui/modals/tgui_input_list.dm
diff --git a/code/modules/tgui/tgui_input_number.dm b/code/modules/tgui/modals/tgui_input_number.dm
similarity index 100%
rename from code/modules/tgui/tgui_input_number.dm
rename to code/modules/tgui/modals/tgui_input_number.dm
diff --git a/code/modules/tgui/tgui_input_text.dm b/code/modules/tgui/modals/tgui_input_text.dm
similarity index 100%
rename from code/modules/tgui/tgui_input_text.dm
rename to code/modules/tgui/modals/tgui_input_text.dm
diff --git a/code/modules/tgui/module.dm b/code/modules/tgui/module.dm
index 2f5ce0b17dda..309c79ee2bc3 100644
--- a/code/modules/tgui/module.dm
+++ b/code/modules/tgui/module.dm
@@ -1,6 +1,5 @@
-/**
- *! SPDX-License-Identifier: MIT
- */
+//* This file is explicitly licensed under the MIT license. *//
+//* Copyright (c) 2023 Citadel Station developers. *//
/**
* new, more-modular tgui_module system
diff --git a/code/modules/tgui/modules/general/cardmod.dm b/code/modules/tgui/modules/general/cardmod.dm
index 6038b1d7c132..8159736558c7 100644
--- a/code/modules/tgui/modules/general/cardmod.dm
+++ b/code/modules/tgui/modules/general/cardmod.dm
@@ -1,3 +1,6 @@
+//* This file is explicitly licensed under the MIT license. *//
+//* Copyright (c) 2023 Citadel Station developers. *//
+
/**
* ID mod module
*
diff --git a/code/modules/tgui/modules/specific/lathe_control.dm b/code/modules/tgui/modules/specific/lathe_control.dm
index bee1c7cb14a0..11bac06b7df4 100644
--- a/code/modules/tgui/modules/specific/lathe_control.dm
+++ b/code/modules/tgui/modules/specific/lathe_control.dm
@@ -1,3 +1,6 @@
+//* This file is explicitly licensed under the MIT license. *//
+//* Copyright (c) 2023 Citadel Station developers. *//
+
/**
* So why do we have discrete modules for lathe control?
*
diff --git a/code/modules/unit_tests/core/priority_queue.dm b/code/modules/unit_tests/core/priority_queue.dm
index e1759b43f2cc..28e0339f0c15 100644
--- a/code/modules/unit_tests/core/priority_queue.dm
+++ b/code/modules/unit_tests/core/priority_queue.dm
@@ -1,5 +1,5 @@
/datum/unit_test/priority_queue/Run()
- var/datum/priority_queue/queue = new(/proc/cmp_numeric_asc)
+ var/datum/priority_queue/queue = new /datum/priority_queue(/proc/cmp_numeric_asc)
for(var/i in 1 to 1000)
queue.enqueue(rand(1, 100000))
var/last = queue.dequeue()
diff --git a/code/modules/vehicles_legacy/construction.dm b/code/modules/vehicles_legacy/construction.dm
index f290ab767cac..6da492e2f5df 100644
--- a/code/modules/vehicles_legacy/construction.dm
+++ b/code/modules/vehicles_legacy/construction.dm
@@ -11,7 +11,7 @@
item_state = "buildpipe"
density = TRUE
- slowdown = 10 //It's a vehicle frame, what do you expect?
+ weight = ITEM_WEIGHT_VEHICLE_FRAME
w_class = 5
pixel_x = -16
diff --git a/code/modules/vore/fluffstuff/custom_items.dm b/code/modules/vore/fluffstuff/custom_items.dm
index a49ccfa82bf9..1da2469624e8 100644
--- a/code/modules/vore/fluffstuff/custom_items.dm
+++ b/code/modules/vore/fluffstuff/custom_items.dm
@@ -676,7 +676,7 @@
desc = "Seems absurd, doesn't it? Yet, here we are. Generally considered dangerous contraband unless the user has permission from Central Command."
icon = 'icons/obj/device_alt.dmi'
icon_state = "hand_tele"
- item_flags = ITEM_NOBLUDGEON
+ item_flags = ITEM_NOBLUDGEON | ITEM_ENCUMBERS_WHILE_HELD
w_class = ITEMSIZE_SMALL
origin_tech = list(TECH_MAGNET = 5, TECH_BLUESPACE = 5, TECH_ILLEGAL = 7)
@@ -972,7 +972,7 @@
icon = 'icons/obj/device_alt.dmi'
icon_state = "motion2"
w_class = ITEMSIZE_TINY
- item_flags = ITEM_NOBLUDGEON
+ item_flags = ITEM_NOBLUDGEON | ITEM_ENCUMBERS_WHILE_HELD
var/tele_name
var/obj/item/perfect_tele/tele_hand
diff --git a/code/modules/xenoarcheaology/tools/equipment.dm b/code/modules/xenoarcheaology/tools/equipment.dm
index 554668ad21a7..327169c1b7d4 100644
--- a/code/modules/xenoarcheaology/tools/equipment.dm
+++ b/code/modules/xenoarcheaology/tools/equipment.dm
@@ -7,6 +7,8 @@
armor_type = /datum/armor/general/biosuit/anomaly
max_pressure_protection = 5 * ONE_ATMOSPHERE // Not very good protection, but if an anomaly starts doing gas stuff you're not screwed
min_pressure_protection = 0.4 * ONE_ATMOSPHERE
+ encumbrance = ITEM_ENCUMBRANCE_ARMOR_ANOMALY
+ weight = ITEM_WEIGHT_ARMOR_ANOMALY
/obj/item/clothing/head/bio_hood/anomaly
name = "Anomaly hood"
@@ -16,6 +18,8 @@
armor_type = /datum/armor/general/biosuit/anomaly
max_pressure_protection = 5 * ONE_ATMOSPHERE // Not very good protection, but if an anomaly starts doing gas stuff you're not screwed
min_pressure_protection = 0.4 * ONE_ATMOSPHERE
+ encumbrance = ITEM_ENCUMBRANCE_ARMOR_ANOMALY_HELMET
+ weight = ITEM_WEIGHT_ARMOR_ANOMALY_HELMET
/obj/item/clothing/suit/space/anomaly
name = "Excavation suit"
@@ -24,7 +28,8 @@
item_state = "cespace_suit"
armor_type = /datum/armor/general/biosuit/anomaly
allowed = list(/obj/item/flashlight,/obj/item/tank,/obj/item/suit_cooling_unit,/obj/item/pickaxe)
- slowdown = 1
+ encumbrance = ITEM_ENCUMBRANCE_VOIDSUIT_ANOMALY
+ weight = ITEM_WEIGHT_VOIDSUIT_ANOMALY
// Pressure protection inherited from space suits
/obj/item/clothing/head/helmet/space/anomaly
@@ -33,3 +38,5 @@
icon_state = "cespace_helmet"
item_state = "cespace_helmet"
armor_type = /datum/armor/general/biosuit/anomaly
+ encumbrance = ITEM_ENCUMBRANCE_VOIDSUIT_ANOMALY_HELMET
+ weight = ITEM_WEIGHT_VOIDSUIT_ANOMALY_HELMET
diff --git a/icons/screen/alerts/backgrounds.dmi b/icons/screen/alerts/backgrounds.dmi
new file mode 100644
index 000000000000..2c328fea468e
Binary files /dev/null and b/icons/screen/alerts/backgrounds.dmi differ
diff --git a/icons/screen/alerts/encumbered.dmi b/icons/screen/alerts/encumbered.dmi
new file mode 100644
index 000000000000..cd840acc6b73
Binary files /dev/null and b/icons/screen/alerts/encumbered.dmi differ
diff --git a/tgui/packages/tgui/interfaces/ui/UIDynamicInputModal.tsx b/tgui/packages/tgui/interfaces/ui/UIDynamicInputModal.tsx
new file mode 100644
index 000000000000..5eb69ae7c00e
--- /dev/null
+++ b/tgui/packages/tgui/interfaces/ui/UIDynamicInputModal.tsx
@@ -0,0 +1,235 @@
+import { round } from "common/math";
+import { BooleanLike } from "common/react";
+import { useBackend, useLocalState } from "../../backend";
+import { Button, Dropdown, Input, NumberInput, Section, Stack, Tooltip } from "../../components";
+import { Window } from "../../layouts";
+
+interface UIDynamicInputContext {
+ title: string;
+ message: string;
+ timeout: number;
+ // key to entry data
+ query: Record;
+}
+
+type UIDynamicInputEntry = StringEntry | NumberEntry | PickEntry | ToggleEntry;
+
+interface BaseEntry {
+ name: string;
+ desc: string;
+}
+
+interface StringEntry extends BaseEntry {
+ type: UIDynamicInputType.String;
+ constraints: StringConstraint;
+ default: StringOption;
+}
+
+interface NumberEntry extends BaseEntry {
+ type: UIDynamicInputType.Number;
+ constraints: NumberConstraint;
+ default: NumberOption;
+}
+
+interface PickEntry extends BaseEntry {
+ type: UIDynamicInputType.ListSingle;
+ constraints: ListConstraint;
+ default: ListOption;
+}
+
+interface ToggleEntry extends BaseEntry {
+ type: UIDynamicInputType.Toggle;
+ constraints: ToggleConstraint;
+ default: ToggleOption;
+}
+
+enum UIDynamicInputType {
+ String = "text",
+ Number = "num",
+ ListSingle = "list_single",
+ Toggle = "bool",
+}
+
+type UIDynamicInputConstraint = StringConstraint | NumberConstraint | ListConstraint | ToggleConstraint;
+
+type StringConstraint = [number];
+type NumberConstraint = [number, number, number | null];
+type ListConstraint = string[];
+type ToggleConstraint = [];
+
+type UIDynamicInputOption = StringOption | NumberOption | ListOption | ToggleOption;
+
+type StringOption = string | null | undefined;
+type NumberOption = number | null | undefined;
+type ListOption = string | null | undefined;
+type ToggleOption = BooleanLike;
+
+export const UIDynamicInputModal = (props, context) => {
+ const { data, act } = useBackend(context);
+ const [options, setOptions] =useLocalState>(context, 'options', {});
+ return (
+
+
+
+
+
+
+
+
+
+ {Object.entries(data.query).map(([key, entry]) => (
+
+
+
+
+
+ {`${entry.name} `}
+
+
+
+
+
+
+
+
+ {/*
+ WARNING: You see that 'as any'? That's to forcefully disable typescript checking.
+ This is because 'right' does work as an align-items CSS properties as of time of writing,
+ but this may change in the future. If shit breaks, remove it and find another hack
+ to align the items.
+ */}
+
+ {
+ let mutated = options;
+ mutated[key] = val;
+ setOptions(mutated);
+ }} />
+
+
+
+ ))}
+
+
+
+
+
+
+
+ act('submit', { choices: preprocessOptions(options, data.query) })} />
+
+
+ act('cancel')} />
+
+
+
+
+
+
+
+ );
+};
+
+const preprocessOptions = (picked: Record, query: Record) => {
+ let built = {};
+ for (let key in Object.keys(query)) {
+ built[key] = picked[key] === undefined? query[key].default : picked[key];
+ }
+ return built;
+};
+
+interface DynamicEntryProps {
+ // eslint-disable-next-line react/no-unused-prop-types
+ id: string;
+ entry: UIDynamicInputEntry;
+ current: UIDynamicInputOption;
+ pick: (val: any) => void;
+}
+
+const DynamicEntry = (props: DynamicEntryProps, context) => {
+ switch (props.entry.type) {
+ case UIDynamicInputType.ListSingle:
+ return (
+
+ );
+ case UIDynamicInputType.Number:
+ return (
+
+ );
+ case UIDynamicInputType.String:
+ return (
+
+ );
+ case UIDynamicInputType.Toggle:
+ return (
+
+ );
+ }
+};
+
+interface DynamicEntryNumberProps extends DynamicEntryProps {
+ entry: NumberEntry;
+ current: NumberOption;
+}
+
+const DynamicEntryNumber = (props: DynamicEntryNumberProps, context) => {
+ let current = props.current === undefined? props.entry.default === null? 0 : props.entry.default : props.current;
+ return (
+ props.pick(
+ props.entry.constraints[2] === null? val : round(val, props.entry.constraints[2])
+ )} width="100%" />
+ );
+};
+
+interface DynamicEntryStringProps extends DynamicEntryProps {
+ entry: StringEntry;
+ current: StringOption;
+}
+
+const DynamicEntryString = (props: DynamicEntryStringProps, context) => {
+ let current = props.current === undefined? props.entry.default === null? "" : props.entry.default : props.current;
+ return (
+ props.pick(
+ val
+ )} width="100%" />
+ );
+};
+
+interface DynamicEntryPickProps extends DynamicEntryProps {
+ entry: PickEntry;
+ current: ListOption;
+}
+
+const DynamicEntryPick = (props: DynamicEntryPickProps, context) => {
+ let current = props.current === undefined? (
+ props.entry.constraints.length > 0? props.entry.constraints[0] : ""
+ ) : props.current;
+ return (
+ props.pick(v)} />
+ );
+};
+
+interface DynamicEntryToggleProps extends DynamicEntryProps {
+ entry: ToggleEntry;
+ current: ToggleOption;
+}
+
+const DynamicEntryToggle = (props: DynamicEntryToggleProps, context) => {
+ let current = props.current === undefined? !!props.entry.default : props.current;
+ return (
+ props.pick(!current)} />
+ );
+};
+
+