Javascript loaded, stylesheets has failed to load.
diff --git a/README.md b/README.md
index 5218aca790e..67d5b8718e7 100644
--- a/README.md
+++ b/README.md
@@ -81,6 +81,18 @@ For a basic setup, simply copy every file from config/example to config.
For more advanced setups, setting the server `tick_lag` in the config as well as configuring SQL are good first steps.
+
+#### Permissions
+
+Permissions with file-based config are handled through `admin_ranks.json`
+and `admins.txt`. To add yourself as the admin, simply find the rank with
+the suitable permissions from the `admin_ranks.json` file, copy its `"name"`
+field value, and input that into `admins.txt` like so:
+
+```cfg
+myckeyhere - Head Admin/Dev
+```
+
---
### SQL Setup
diff --git a/SQL/migrate/V061__custom_items_database.sql b/SQL/migrate/V061__custom_items_database.sql
new file mode 100644
index 00000000000..c33dd2d543f
--- /dev/null
+++ b/SQL/migrate/V061__custom_items_database.sql
@@ -0,0 +1,19 @@
+--
+-- Implemented in PR TODO.
+-- Adds a `ss13_characters_custom_items` table to replace the old custom item system.
+--
+
+CREATE TABLE `ss13_characters_custom_items` (
+ `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
+ `char_id` INT(11) NOT NULL,
+ `item_path` VARCHAR(255) NOT NULL COLLATE 'utf8mb4_unicode_ci',
+ `item_data` LONGTEXT NOT NULL COLLATE 'utf8mb4_bin',
+ `req_titles` LONGTEXT NULL DEFAULT NULL COLLATE 'utf8mb4_bin',
+ `additional_data` VARCHAR(255) NULL DEFAULT NULL COLLATE 'utf8mb4_unicode_ci',
+ PRIMARY KEY (`id`) USING BTREE,
+ INDEX `FK_ss13_characters_custom_items_ss13_characters` (`char_id`) USING BTREE,
+ CONSTRAINT `FK_ss13_characters_custom_items_ss13_characters` FOREIGN KEY (`char_id`) REFERENCES `ss13_characters` (`id`) ON UPDATE CASCADE ON DELETE CASCADE
+)
+COLLATE='utf8mb4_unicode_ci'
+ENGINE=InnoDB
+;
diff --git a/SQL/migrate/V062__hair_gradient_styles.sql b/SQL/migrate/V062__hair_gradient_styles.sql
new file mode 100644
index 00000000000..4c992c47f68
--- /dev/null
+++ b/SQL/migrate/V062__hair_gradient_styles.sql
@@ -0,0 +1,8 @@
+--
+-- Implemented in PR #10718.
+-- Adds a `Hair Gradient Style and Hair Gradient Color` columns for hair gradient preferences.
+--
+
+ALTER TABLE `ss13_characters`
+ ADD COLUMN `grad_colour` varchar(7) DEFAULT NULL AFTER `facial_colour`,
+ ADD COLUMN `gradient_style` varchar(32) DEFAULT NULL AFTER `facial_style`;
diff --git a/aurorastation.dme b/aurorastation.dme
index ce2ef797b85..515cd04bd48 100644
--- a/aurorastation.dme
+++ b/aurorastation.dme
@@ -1183,7 +1183,6 @@
#include "code\modules\admin\verbs\bluespacetech.dm"
#include "code\modules\admin\verbs\BrokenInhands.dm"
#include "code\modules\admin\verbs\buildmode.dm"
-#include "code\modules\admin\verbs\check_customitem_activity.dm"
#include "code\modules\admin\verbs\cinematic.dm"
#include "code\modules\admin\verbs\clear_toxins.dm"
#include "code\modules\admin\verbs\custom_event.dm"
@@ -1378,6 +1377,7 @@
#include "code\modules\clothing\factions\gadpathur.dm"
#include "code\modules\clothing\factions\goldendeep.dm"
#include "code\modules\clothing\factions\himeo.dm"
+#include "code\modules\clothing\factions\idris.dm"
#include "code\modules\clothing\factions\konyang.dm"
#include "code\modules\clothing\factions\vysoka.dm"
#include "code\modules\clothing\glasses\glasses.dm"
@@ -1661,6 +1661,7 @@
#include "code\modules\heavy_vehicle\mech_construction.dm"
#include "code\modules\heavy_vehicle\mech_damage.dm"
#include "code\modules\heavy_vehicle\mech_damage_immunity.dm"
+#include "code\modules\heavy_vehicle\mech_helpers.dm"
#include "code\modules\heavy_vehicle\mech_icon.dm"
#include "code\modules\heavy_vehicle\mech_interaction.dm"
#include "code\modules\heavy_vehicle\mech_life.dm"
diff --git a/code/__defines/chemistry.dm b/code/__defines/chemistry.dm
index 1044033e0d4..887ee9cf3f7 100644
--- a/code/__defines/chemistry.dm
+++ b/code/__defines/chemistry.dm
@@ -75,6 +75,7 @@
#define CE_BLOODRESTORE "bloodrestore" // Iron/nutriment
#define CE_BRAIN_REGEN "brainfix" // Alkysine
#define CE_OXYGENATED "oxygenated" // Dexalin
+#define CE_BLOODCLOT "bloodclot" // Coagzolug
// Deal damage
#define CE_BREATHLOSS "breathloss"
diff --git a/code/__defines/items_clothing.dm b/code/__defines/items_clothing.dm
index 7e165d6c6a7..a7b6e91ab43 100644
--- a/code/__defines/items_clothing.dm
+++ b/code/__defines/items_clothing.dm
@@ -38,6 +38,7 @@
#define BLOCK_GAS_SMOKE_EFFECT 0x10 // Blocks the effect that chemical clouds would have on a mob -- glasses, mask and helmets ONLY! (NOTE: flag shared with ONESIZEFITSALL)
#define FLEXIBLEMATERIAL 0x20 // At the moment, masks with this flag will not prevent eating even if they are covering your face.
#define SOUNDPROTECTION 0x40 // whether wearing this item will protect you from loud noises such as flashbangs | this only works for ear slots or the head slot
+#define LIGHTSTEP 0x80 // When applied to footwear, this makes it so that they don't trigger things like landmines and mouse traps
// Flags for pass_flags.
#define PASSTABLE 0x1
diff --git a/code/_helpers/global_lists.dm b/code/_helpers/global_lists.dm
index e7b1a208cdd..cd3e8c5386c 100644
--- a/code/_helpers/global_lists.dm
+++ b/code/_helpers/global_lists.dm
@@ -49,6 +49,7 @@ var/list/obj/item/device/uplink/world_uplinks = list()
var/global/list/hair_styles_list = list() //stores /datum/sprite_accessory/hair indexed by name
var/global/list/hair_styles_male_list = list()
var/global/list/hair_styles_female_list = list()
+var/global/list/hair_gradient_styles_list = list()
var/global/list/facial_hair_styles_list = list() //stores /datum/sprite_accessory/facial_hair indexed by name
var/global/list/facial_hair_styles_male_list = list()
var/global/list/facial_hair_styles_female_list = list()
@@ -105,6 +106,14 @@ var/global/list/cloaking_devices = list()
sortTim(hair_styles_male_list, /proc/cmp_text_asc)
sortTim(hair_styles_female_list, /proc/cmp_text_asc)
+ //Gradients - Initialise all /datum/sprite_accessory/hair_gradients into an list indexed by hairgradient-style name
+ paths = subtypesof(/datum/sprite_accessory/hair_gradients)
+ for(var/path in paths)
+ var/datum/sprite_accessory/hair_gradients/H = new path()
+ hair_gradient_styles_list[H.name] = H
+
+ sortTim(hair_gradient_styles_list, /proc/cmp_text_asc)
+
//Facial Hair - Initialise all /datum/sprite_accessory/facial_hair into an list indexed by facialhair-style name
paths = subtypesof(/datum/sprite_accessory/facial_hair)
for(var/path in paths)
diff --git a/code/_onclick/hud/_defines.dm b/code/_onclick/hud/_defines.dm
index 0a2e73c5383..5c3b3f1d5cd 100644
--- a/code/_onclick/hud/_defines.dm
+++ b/code/_onclick/hud/_defines.dm
@@ -78,6 +78,7 @@
#define ui_fire "EAST-1:28,NORTH-3:25"
#define ui_oxygen "EAST-1:28,NORTH-4:23"
#define ui_pressure "EAST-1:28,NORTH-5:21"
+#define ui_paralysis "EAST-1:28,NORTH-10:23"
#define ui_alien_toxin "EAST-1:28,NORTH-2:25"
#define ui_alien_fire "EAST-1:28,NORTH-3:25"
diff --git a/code/_onclick/hud/action.dm b/code/_onclick/hud/action.dm
index 712728aa861..4498c7406f1 100644
--- a/code/_onclick/hud/action.dm
+++ b/code/_onclick/hud/action.dm
@@ -22,6 +22,7 @@
var/obj/screen/movable/action_button/button = null
var/button_icon = 'icons/obj/action_buttons/actions.dmi'
var/button_icon_state = "default"
+ var/button_icon_color
var/background_icon_state = "bg_default"
var/mob/living/owner
@@ -146,6 +147,8 @@
img = image(owner.button_icon,src,owner.button_icon_state)
img.pixel_x = 0
img.pixel_y = 0
+ if(owner.button_icon_color)
+ img.color = owner.button_icon_color
add_overlay(img)
if(!owner.IsAvailable())
diff --git a/code/_onclick/hud/human.dm b/code/_onclick/hud/human.dm
index e2363e3ba66..f14a04ba887 100644
--- a/code/_onclick/hud/human.dm
+++ b/code/_onclick/hud/human.dm
@@ -270,6 +270,13 @@
mymob.fire.screen_loc = ui_fire
hud_elements |= mymob.fire
+ mymob.paralysis_indicator = new /obj/screen/paralysis()
+ mymob.paralysis_indicator.icon = 'icons/mob/status_indicators.dmi'
+ mymob.paralysis_indicator.icon_state = "paralysis0"
+ mymob.paralysis_indicator.name = "paralysis"
+ mymob.paralysis_indicator.screen_loc = ui_paralysis
+ hud_elements |= mymob.paralysis_indicator
+
mymob.healths = new /obj/screen()
mymob.healths.icon = ui_style
mymob.healths.icon_state = "health0"
@@ -484,4 +491,11 @@
if(icon_state == "oxy0")
to_chat(usr, SPAN_NOTICE("You are breathing easy."))
else
- to_chat(usr, SPAN_DANGER("You cannot breathe!"))
\ No newline at end of file
+ to_chat(usr, SPAN_DANGER("You cannot breathe!"))
+
+/obj/screen/paralysis/Click(var/location, var/control, var/params)
+ if(istype(usr) && usr.paralysis_indicator == src)
+ if(usr.paralysis)
+ to_chat(usr, SPAN_WARNING("You are completely paralyzed and cannot move!"))
+ else
+ to_chat(usr, SPAN_NOTICE("You are walking around completely fine."))
\ No newline at end of file
diff --git a/code/controllers/subsystems/economy.dm b/code/controllers/subsystems/economy.dm
index 40cdf948bb4..e4cbd716293 100644
--- a/code/controllers/subsystems/economy.dm
+++ b/code/controllers/subsystems/economy.dm
@@ -24,9 +24,8 @@ var/datum/controller/subsystem/economy/SSeconomy
create_station_account()
- for(var/department in station_departments)
- create_department_account(department)
- create_department_account("Vendor")
+ for(var/account in department_funds)
+ create_department_account(account)
..()
@@ -77,7 +76,7 @@ var/datum/controller/subsystem/economy/SSeconomy
department_account.account_number = next_account_number
next_account_number += rand(1,500)
department_account.remote_access_pin = rand(1111, 111111)
- department_account.money = 5000
+ department_account.money = department_funds[department]
//create an entry in the account transaction log for when it was created
var/datum/transaction/T = new()
diff --git a/code/controllers/subsystems/ticker.dm b/code/controllers/subsystems/ticker.dm
index f510921ff21..8b12065122f 100644
--- a/code/controllers/subsystems/ticker.dm
+++ b/code/controllers/subsystems/ticker.dm
@@ -363,6 +363,7 @@ var/datum/controller/subsystem/ticker/SSticker
to_world("Welcome to the pre-game lobby!")
to_world("Please, setup your character and select ready. Game will start in [pregame_timeleft] seconds.")
+ callHook("pregame_start")
/datum/controller/subsystem/ticker/proc/setup()
//Create and announce mode
diff --git a/code/game/atoms_movable.dm b/code/game/atoms_movable.dm
index be1b9db2254..4b9942f1dae 100644
--- a/code/game/atoms_movable.dm
+++ b/code/game/atoms_movable.dm
@@ -365,4 +365,7 @@
M.Turn(pick(-30, 30))
animate(I, alpha = 175, pixel_x = to_x, pixel_y = to_y, time = 3, transform = M, easing = CUBIC_EASING)
sleep(1)
- animate(I, alpha = 0, transform = matrix(), time = 1)
\ No newline at end of file
+ animate(I, alpha = 0, transform = matrix(), time = 1)
+
+/atom/movable/proc/get_floating_chat_x_offset()
+ return 0
\ No newline at end of file
diff --git a/code/game/machinery/CableLayer.dm b/code/game/machinery/CableLayer.dm
index 112b469beae..5016f871fa6 100644
--- a/code/game/machinery/CableLayer.dm
+++ b/code/game/machinery/CableLayer.dm
@@ -12,42 +12,49 @@
/obj/machinery/cablelayer/Initialize()
. = ..()
cable = new(src)
- cable.amount = 100
+ cable.amount = max_cable
/obj/machinery/cablelayer/Move(new_turf,M_Dir)
..()
- layCable(new_turf,M_Dir)
+ if(on)
+ layCable(new_turf,M_Dir)
-/obj/machinery/cablelayer/attack_hand(mob/user as mob)
- if(!cable&&!on)
- to_chat(user, "\The [src] doesn't have any cable loaded.")
+/obj/machinery/cablelayer/attack_hand(mob/user)
+ if(!cable && !on)
+ to_chat(user, SPAN_WARNING("\The [src] doesn't have any cable loaded."))
return
- on=!on
- user.visible_message("\The [user] [!on?"dea":"a"]ctivates \the [src].", "You switch [src] [on? "on" : "off"]")
+ on = !on
+ user.visible_message("\The [user] [!on ? "de" : ""]activates \the [src].", SPAN_NOTICE("You switch \the [src] [on ? "on" : "off"]."))
return
-/obj/machinery/cablelayer/attackby(var/obj/item/O as obj, var/mob/user as mob)
+/obj/machinery/cablelayer/attackby(var/obj/item/O, var/mob/user)
if(O.iscoil())
-
var/result = load_cable(O)
if(!result)
- to_chat(user, "\The [src]'s cable reel is full.")
+ to_chat(user, SPAN_WARNING("\The [src]'s cable reel is full."))
else
- to_chat(user, "You load [result] lengths of cable into [src].")
+ to_chat(user, SPAN_NOTICE("You load [result] lengths of cable into \the [src]."))
return
if(O.iswirecutter())
if(cable && cable.amount)
- var/m = round(input(usr,"Please specify the length of cable to cut","Cut cable",min(cable.amount,30)) as num, 1)
+ var/m = round(input(usr,"Please specify the length of cable to cut.", "Cut Cable",min(cable.amount,30)) as num, 1)
m = min(m, cable.amount)
m = min(m, 30)
if(m)
playsound(loc, 'sound/items/wirecutter.ogg', 50, 1)
- use_cable(m)
- var/obj/item/stack/cable_coil/CC = new (get_turf(src))
- CC.amount = m
+ var/cable_color = use_cable(m)
+ var/obj/item/stack/cable_coil/CC = new(get_turf(src), m, cable_color)
+ user.put_in_hands(CC)
else
- to_chat(usr, "There's no more cable on the reel.")
+ to_chat(user, SPAN_WARNING("There's no more cable on the reel."))
+ return
+
+ if(O.ismultitool())
+ if(!cable)
+ to_chat(user, SPAN_WARNING("\The [src] doesn't have any cable loaded!"))
+ return
+ cable.attackby(O, user)
/obj/machinery/cablelayer/examine(mob/user)
..()
@@ -60,49 +67,43 @@
if(to_load)
to_load = min(CC.amount, to_load)
if(!cable)
- cable = new(src)
- cable.amount = 0
- cable.amount += to_load
+ cable = new(src, 0, CC.color)
+ cable.amount = to_load
CC.use(to_load)
return to_load
else
- return 0
- return
+ return FALSE
/obj/machinery/cablelayer/proc/use_cable(amount)
- if(!cable || cable.amount<1)
- visible_message("A red light flashes on \the [src].")
+ if(!cable || cable.amount < 1)
+ on = FALSE
+ reset()
+ playsound(loc, 'sound/machines/buzz-sigh.ogg', 50, TRUE)
+ visible_message(SPAN_WARNING("A red light flashes on \the [src]."))
return
+ var/cable_color = cable.color
cable.use(amount)
if(QDELETED(cable))
cable = null
- return 1
+ return cable_color
/obj/machinery/cablelayer/proc/reset()
last_piece = null
-/obj/machinery/cablelayer/proc/dismantleFloor(var/turf/new_turf)
- if(istype(new_turf, /turf/simulated/floor))
- var/turf/simulated/floor/T = new_turf
- if(!T.is_plating())
- T.make_plating(!(T.broken || T.burnt))
- return new_turf.is_plating()
-
/obj/machinery/cablelayer/proc/layCable(var/turf/new_turf,var/M_Dir)
- if(!on)
+ if(!istype(new_turf))
return reset()
- else
- dismantleFloor(new_turf)
- if(!istype(new_turf) || !dismantleFloor(new_turf))
+ if(!new_turf.is_plating())
return reset()
var/fdirn = turn(M_Dir,180)
for(var/obj/structure/cable/LC in new_turf) // check to make sure there's not a cable there already
if(LC.d1 == fdirn || LC.d2 == fdirn)
return reset()
- if(!use_cable(1))
+ var/cable_color = use_cable(1)
+ if(!cable_color)
return reset()
var/obj/structure/cable/NC = new(new_turf)
- NC.cableColor("red")
+ NC.cableColor(cable_color)
NC.d1 = 0
NC.d2 = fdirn
NC.update_icon()
@@ -119,6 +120,5 @@
PN.add_cable(NC)
NC.mergeConnectedNetworks(NC.d2)
- //NC.mergeConnectedNetworksOnTurf()
last_piece = NC
- return 1
+ return TRUE
\ No newline at end of file
diff --git a/code/game/machinery/body_scanner.dm b/code/game/machinery/body_scanner.dm
index 8d19315ae8b..6b2b41ca9c2 100644
--- a/code/game/machinery/body_scanner.dm
+++ b/code/game/machinery/body_scanner.dm
@@ -306,7 +306,8 @@
for(var/obj/machinery/bodyscanner/C in orange(1,src))
connected = C
break
- connected.connected = src
+ if(connected)
+ connected.connected = src
update_icon()
/obj/machinery/body_scanconsole/attack_ai(var/mob/user)
diff --git a/code/game/machinery/mech_recharger.dm b/code/game/machinery/mech_recharger.dm
index 377497acde6..9468ffadf10 100644
--- a/code/game/machinery/mech_recharger.dm
+++ b/code/game/machinery/mech_recharger.dm
@@ -110,4 +110,22 @@
/obj/machinery/mech_recharger/proc/stop_charging()
update_use_power(1)
- charging = null
\ No newline at end of file
+ charging = null
+
+
+/obj/machinery/mech_recharger/hephaestus
+ name = "hephaestus exosuit dock"
+ desc = "A massive vehicle dock elevated slightly above the ground, constructed for equally massive charging speeds."
+ icon_state = "supermechcharger"
+ idle_power_usage = 400
+ active_power_usage = 120 KILOWATTS
+
+ base_charge_rate = 120 KILOWATTS
+ repair = 1
+
+ component_types = list(
+ /obj/item/circuitboard/mech_recharger/hephaestus,
+ /obj/item/stock_parts/capacitor = 3,
+ /obj/item/stock_parts/scanning_module = 2,
+ /obj/item/stock_parts/manipulator = 3
+ )
diff --git a/code/game/objects/effects/decals/Cleanable/humans.dm b/code/game/objects/effects/decals/Cleanable/humans.dm
index a3a9de78022..c39a791fd32 100644
--- a/code/game/objects/effects/decals/Cleanable/humans.dm
+++ b/code/game/objects/effects/decals/Cleanable/humans.dm
@@ -83,6 +83,8 @@
if(perp.shoes && !perp.buckled)//Adding blood to shoes
var/obj/item/clothing/shoes/S = perp.shoes
if(istype(S))
+ if(S.item_flags & LIGHTSTEP)
+ return
S.blood_color = basecolor
S.track_footprint = max(amount, S.track_footprint)
if(!S.blood_overlay)
diff --git a/code/game/objects/items/devices/scanners.dm b/code/game/objects/items/devices/scanners.dm
index 80cae247231..f97ee9dfeed 100644
--- a/code/game/objects/items/devices/scanners.dm
+++ b/code/game/objects/items/devices/scanners.dm
@@ -625,3 +625,78 @@ BREATH ANALYZER
++unknown
if(unknown)
to_chat(user,"Non-medical reagent[(unknown > 1)?"s":""] found in subject's respitory system.")
+
+
+/obj/item/device/advanced_healthanalyzer
+ name = "zeng-hu body analyzer"
+ desc = "An expensive and varied-use health analyzer that prints full-body scans after a short scanning delay."
+ icon_state = "zh-analyzer"
+ item_state = "healthanalyzer"
+ slot_flags = SLOT_BELT
+ w_class = ITEMSIZE_NORMAL
+ origin_tech = list(TECH_MAGNET = 2, TECH_BIO = 3)
+ var/obj/machinery/body_scanconsole/internal_bodyscanner = null //this is used to print the date and to deal with extra
+
+/obj/item/device/advanced_healthanalyzer/Initialize()
+ . = ..()
+ if(!internal_bodyscanner)
+ var/obj/machinery/body_scanconsole/S = new (src)
+ S.forceMove(src)
+ S.use_power = FALSE
+ internal_bodyscanner = S
+
+/obj/item/device/advanced_healthanalyzer/Destroy()
+ if(internal_bodyscanner)
+ QDEL_NULL(internal_bodyscanner)
+ return ..()
+
+/obj/item/device/advanced_healthanalyzer/attack(mob/living/M, mob/living/user)
+ if(!internal_bodyscanner)
+ return
+ if(do_after(user, 7 SECONDS, TRUE))
+ print_scan(M, user)
+ add_fingerprint(user)
+
+/obj/item/device/advanced_healthanalyzer/proc/print_scan(var/mob/M, var/mob/living/user)
+ var/obj/item/paper/R = new(user.loc)
+ R.color = "#eeffe8"
+ R.set_content_unsafe("Scan ([M.name])", internal_bodyscanner.format_occupant_data(get_medical_data(M)))
+
+ if(ishuman(user) && !(user.l_hand && user.r_hand))
+ user.put_in_hands(R)
+ user.visible_message("\The [src] spits out a piece of paper.")
+
+/obj/item/device/advanced_healthanalyzer/proc/get_medical_data(var/mob/living/carbon/human/H)
+ if (!ishuman(H))
+ return
+
+ var/list/medical_data = list(
+ "stationtime" = worldtime2text(),
+ "brain_activity" = H.get_brain_status(),
+ "blood_volume" = H.get_blood_volume(),
+ "blood_oxygenation" = H.get_blood_oxygenation(),
+ "blood_pressure" = H.get_blood_pressure(),
+
+ "bruteloss" = get_severity(H.getBruteLoss(), TRUE),
+ "fireloss" = get_severity(H.getFireLoss(), TRUE),
+ "oxyloss" = get_severity(H.getOxyLoss(), TRUE),
+ "toxloss" = get_severity(H.getToxLoss(), TRUE),
+ "cloneloss" = get_severity(H.getCloneLoss(), TRUE),
+
+ "rads" = H.total_radiation,
+ "paralysis" = H.paralysis,
+ "bodytemp" = H.bodytemperature,
+ "borer_present" = H.has_brain_worms(),
+ "inaprovaline_amount" = H.reagents.get_reagent_amount(/datum/reagent/inaprovaline),
+ "dexalin_amount" = H.reagents.get_reagent_amount(/datum/reagent/dexalin),
+ "stoxin_amount" = H.reagents.get_reagent_amount(/datum/reagent/soporific),
+ "bicaridine_amount" = H.reagents.get_reagent_amount(/datum/reagent/bicaridine),
+ "dermaline_amount" = H.reagents.get_reagent_amount(/datum/reagent/dermaline),
+ "blood_amount" = H.vessel.get_reagent_amount(/datum/reagent/blood),
+ "disabilities" = H.sdisabilities,
+ "lung_ruptured" = H.is_lung_ruptured(),
+ "external_organs" = H.organs.Copy(),
+ "internal_organs" = H.internal_organs.Copy(),
+ "species_organs" = H.species.has_organ
+ )
+ return medical_data
diff --git a/code/game/objects/items/glassjar.dm b/code/game/objects/items/glassjar.dm
index 8db7ad4c609..acd82f78473 100644
--- a/code/game/objects/items/glassjar.dm
+++ b/code/game/objects/items/glassjar.dm
@@ -219,6 +219,8 @@
for(var/i = 1 to GUMBALL_MAX)
var/obj/item/clothing/mask/chewable/candy/gum/gumball/medical/G = new(src)
contained += G
+
+ return INITIALIZE_HINT_LATELOAD
#undef JAR_NOTHING
#undef JAR_MONEY
diff --git a/code/game/objects/items/toys.dm b/code/game/objects/items/toys.dm
index 542b646c1de..57190703374 100644
--- a/code/game/objects/items/toys.dm
+++ b/code/game/objects/items/toys.dm
@@ -503,7 +503,9 @@
/obj/item/toy/snappop/Crossed(H as mob|obj)
if((ishuman(H))) //i guess carp and shit shouldn't set them off
- var/mob/living/carbon/M = H
+ var/mob/living/carbon/human/M = H
+ if(M.shoes?.item_flags & LIGHTSTEP)
+ return
if(M.m_intent == M_RUN)
to_chat(M, SPAN_WARNING("You step on the snap pop!"))
do_pop()
diff --git a/code/game/objects/items/weapons/RFD.dm b/code/game/objects/items/weapons/RFD.dm
index ed8dd7180cc..6445b5e260f 100644
--- a/code/game/objects/items/weapons/RFD.dm
+++ b/code/game/objects/items/weapons/RFD.dm
@@ -336,6 +336,7 @@ RFD Construction-Class
/obj/item/rfd/construction/mounted/can_use(var/mob/user,var/turf/T)
return (user.Adjacent(T) && !user.stat && !user.restrained())
+
/*
RFD Service-Class
*/
diff --git a/code/game/objects/items/weapons/circuitboards/machinery/mech_recharger.dm b/code/game/objects/items/weapons/circuitboards/machinery/mech_recharger.dm
index a8614345b91..9d226321301 100644
--- a/code/game/objects/items/weapons/circuitboards/machinery/mech_recharger.dm
+++ b/code/game/objects/items/weapons/circuitboards/machinery/mech_recharger.dm
@@ -1,5 +1,5 @@
#ifndef T_BOARD
-#error T_BOARD macro is not defined but we need it!
+#error T_BOARD macro is not defined but we need it!
#endif
/obj/item/circuitboard/mech_recharger
@@ -10,4 +10,13 @@
req_components = list(
"/obj/item/stock_parts/capacitor" = 2,
"/obj/item/stock_parts/scanning_module" = 1,
- "/obj/item/stock_parts/manipulator" = 2)
\ No newline at end of file
+ "/obj/item/stock_parts/manipulator" = 2)
+
+/obj/item/circuitboard/mech_recharger/hephaestus
+ name = T_BOARD("hephaestus mech recharger")
+ build_path = /obj/machinery/mech_recharger/hephaestus
+ origin_tech = list(TECH_DATA = 2, TECH_POWER = 3, TECH_ENGINEERING = 3)
+ req_components = list(
+ "/obj/item/stock_parts/capacitor" = 3,
+ "/obj/item/stock_parts/scanning_module" = 2,
+ "/obj/item/stock_parts/manipulator" = 3)
\ No newline at end of file
diff --git a/code/game/objects/items/weapons/landmines.dm b/code/game/objects/items/weapons/landmines.dm
index d4a674ef475..420e9223839 100644
--- a/code/game/objects/items/weapons/landmines.dm
+++ b/code/game/objects/items/weapons/landmines.dm
@@ -57,6 +57,11 @@
/obj/item/landmine/Crossed(AM as mob|obj)
if(deployed)
+ if(ishuman(AM))
+ var/mob/living/carbon/human/H = AM
+ if(H.shoes?.item_flags & LIGHTSTEP)
+ ..()
+ return
if(isliving(AM))
var/mob/living/L = AM
if(L.mob_size >= 5)
diff --git a/code/game/objects/items/weapons/material/caltrops.dm b/code/game/objects/items/weapons/material/caltrops.dm
index 55724b94202..02b7d5b590d 100644
--- a/code/game/objects/items/weapons/material/caltrops.dm
+++ b/code/game/objects/items/weapons/material/caltrops.dm
@@ -22,9 +22,10 @@
var/damage_coef = 1
if(H.buckled)
return
-
if(H.resting)
return
+ if(H.shoes?.item_flags & LIGHTSTEP)
+ return
to_chat(H, SPAN_DANGER("You step on \the [src]!"))
playsound(get_turf(src), 'sound/effects/glass_step.ogg', 50, TRUE)
diff --git a/code/game/objects/items/weapons/material/misc.dm b/code/game/objects/items/weapons/material/misc.dm
index 4d560dd94ab..9e0cb3e7d79 100644
--- a/code/game/objects/items/weapons/material/misc.dm
+++ b/code/game/objects/items/weapons/material/misc.dm
@@ -82,6 +82,7 @@
)
sharp = 1
edge = 1
+ force_divisor = 0.25
/obj/item/material/minihoe // -- Numbers
name = "mini hoe"
diff --git a/code/game/objects/items/weapons/policetape.dm b/code/game/objects/items/weapons/policetape.dm
index f3ec465eaaf..4606c4c6390 100644
--- a/code/game/objects/items/weapons/policetape.dm
+++ b/code/game/objects/items/weapons/policetape.dm
@@ -71,8 +71,26 @@ var/list/tape_roll_applications = list()
/obj/item/tape/engineering
name = "engineering tape"
desc = "A length of engineering tape. Better not cross it."
- req_one_access = list(access_engine,access_atmospherics)
+ desc_info = "You can use a multitool on this tape to allow emergency shield generators to deploy shields on this tile."
+ req_one_access = list(access_engine, access_atmospherics)
icon_base = "engineering"
+ var/shield_marker = FALSE
+
+/obj/item/tape/engineering/examine(mob/user, distance)
+ . = ..()
+ if(shield_marker)
+ to_chat(user, SPAN_NOTICE("This strip of tape has been modified to serve as a marker for emergency shield generators to lock onto."))
+
+/obj/item/tape/engineering/attackby(obj/item/W, mob/user)
+ if(W.ismultitool())
+ shield_marker = !shield_marker
+ to_chat(user, SPAN_NOTICE("You [shield_marker ? "" : "un"]designate \the [src] as a target for an emergency shield generator."))
+ if(shield_marker)
+ animate(src, 1 SECOND, color = color_rotation(-60))
+ else
+ animate(src, 1 SECOND, color = initial(color))
+ return
+ return ..()
/obj/item/taperoll/attack_self(mob/user as mob)
if(icon_state == "[icon_base]_start")
diff --git a/code/game/objects/items/weapons/soap.dm b/code/game/objects/items/weapons/soap.dm
index b970d36e985..68450cb9aea 100644
--- a/code/game/objects/items/weapons/soap.dm
+++ b/code/game/objects/items/weapons/soap.dm
@@ -47,7 +47,11 @@
overlays += image('icons/obj/items.dmi', icon_state = "soap_key_overlay")
/obj/item/soap/Crossed(AM as mob|obj)
- if (istype(AM, /mob/living))
+ if(isliving(AM))
+ if(ishuman(AM))
+ var/mob/living/carbon/human/H = AM
+ if(H.shoes?.item_flags & LIGHTSTEP)
+ return
var/mob/living/M = AM
M.slip("the [src.name]",3)
diff --git a/code/game/objects/items/weapons/storage/backpack.dm b/code/game/objects/items/weapons/storage/backpack.dm
index fc6ef02a400..51453d59cc7 100644
--- a/code/game/objects/items/weapons/storage/backpack.dm
+++ b/code/game/objects/items/weapons/storage/backpack.dm
@@ -513,3 +513,20 @@
canremove = 0
species_restricted = list(BODYTYPE_VAURCA_BREEDER)
sprite_sheets = list(BODYTYPE_VAURCA_BREEDER = 'icons/mob/species/breeder/back.dmi')
+
+/obj/item/storage/backpack/service
+ name = "idris service backpack"
+ desc = "The infamously Idris Service Standard refers to this monstrous, self-stabilizing back-mounted utensil and service item holder, not anything professional."
+ icon_state = "idris_backpack"
+ storage_slots = 6
+ max_w_class = ITEMSIZE_LARGE
+ can_hold = list(
+ /obj/item/tray,
+ /obj/item/material/kitchen/utensil/fork,
+ /obj/item/material/kitchen/utensil/knife,
+ /obj/item/material/kitchen/utensil/spoon,
+ /obj/item/material/knife,
+ /obj/item/material/hatchet/butch,
+ /obj/item/reagent_containers/food/drinks/drinkingglass,
+ /obj/item/storage/toolbox/lunchbox/nt
+ )
\ No newline at end of file
diff --git a/code/game/objects/items/weapons/storage/firstaid.dm b/code/game/objects/items/weapons/storage/firstaid.dm
index c7b2bc27e81..cdb0ccd0019 100644
--- a/code/game/objects/items/weapons/storage/firstaid.dm
+++ b/code/game/objects/items/weapons/storage/firstaid.dm
@@ -137,7 +137,8 @@
starts_with = list(
/obj/item/stack/medical/bruise_pack = 2,
/obj/item/stack/medical/advanced/bruise_pack = 2,
- /obj/item/reagent_containers/pill/bicaridine = 2,
+ /obj/item/reagent_containers/pill/bicaridine = 1,
+ /obj/item/reagent_containers/hypospray/autoinjector/coagzolug = 1,
/obj/item/device/healthanalyzer = 1
)
diff --git a/code/game/objects/items/weapons/storage/internal.dm b/code/game/objects/items/weapons/storage/internal.dm
index 6d06d886c09..fd1dd16c733 100644
--- a/code/game/objects/items/weapons/storage/internal.dm
+++ b/code/game/objects/items/weapons/storage/internal.dm
@@ -84,3 +84,16 @@
/obj/item/storage/internal/Adjacent(var/atom/neighbor)
return master_item.Adjacent(neighbor)
+
+/obj/item/storage/internal/skrell
+ name = "headtail storage"
+ icon = 'icons/obj/action_buttons/organs.dmi'
+ icon_state = "skrell_headpocket"
+ storage_slots = 1
+ max_storage_space = 2
+ max_w_class = ITEMSIZE_SMALL
+ use_sound = null
+
+/obj/item/storage/internal/skrell/Initialize()
+ . = ..()
+ name = initial(name)
\ No newline at end of file
diff --git a/code/game/objects/structures/crates_lockers/closets/secure/medical.dm b/code/game/objects/structures/crates_lockers/closets/secure/medical.dm
index c5263f700b7..700d6c2dd67 100644
--- a/code/game/objects/structures/crates_lockers/closets/secure/medical.dm
+++ b/code/game/objects/structures/crates_lockers/closets/secure/medical.dm
@@ -118,6 +118,7 @@
new /obj/item/storage/box/inhalers(src)
new /obj/item/clothing/glasses/hud/health/aviator(src)
new /obj/item/storage/box/fancy/keypouch/med(src)
+ new /obj/item/device/advanced_healthanalyzer(src)
/obj/structure/closet/secure_closet/CMO2
name = "chief medical officer's attire"
diff --git a/code/game/objects/structures/stool_bed_chair_nest/bed.dm b/code/game/objects/structures/stool_bed_chair_nest/bed.dm
index 1e47b651d3d..e3b83955d9e 100644
--- a/code/game/objects/structures/stool_bed_chair_nest/bed.dm
+++ b/code/game/objects/structures/stool_bed_chair_nest/bed.dm
@@ -82,6 +82,11 @@
desc += padding_material ? " It's made of [material.use_name] and covered with [padding_material.use_name]." : " It's made of [material.use_name]."
+/obj/structure/bed/forceMove(atom/dest)
+ . = ..()
+ if(buckled_mob)
+ buckled_mob.forceMove(dest)
+
/obj/structure/bed/CanPass(atom/movable/mover, turf/target, height=0, air_group=0)
if(istype(mover) && mover.checkpass(PASSTABLE))
return 1
diff --git a/code/global.dm b/code/global.dm
index a442f7ebfb3..8985488586d 100644
--- a/code/global.dm
+++ b/code/global.dm
@@ -146,7 +146,17 @@ var/max_explosion_range = 14
// Announcer intercom, because too much stuff creates an intercom for one message then hard del()s it.
var/global/obj/item/device/radio/intercom/global_announcer = new(null)
-var/list/station_departments = list("Command", "Medical", "Engineering", "Science", "Security", "Cargo", "Civilian")
+// the number next to it denotes how much money the department receives when its account is generated
+var/list/department_funds = list(
+ "Command" = 10000,
+ "Medical" = 10000,
+ "Engineering" = 10000,
+ "Science" = 10000,
+ "Security" = 10000,
+ "Cargo" = 5000,
+ "Civilian" = 10000,
+ "Vendor" = 0
+ )
//List of exosuit tracking beacons, to save performance
-var/global/list/exo_beacons = list()
+var/global/list/exo_beacons = list()
\ No newline at end of file
diff --git a/code/modules/admin/admin.dm b/code/modules/admin/admin.dm
index 0ede3b88592..ffd797bea64 100644
--- a/code/modules/admin/admin.dm
+++ b/code/modules/admin/admin.dm
@@ -1010,27 +1010,6 @@ proc/admin_notice(var/message, var/rights)
item_to_spawn.spawn_item(get_turf(usr))
-/datum/admins/proc/check_custom_items()
-
- set category = "Debug"
- set desc = "Check the custom item list."
- set name = "Check Custom Items"
-
- if(!check_rights(R_SPAWN)) return
-
- if(!custom_items)
- to_chat(usr, "Custom item list is null.")
- return
-
- if(!custom_items.len)
- to_chat(usr, "Custom item list not populated.")
- return
-
- for(var/assoc_key in custom_items)
- to_chat(usr, "[assoc_key] has:")
- var/list/current_items = custom_items[assoc_key]
- for(var/datum/custom_item/item in current_items)
- to_chat(usr, "- name: [item.name] icon: [item.item_icon] path: [item.item_path] desc: [item.item_desc]")
/datum/admins/proc/spawn_plant(seedtype in SSplants.seeds)
set category = "Debug"
diff --git a/code/modules/admin/admin_verbs.dm b/code/modules/admin/admin_verbs.dm
index b9ad8e67677..cf412ea740c 100644
--- a/code/modules/admin/admin_verbs.dm
+++ b/code/modules/admin/admin_verbs.dm
@@ -72,7 +72,6 @@ var/list/admin_verbs_admin = list(
/client/proc/toggleghostwriters,
/client/proc/toggledrones,
/datum/admins/proc/show_skills,
- /client/proc/check_customitem_activity,
/client/proc/man_up,
/client/proc/global_man_up,
/client/proc/response_team, // Response Teams admin verb,
@@ -145,7 +144,6 @@ var/list/admin_verbs_spawn = list(
/client/proc/game_panel,
/datum/admins/proc/spawn_fruit,
/datum/admins/proc/spawn_custom_item,
- /datum/admins/proc/check_custom_items,
/datum/admins/proc/spawn_plant,
/datum/admins/proc/spawn_atom, // allows us to spawn instances,
/client/proc/respawn_character,
@@ -171,7 +169,6 @@ var/list/admin_verbs_server = list(
/datum/admins/proc/toggle_round_spookyness,
/datum/admins/proc/toggle_space_ninja,
/client/proc/toggle_random_events,
- /client/proc/check_customitem_activity,
/client/proc/nanomapgen_DumpImage,
/client/proc/toggle_recursive_explosions,
/client/proc/restart_controller,
@@ -350,7 +347,6 @@ var/list/admin_verbs_hideable = list(
/datum/admins/proc/call_drop_pod,
/datum/admins/proc/spawn_fruit,
/datum/admins/proc/spawn_custom_item,
- /datum/admins/proc/check_custom_items,
/datum/admins/proc/spawn_plant,
/client/proc/show_plant_genes,
/datum/admins/proc/spawn_atom,
@@ -400,7 +396,6 @@ var/list/admin_verbs_hideable = list(
/client/proc/callproc,
/client/proc/callproc_target,
/client/proc/debug_controller,
- /client/proc/check_customitem_activity,
/client/proc/print_logout_report,
/client/proc/edit_admin_permissions,
/proc/possess,
diff --git a/code/modules/admin/topic.dm b/code/modules/admin/topic.dm
index a9b5e68d84a..683ff801313 100644
--- a/code/modules/admin/topic.dm
+++ b/code/modules/admin/topic.dm
@@ -1460,10 +1460,6 @@
src.admincaster_screen = 20
src.access_news_network()
- else if(href_list["populate_inactive_customitems"])
- if(check_rights(R_ADMIN|R_SERVER))
- populate_inactive_customitems_list(src.owner)
-
else if(href_list["vsc"])
if(check_rights(R_ADMIN|R_SERVER))
if(href_list["vsc"] == "airflow")
diff --git a/code/modules/admin/verbs/check_customitem_activity.dm b/code/modules/admin/verbs/check_customitem_activity.dm
deleted file mode 100644
index e9bbaded60b..00000000000
--- a/code/modules/admin/verbs/check_customitem_activity.dm
+++ /dev/null
@@ -1,85 +0,0 @@
-var/checked_for_inactives = 0
-var/inactive_keys = "None
"
-
-/client/proc/check_customitem_activity()
- set category = "Admin"
- set name = "Check activity of players with custom items"
-
- var/dat = "Inactive players with custom items
"
- dat += "
"
- dat += "The list below contains players with custom items that have not logged\
- in for the past two months, or have not logged in since this system was implemented.\
- This system requires the feedback SQL database to be properly setup and linked.
"
- dat += "
"
- dat += "Populating this list is done automatically, but must be manually triggered on a per\
- round basis. Populating the list may cause a lag spike, so use it sparingly.
"
- dat += "