diff --git a/code/__HELPERS/unsorted.dm b/code/__HELPERS/unsorted.dm
index 96306bc98e..9f2919cc9b 100644
--- a/code/__HELPERS/unsorted.dm
+++ b/code/__HELPERS/unsorted.dm
@@ -263,7 +263,7 @@ Turf and target are separate in case you want to teleport some distance from a t
return .
//Returns a list of all items of interest with their name
-/proc/getpois(mobs_only=0,skip_mindless=0)
+/proc/getpois(mobs_only = FALSE, skip_mindless = FALSE, specify_dead_role = TRUE)
var/list/mobs = sortmobs()
var/list/namecounts = list()
var/list/pois = list()
@@ -277,7 +277,7 @@ Turf and target are separate in case you want to teleport some distance from a t
if(M.real_name && M.real_name != M.name)
name += " \[[M.real_name]\]"
- if(M.stat == DEAD)
+ if(M.stat == DEAD && specify_dead_role)
if(isobserver(M))
name += " \[ghost\]"
else
diff --git a/code/datums/components/orbiter.dm b/code/datums/components/orbiter.dm
index 49b19f767c..26f52f6ba5 100644
--- a/code/datums/components/orbiter.dm
+++ b/code/datums/components/orbiter.dm
@@ -146,9 +146,11 @@
if(!istype(A) || !get_turf(A) || A == src)
return
+ orbit_target = A
return A.AddComponent(/datum/component/orbiter, src, radius, clockwise, rotation_speed, rotation_segments, pre_rotation)
/atom/movable/proc/stop_orbit(datum/component/orbiter/orbits)
+ orbit_target = null
return // We're just a simple hook
/atom/proc/transfer_observers_to(atom/target)
diff --git a/code/game/atoms.dm b/code/game/atoms.dm
index c453b4bb62..cd0c02a359 100644
--- a/code/game/atoms.dm
+++ b/code/game/atoms.dm
@@ -103,6 +103,9 @@
///Mobs that are currently do_after'ing this atom, to be cleared from on Destroy()
var/list/targeted_by
+ ///Reference to atom being orbited
+ var/atom/orbit_target
+
/**
* Called when an atom is created in byond (built in engine proc)
*
diff --git a/code/game/machinery/cell_charger.dm b/code/game/machinery/cell_charger.dm
index effd70e9ab..25445f0d1c 100644
--- a/code/game/machinery/cell_charger.dm
+++ b/code/game/machinery/cell_charger.dm
@@ -10,7 +10,7 @@
circuit = /obj/item/circuitboard/machine/cell_charger
pass_flags = PASSTABLE
var/obj/item/stock_parts/cell/charging = null
- var/charge_rate = 500
+ var/recharge_coeff = 1
/obj/machinery/cell_charger/update_overlays()
. += ..()
@@ -28,9 +28,10 @@
. = ..()
. += "There's [charging ? "a" : "no"] cell in the charger."
if(charging)
- . += "Current charge: [round(charging.percent(), 1)]%."
+ var/obj/item/stock_parts/cell/C = charging.get_cell()
+ . += "Current charge: [C.percent()]%."
if(in_range(user, src) || isobserver(user))
- . += "The status display reads: Charge rate at [charge_rate]J per cycle."
+ . += "The status display reads: Charge rate at [recharge_coeff*10]J per cycle."
/obj/machinery/cell_charger/attackby(obj/item/W, mob/user, params)
if(istype(W, /obj/item/stock_parts/cell) && !panel_open)
@@ -122,17 +123,18 @@
charging.emp_act(severity)
/obj/machinery/cell_charger/RefreshParts()
- charge_rate = 500
for(var/obj/item/stock_parts/capacitor/C in component_parts)
- charge_rate *= C.rating
+ recharge_coeff = C.rating
/obj/machinery/cell_charger/process()
if(!charging || !anchored || (stat & (BROKEN|NOPOWER)))
return
- if(charging.percent() >= 100)
- return
- use_power(charge_rate)
- charging.give(charge_rate) //this is 2558, efficient batteries exist
+ if(charging)
+ var/obj/item/stock_parts/cell/C = charging.get_cell()
+ if(C)
+ if(C.charge < C.maxcharge)
+ C.give(C.chargerate * recharge_coeff)
+ use_power(250 * recharge_coeff)
update_icon()
diff --git a/code/modules/integrated_electronics/subtypes/weaponized.dm b/code/modules/integrated_electronics/subtypes/weaponized.dm
index 96a732d08f..25fa7058fb 100644
--- a/code/modules/integrated_electronics/subtypes/weaponized.dm
+++ b/code/modules/integrated_electronics/subtypes/weaponized.dm
@@ -137,6 +137,10 @@
//Shooting Code:
A.preparePixelProjectile(target, src)
A.fire()
+ if(ismob(loc.loc))
+ installed_gun.shoot_live_shot(loc.loc)
+ else
+ installed_gun.shoot_live_shot() //Shitcode, but we don't have much of a choice
log_attack("[assembly] [REF(assembly)] has fired [installed_gun].")
return A
diff --git a/code/modules/mining/lavaland/necropolis_chests.dm b/code/modules/mining/lavaland/necropolis_chests.dm
index 600a862ebf..256dc958d4 100644
--- a/code/modules/mining/lavaland/necropolis_chests.dm
+++ b/code/modules/mining/lavaland/necropolis_chests.dm
@@ -522,7 +522,7 @@
max_charges = 1
item_flags = NEEDS_PERMIT | NOBLUDGEON
w_class = WEIGHT_CLASS_BULKY
- force = 18
+ force = 15
/obj/item/ammo_casing/magic/hook
name = "hook"
@@ -536,11 +536,11 @@
icon_state = "hook"
icon = 'icons/obj/lavaland/artefacts.dmi'
pass_flags = PASSTABLE
- damage = 25
- armour_penetration = 100
+ damage = 15
+ armour_penetration = 10
+ knockdown = 5
damage_type = BRUTE
hitsound = 'sound/effects/splat.ogg'
- knockdown = 30
var/chain
/obj/item/projectile/hook/fire(setAngle)
diff --git a/code/modules/mob/dead/observer/observer.dm b/code/modules/mob/dead/observer/observer.dm
index 6f43eb9efd..a111e54780 100644
--- a/code/modules/mob/dead/observer/observer.dm
+++ b/code/modules/mob/dead/observer/observer.dm
@@ -561,7 +561,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
var/list/dest = list() //List of possible destinations (mobs)
var/target = null //Chosen target.
- dest += getpois(mobs_only=1) //Fill list, prompt user with list
+ dest += getpois(mobs_only = TRUE) //Fill list, prompt user with list
target = input("Please, select a player!", "Jump to Mob", null, null) as null|anything in dest
if (!target)//Make sure we actually have a target
@@ -898,7 +898,9 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
if (!eye_name)
return
- var/mob/mob_eye = creatures[eye_name]
+ do_observe(creatures[eye_name])
+
+/mob/dead/observer/proc/do_observe(mob/mob_eye)
//Istype so we filter out points of interest that are not mobs
if(client && mob_eye && istype(mob_eye))
client.eye = mob_eye
diff --git a/code/modules/mob/dead/observer/orbit.dm b/code/modules/mob/dead/observer/orbit.dm
index 3aa5f8e302..26494dcb34 100644
--- a/code/modules/mob/dead/observer/orbit.dm
+++ b/code/modules/mob/dead/observer/orbit.dm
@@ -1,5 +1,6 @@
/datum/orbit_menu
var/mob/dead/observer/owner
+ var/auto_observe = FALSE
/datum/orbit_menu/New(mob/dead/observer/new_owner)
if(!istype(new_owner))
@@ -10,6 +11,7 @@
return GLOB.observer_state
/datum/orbit_menu/ui_interact(mob/user, datum/tgui/ui)
+ ui = SStgui.try_update_ui(user, src, ui)
if (!ui)
ui = new(user, src, "Orbit")
ui.open()
@@ -18,15 +20,35 @@
if (..())
return
- if (action == "orbit")
- var/ref = params["ref"]
- var/atom/movable/poi = (locate(ref) in GLOB.mob_list) || (locate(ref) in GLOB.poi_list)
- if (poi != null)
+ switch(action)
+ if ("orbit")
+ var/ref = params["ref"]
+ var/atom/movable/poi = (locate(ref) in GLOB.mob_list) || (locate(ref) in GLOB.poi_list)
+ if (poi == null)
+ . = TRUE
+ return
owner.ManualFollow(poi)
+ owner.reset_perspective(null)
+ if (auto_observe)
+ owner.do_observe(poi)
+ . = TRUE
+ if ("refresh")
+ update_static_data(owner, ui)
+ . = TRUE
+ if ("toggle_observe")
+ auto_observe = !auto_observe
+ if (auto_observe && owner.orbit_target)
+ owner.do_observe(owner.orbit_target)
+ else
+ owner.reset_perspective(null)
/datum/orbit_menu/ui_data(mob/user)
var/list/data = list()
+ data["auto_observe"] = auto_observe
+ return data
+/datum/orbit_menu/ui_static_data(mob/user)
+ var/list/data = list()
var/list/alive = list()
var/list/antagonists = list()
var/list/dead = list()
@@ -34,7 +56,7 @@
var/list/misc = list()
var/list/npcs = list()
- var/list/pois = getpois(skip_mindless = 1)
+ var/list/pois = getpois(skip_mindless = TRUE, specify_dead_role = FALSE)
for (var/name in pois)
var/list/serialized = list()
serialized["name"] = name
@@ -80,7 +102,7 @@
data["npcs"] = npcs
return data
-
+
/datum/orbit_menu/ui_assets()
. = ..() || list()
. += get_asset_datum(/datum/asset/simple/orbit)
diff --git a/code/modules/mob/living/carbon/human/species_types/dwarves.dm b/code/modules/mob/living/carbon/human/species_types/dwarves.dm
index 7c35ade4f2..e0a9bcaa36 100644
--- a/code/modules/mob/living/carbon/human/species_types/dwarves.dm
+++ b/code/modules/mob/living/carbon/human/species_types/dwarves.dm
@@ -30,10 +30,7 @@ GLOBAL_LIST_INIT(dwarf_last, world.file2list("strings/names/dwarf_last.txt")) //
/datum/species/dwarf/on_species_gain(mob/living/carbon/C, datum/species/old_species)
. = ..()
- var/dwarf_hair = pick("Beard (Dwarf)", "Beard (Very Long)", "Beard (Long)") //beard roullette
var/mob/living/carbon/human/H = C
- H.facial_hair_style = dwarf_hair
- H.update_hair()
H.AddElement(/datum/element/dwarfism, COMSIG_SPECIES_LOSS, src)
RegisterSignal(C, COMSIG_MOB_SAY, .proc/handle_speech) //We register handle_speech is being used.
diff --git a/code/modules/modular_computers/file_system/programs/card.dm b/code/modules/modular_computers/file_system/programs/card.dm
index 6d45914add..3455547d20 100644
--- a/code/modules/modular_computers/file_system/programs/card.dm
+++ b/code/modules/modular_computers/file_system/programs/card.dm
@@ -175,7 +175,7 @@
if("PRG_edit")
if(!computer || !authenticated || !target_id_card)
return
- var/new_name = params["name"]
+ var/new_name = reject_bad_name(params["name"])
if(!new_name)
return
target_id_card.registered_name = new_name
@@ -190,7 +190,7 @@
return
if(target == "Custom")
- var/custom_name = params["custom_name"]
+ var/custom_name = reject_bad_name(params["custom_name"])
if(custom_name)
target_id_card.assignment = custom_name
target_id_card.update_label()
diff --git a/code/modules/uplink/uplink_items/uplink_stealth.dm b/code/modules/uplink/uplink_items/uplink_stealth.dm
index 18a7707a88..1bd75fa2b1 100644
--- a/code/modules/uplink/uplink_items/uplink_stealth.dm
+++ b/code/modules/uplink/uplink_items/uplink_stealth.dm
@@ -102,6 +102,7 @@
along with slurred speech, aggression, and the ability to infect others with this agent."
item = /obj/item/storage/box/syndie_kit/romerol
cost = 25
+ player_minimum = 25
cant_discount = TRUE
exclude_modes = list(/datum/game_mode/nuclear)
diff --git a/html/changelogs/AutoChangeLog-pr-14132.yml b/html/changelogs/AutoChangeLog-pr-14132.yml
new file mode 100644
index 0000000000..ad899da2ba
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-14132.yml
@@ -0,0 +1,4 @@
+author: "shellspeed1"
+delete-after: True
+changes:
+ - balance: "There actually needs to be people for zombies to happen now."
diff --git a/html/changelogs/AutoChangeLog-pr-14155.yml b/html/changelogs/AutoChangeLog-pr-14155.yml
new file mode 100644
index 0000000000..d080417703
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-14155.yml
@@ -0,0 +1,4 @@
+author: "SmArtKar"
+delete-after: True
+changes:
+ - rscadd: "The orbit menu now has an Auto-Observe button! No more sifting through the lame observe menu to snoop in people's backpacks! Also, orbit menu now refreshes."
diff --git a/html/changelogs/AutoChangeLog-pr-14170.yml b/html/changelogs/AutoChangeLog-pr-14170.yml
new file mode 100644
index 0000000000..b5e70c065b
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-14170.yml
@@ -0,0 +1,4 @@
+author: "SmArtKar"
+delete-after: True
+changes:
+ - bugfix: "KAs are no longer getting broken when fired by a circuit"
diff --git a/html/changelogs/AutoChangeLog-pr-14172.yml b/html/changelogs/AutoChangeLog-pr-14172.yml
new file mode 100644
index 0000000000..8a0483d7b7
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-14172.yml
@@ -0,0 +1,4 @@
+author: "keronshb"
+delete-after: True
+changes:
+ - balance: "Makes cell chargers, charge faster."
diff --git a/html/changelogs/AutoChangeLog-pr-14174.yml b/html/changelogs/AutoChangeLog-pr-14174.yml
new file mode 100644
index 0000000000..2fb0998246
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-14174.yml
@@ -0,0 +1,6 @@
+author: "keronshb"
+delete-after: True
+changes:
+ - balance: "Force and damage > 15 from 18/25"
+ - balance: "Knockdown put down to 5 from 30"
+ - balance: "Armor pen down to 10 from 100."
diff --git a/html/changelogs/AutoChangeLog-pr-14183.yml b/html/changelogs/AutoChangeLog-pr-14183.yml
new file mode 100644
index 0000000000..82dddf2736
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-14183.yml
@@ -0,0 +1,4 @@
+author: "timothyteakettle"
+delete-after: True
+changes:
+ - rscadd: "dwarf facial hair is no longer randomised"
diff --git a/icons/obj/clothing/accessories.dmi b/icons/obj/clothing/accessories.dmi
index 3731c9e706..e452ca687b 100644
Binary files a/icons/obj/clothing/accessories.dmi and b/icons/obj/clothing/accessories.dmi differ
diff --git a/tgui/packages/tgui/interfaces/Orbit.js b/tgui/packages/tgui/interfaces/Orbit.js
index 7423dadbc4..1b6daccabc 100644
--- a/tgui/packages/tgui/interfaces/Orbit.js
+++ b/tgui/packages/tgui/interfaces/Orbit.js
@@ -1,10 +1,10 @@
import { createSearch } from 'common/string';
+import { multiline } from 'common/string';
import { resolveAsset } from '../assets';
import { useBackend, useLocalState } from '../backend';
-import { Box, Button, Flex, Icon, Input, Section } from '../components';
+import { Box, Button, Divider, Flex, Icon, Input, Section } from '../components';
import { Window } from '../layouts';
-const PATTERN_DESCRIPTOR = / \[(?:ghost|dead)\]$/;
const PATTERN_NUMBER = / \(([0-9]+)\)$/;
const searchFor = searchText => createSearch(searchText, thing => thing.name);
@@ -43,7 +43,7 @@ const BasicSection = (props, context) => {
{things.map(thing => (