diff --git a/code/datums/datum.dm b/code/datums/datum.dm
index cf0d7816d5b..7066ac6d57e 100644
--- a/code/datums/datum.dm
+++ b/code/datums/datum.dm
@@ -115,10 +115,6 @@
if (!isturf(src))
cleanup_events(src)
- var/ui_key = REF(src)
- if(LAZYISIN(SSnanoui.open_uis, ui_key))
- SSnanoui.close_uis(src)
-
//BEGIN: ECS SHIT
var/list/dc = _datum_components
if(dc)
diff --git a/code/game/machinery/doors/windowdoor.dm b/code/game/machinery/doors/windowdoor.dm
index 6a0c4ea0ea2..a9b7fec7af2 100644
--- a/code/game/machinery/doors/windowdoor.dm
+++ b/code/game/machinery/doors/windowdoor.dm
@@ -155,7 +155,7 @@
take_damage(25)
return
else
- return attackby(user, user)
+ return attackby(null, user)
/obj/machinery/door/window/emag_act(var/remaining_charges, var/mob/user)
if (density && operable())
diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm
index 7d21ebb7b6d..adc75a9ffc5 100644
--- a/code/game/objects/items.dm
+++ b/code/game/objects/items.dm
@@ -257,10 +257,7 @@
/obj/item/Destroy()
if(ismob(loc))
var/mob/m = loc
- m.drop_from_inventory(src)
- m.update_inv_r_hand()
- m.update_inv_l_hand()
- src.loc = null
+ m.drop_from_inventory(src, null)
if(!QDELETED(action))
QDEL_NULL(action) // /mob/living/proc/handle_actions() creates it, for ungodly reasons
@@ -930,7 +927,7 @@ GLOBAL_LIST_INIT(slot_flags_enumeration, list(
user.langchat_speech("holds up [src].", viewers, GLOB.all_languages, skip_language_check = TRUE, animation_style = LANGCHAT_FAST_POP, additional_styles = list("langchat_small", "emote"))
for (var/mob/M in viewers)
if(!user.is_invisible_to(M))
- M.show_message("[user] holds up [icon2html(src, viewers)] [src]. Take a closer look.",1)
+ M.show_message("[user] holds up [icon2html(src, M)] [src]. Take a closer look.",1)
/mob/living/carbon/verb/showoff()
set name = "Show Held Item"
diff --git a/code/modules/mob/abstract/ghost/ghost.dm b/code/modules/mob/abstract/ghost/ghost.dm
index 86da2ead88e..9c053c0dbd6 100644
--- a/code/modules/mob/abstract/ghost/ghost.dm
+++ b/code/modules/mob/abstract/ghost/ghost.dm
@@ -132,13 +132,12 @@
set category = "Ghost"
set desc = "Follow and haunt a mob."
- var/datum/tgui_module/follow_menu/GM = new /datum/tgui_module/follow_menu(usr)
- GM.ui_interact(usr)
+ GLOB.follow_menu.ui_interact(src)
// This is the ghost's follow verb with an argument
/mob/abstract/ghost/proc/ManualFollow(var/atom/movable/target)
if(!target)
- return
+ return FALSE
//Stops orbit if there's any; TG doesn't do this, but if you don't it breaks the orbiting reference
//if you are jumping from one mob to another, hence why we're doing it here
@@ -154,6 +153,7 @@
to_chat(src, SPAN_NOTICE("Now following \the [target]."))
update_sight()
+ return TRUE
/mob/abstract/ghost/proc/update_sight()
//if they are on a restricted level, then set the ghost vision for them.
diff --git a/code/modules/mob/living/carbon/human/death.dm b/code/modules/mob/living/carbon/human/death.dm
index c30ca732347..5ff5ff87397 100644
--- a/code/modules/mob/living/carbon/human/death.dm
+++ b/code/modules/mob/living/carbon/human/death.dm
@@ -109,9 +109,9 @@
var/datum/sprite_accessory/hair/hair = GLOB.hair_styles_list[h_style]
var/datum/sprite_accessory/facial_hair/facial = GLOB.facial_hair_styles_list[f_style]
- if(!facial.keep_as_skeleton && f_style)
+ if(facial && !facial.keep_as_skeleton)
f_style = "Shaved"
- if(!hair.keep_as_skeleton && h_style)
+ if(hair && !hair.keep_as_skeleton)
h_style = "Bald"
update_hair(0)
diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm
index c662494a0ca..19c7ce3e6c5 100644
--- a/code/modules/mob/living/carbon/human/human.dm
+++ b/code/modules/mob/living/carbon/human/human.dm
@@ -1466,7 +1466,7 @@
self = 1
if ((src.species.flags & NO_BLOOD) || (status_flags & FAKEDEATH))
- to_chat(usr, SPAN_WARNING(self ? "You have no pulse." : "[src] has no pulse!"))
+ to_chat(usr, SPAN_WARNING("[self ? "You have" : "[src] has"] no pulse!"))
return
if(!self)
diff --git a/code/modules/mob/living/carbon/human/human_defines.dm b/code/modules/mob/living/carbon/human/human_defines.dm
index eec74a16945..fc14e29f070 100644
--- a/code/modules/mob/living/carbon/human/human_defines.dm
+++ b/code/modules/mob/living/carbon/human/human_defines.dm
@@ -38,7 +38,6 @@
var/size_multiplier = 1 //multiplier for the mob's icon size
var/damage_multiplier = 1 //multiplies melee combat damage
- var/icon_update = 1 //whether icon updating shall take place
var/default_lighting_alpha = LIGHTING_PLANE_ALPHA_VISIBLE
diff --git a/code/modules/mob/living/carbon/human/human_movement.dm b/code/modules/mob/living/carbon/human/human_movement.dm
index fe8fbe30f97..386028d36a5 100644
--- a/code/modules/mob/living/carbon/human/human_movement.dm
+++ b/code/modules/mob/living/carbon/human/human_movement.dm
@@ -122,9 +122,9 @@
/mob/living/carbon/human/set_dir(var/new_dir, ignore_facing_dir = FALSE)
. = ..()
if(. && tail_style)
- update_tail_showing(1)
+ update_tail_showing(!lying)
if(lying)
- update_icon(forceDirUpdate = TRUE)
+ update_icon(TRUE)
/mob/living/carbon/human/Move()
. = ..()
diff --git a/code/modules/mob/living/carbon/human/species/species.dm b/code/modules/mob/living/carbon/human/species/species.dm
index 4e0523f1039..203de09a486 100644
--- a/code/modules/mob/living/carbon/human/species/species.dm
+++ b/code/modules/mob/living/carbon/human/species/species.dm
@@ -995,7 +995,9 @@
/datum/species/proc/handle_stance_damage(var/mob/living/carbon/human/H, var/damage_only = FALSE)
var/static/support_limbs = list(
BP_L_LEG = BP_R_LEG,
- BP_L_FOOT = BP_R_FOOT
+ BP_L_FOOT = BP_R_FOOT,
+ BP_R_LEG = BP_L_LEG,
+ BP_R_FOOT = BP_L_FOOT
)
var/has_opposite_limb = FALSE
diff --git a/code/modules/mob/living/carbon/human/update_icons.dm b/code/modules/mob/living/carbon/human/update_icons.dm
index 4f0eb036d2d..7398053cfa4 100644
--- a/code/modules/mob/living/carbon/human/update_icons.dm
+++ b/code/modules/mob/living/carbon/human/update_icons.dm
@@ -104,26 +104,29 @@ There are several things that need to be remembered:
var/list/overlays_raw[TOTAL_LAYERS] // Our set of "raw" overlays that can be modified, but cannot be directly applied to the mob without preprocessing.
var/previous_damage_appearance // store what the body last looked like, so we only have to update it if something changed
-#define UPDATE_ICON_IGNORE_DIRECTION_UPDATE -1
-
// Updates overlays from overlays_raw.
/mob/living/carbon/human/update_icon(var/forceDirUpdate = FALSE)
if (QDELETED(src))
return // No point.
+ var/update_lying = (lying_prev != lying) || forceDirUpdate || size_multiplier != 1
+ var/draw_specific_icon = (!lying || species.prone_icon)
+
+ if(update_lying && draw_specific_icon)
+ update_inv_l_hand(FALSE)
+ update_inv_r_hand(FALSE)
+
update_hud() //TODO: remove the need for this
- ClearOverlays()
if(cloaked)
icon = 'icons/mob/human.dmi'
icon_state = "body_cloaked"
- AddOverlays(list(overlays_raw[L_HAND_LAYER], overlays_raw[R_HAND_LAYER]))
-
- else if (icon_update)
+ SetOverlays(list(overlays_raw[L_HAND_LAYER], overlays_raw[R_HAND_LAYER]))
+ else
+ var/list/ovr = list()
if (icon != stand_icon)
icon = stand_icon
- var/list/ovr = list()
// We manually add each element instead of just using Copy() so that lists are appended instead of inserted.
for (var/item in overlays_raw)
if (item)
@@ -137,18 +140,20 @@ There are several things that need to be remembered:
var/icon/aura_overlay = icon(A.icon, icon_state = A.icon_state)
ovr += aura_overlay
- AddOverlays(ovr)
-
- if (((lying_prev != lying) || forceDirUpdate || size_multiplier != 1) && forceDirUpdate != UPDATE_ICON_IGNORE_DIRECTION_UPDATE)
- if(lying && !species.prone_icon) //Only rotate them if we're not drawing a specific icon for being prone.
- var/matrix/M = matrix()
+ SetOverlays(ovr)
+ if(update_lying) //Only rotate them if we're not drawing a specific icon for being prone.
+ var/matrix/M = matrix()
+ M.Scale(size_multiplier)
+ if(draw_specific_icon)
+ M.Translate(0, 16*(size_multiplier-1))
+ animate(src, transform = M, time = ANIM_LYING_TIME)
+ else
switch(src.dir)
if(SOUTH,EAST)
M.Turn(90)
else
M.Turn(-90)
- M.Scale(size_multiplier)
M.Translate(1,-6)
animate(src, transform = M, time = (forceDirUpdate ? 0 : ANIM_LYING_TIME))
@@ -157,15 +162,6 @@ There are several things that need to be remembered:
if(istype(src.r_hand, /obj/item/gun) && lying)
HeldObjectDirTransform(slot_r_hand, src.dir)
- else
- update_inv_l_hand(FALSE)
- update_inv_r_hand(FALSE)
- update_icon(UPDATE_ICON_IGNORE_DIRECTION_UPDATE)
- var/matrix/M = matrix()
- M.Scale(size_multiplier)
- M.Translate(0, 16*(size_multiplier-1))
- animate(src, transform = M, time = ANIM_LYING_TIME)
-
UpdateOverlays()
lying_prev = lying
@@ -196,9 +192,7 @@ There are several things that need to be remembered:
animate(item_image, transform = item_transform)
overlays_raw[layer] = item_image
- update_icon(UPDATE_ICON_IGNORE_DIRECTION_UPDATE)
-
-#undef UPDATE_ICON_IGNORE_DIRECTION_UPDATE
+ update_icon()
//DAMAGE OVERLAYS
//constructs damage icon for each organ from mask * damage field and saves it in our overlays_raw list (as a list of icons).
@@ -1245,7 +1239,7 @@ There are several things that need to be remembered:
overlays_raw[L_HAND_LAYER] = null
if(update_icons)
- update_icon(forceDirUpdate = TRUE)
+ update_icon(TRUE)
/mob/living/carbon/human/update_inv_r_hand(update_icons = TRUE)
if (QDELETED(src))
@@ -1284,7 +1278,7 @@ There are several things that need to be remembered:
overlays_raw[R_HAND_LAYER] = null
if(update_icons)
- update_icon(forceDirUpdate = TRUE)
+ update_icon(TRUE)
/mob/living/carbon/human/update_inv_wrists(var/update_icons=1)
if (QDELETED(src))
@@ -1389,7 +1383,7 @@ There are several things that need to be remembered:
if(species.tail && !(mutations & HUSK) && !(mutations & SKELETON) && !(wear_suit && wear_suit.flags_inv & HIDETAIL))
var/icon/tail_s = get_tail_icon()
overlays_raw[tail_layer] = image(tail_s, icon_state = "[tail_style]_s")
- animate_tail_reset()
+ animate_tail_reset(FALSE)
update_tail_accessory(FALSE)
if(update_icons)
@@ -1414,7 +1408,7 @@ There are several things that need to be remembered:
return tail_icon
-/mob/living/carbon/human/proc/set_tail_state(var/mob_state)
+/mob/living/carbon/human/proc/set_tail_state(var/mob_state, var/update = TRUE)
if(!tail_style)
return
@@ -1428,8 +1422,7 @@ There are several things that need to be remembered:
if(tail_overlay && species.tail_animation)
if(tail_overlay.icon_state != mob_state)
tail_overlay.icon_state = mob_state
- update_tail_accessory()
- update_icon()
+ update_tail_accessory(update)
return tail_overlay
return null
@@ -1461,11 +1454,11 @@ There are several things that need to be remembered:
/mob/living/carbon/human/proc/animate_tail_fast()
set_tail_state("[tail_style]_loop")
-/mob/living/carbon/human/proc/animate_tail_reset()
+/mob/living/carbon/human/proc/animate_tail_reset(var/update = TRUE)
if(stat != DEAD && !lying)
- set_tail_state("[tail_style]_idle")
+ set_tail_state("[tail_style]_idle", update)
else
- set_tail_state("[tail_style]_static")
+ set_tail_state("[tail_style]_static", update)
/mob/living/carbon/human/proc/animate_tail_stop(var/update_icons=1)
set_tail_state("[tail_style]_static")
diff --git a/code/modules/nano/modules/follow_menu.dm b/code/modules/nano/modules/follow_menu.dm
index 87b033df6f1..657895e3718 100644
--- a/code/modules/nano/modules/follow_menu.dm
+++ b/code/modules/nano/modules/follow_menu.dm
@@ -1,3 +1,5 @@
+GLOBAL_DATUM_INIT(follow_menu, /datum/tgui_module/follow_menu, new)
+
/datum/tgui_module/follow_menu/ui_interact(var/mob/user, var/datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
@@ -14,9 +16,15 @@
return
if(action == "follow_target")
- ghost.ManualFollow(locate(params["follow_target"]) in GLOB.mob_list)
+ if(!ghost.ManualFollow(locate(params["follow_target"]) in GLOB.mob_list))
+ to_chat(ghost, SPAN_WARNING("Failed to follow selected target. Refreshing mob list..."))
+ return TRUE
-/datum/tgui_module/follow_menu/ui_data(mob/user)
+ if(action == "refresh")
+ ui.send_full_update()
+ return TRUE
+
+/datum/tgui_module/follow_menu/ui_static_data(mob/user)
var/list/data = list()
// Don't worry about this is_mod check being for storytellers as well - all it does is highlight antags in red.
var/is_mod = check_rights(R_MOD|R_ADMIN, 0, user) || isstoryteller(user)
diff --git a/code/modules/nano/nanoui.dm b/code/modules/nano/nanoui.dm
index 9baa217ba53..c441af104f2 100644
--- a/code/modules/nano/nanoui.dm
+++ b/code/modules/nano/nanoui.dm
@@ -519,7 +519,7 @@ nanoui is used to open and update nano browser uis
* @return nothing
*/
/datum/nanoui/process(update = 0)
- if (!src_object || !user)
+ if (QDELETED(src_object) || QDELETED(user))
close()
return
diff --git a/code/modules/organs/subtypes/standard.dm b/code/modules/organs/subtypes/standard.dm
index 242123f7532..8802cd65738 100644
--- a/code/modules/organs/subtypes/standard.dm
+++ b/code/modules/organs/subtypes/standard.dm
@@ -194,12 +194,11 @@
/obj/item/organ/external/hand/is_malfunctioning()
. = ..()
- if(!.)
- if(owner.is_mechanical())
- var/actuator_type = limb_name == BP_L_HAND ? BP_ACTUATORS_LEFT : BP_ACTUATORS_RIGHT
- var/obj/item/organ/internal/machine/actuators/actuator = owner.internal_organs_by_name[actuator_type]
- if(!actuator || (actuator.status & ORGAN_DEAD))
- return TRUE
+ if(!. && owner?.is_mechanical())
+ var/actuator_type = limb_name == BP_L_HAND ? BP_ACTUATORS_LEFT : BP_ACTUATORS_RIGHT
+ var/obj/item/organ/internal/machine/actuators/actuator = owner.internal_organs_by_name[actuator_type]
+ if(!actuator || (actuator.status & ORGAN_DEAD))
+ return TRUE
/obj/item/organ/external/hand/take_damage(brute, burn, damage_flags, used_weapon, list/forbidden_limbs, silent)
. = ..()
diff --git a/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Drugs.dm b/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Drugs.dm
index d0108be2878..921f4a0c6c3 100644
--- a/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Drugs.dm
+++ b/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Drugs.dm
@@ -312,7 +312,7 @@
M.hallucination = max(M.hallucination, drug_strength)
if(prob(15))
- to_chat(SPAN_GOOD(pick("The floor is melting...", "Everything is so much brighter! Wow!", "Everything is shifting around you.")))
+ to_chat(M, SPAN_GOOD(pick("The floor is melting...", "Everything is so much brighter! Wow!", "Everything is shifting around you.")))
/singleton/reagent/drugs/night_juice
diff --git a/code/modules/shuttles/shuttle_console.dm b/code/modules/shuttles/shuttle_console.dm
index 2966904f98f..75ada22dd0f 100644
--- a/code/modules/shuttles/shuttle_console.dm
+++ b/code/modules/shuttles/shuttle_console.dm
@@ -170,6 +170,7 @@
"can_force" = shuttle.can_force(),
"can_rename_ship" = can_rename_ship,
"ship_name" = shuttle.name,
+ "current_location" = shuttle.get_location_name(),
)
/obj/machinery/computer/shuttle_control/ui_act(action, params)
diff --git a/code/modules/vehicles/vehicle.dm b/code/modules/vehicles/vehicle.dm
index a9726b238b7..596d0b17b91 100644
--- a/code/modules/vehicles/vehicle.dm
+++ b/code/modules/vehicles/vehicle.dm
@@ -202,15 +202,13 @@
if(powered && cell?.charge < charge_use && !organic)
return FALSE
on = TRUE
- set_light_range_power_color(initial(light_range))
- set_light_on(on)
+ set_light(initial(light_range))
update_icon()
return TRUE
/obj/vehicle/proc/turn_off()
on = FALSE
- set_light_range_power_color(0)
- set_light_on(on)
+ set_light(0)
update_icon()
/obj/vehicle/emag_act(var/remaining_charges, mob/user as mob)
diff --git a/html/changelogs/JohnWildkins-cooked.yml b/html/changelogs/JohnWildkins-cooked.yml
new file mode 100644
index 00000000000..66ddc0a03ea
--- /dev/null
+++ b/html/changelogs/JohnWildkins-cooked.yml
@@ -0,0 +1,24 @@
+# Your name.
+author: Wildkins
+
+# Optional: Remove this file after generating master changelog. Useful for PR changelogs that won't get used again.
+delete-after: True
+
+# Any changes you've made. See valid prefix list above.
+# INDENT WITH TWO SPACES. NOT TABS. SPACES.
+# SCREW THIS UP AND IT WON'T WORK.
+# Also, this gets changed to [] after reading. Just remove the brackets when you add new shit.
+# Please surround your changes in double quotes ("). It works without them, but if you use certain characters it screws up compiling. The quotes will not show up in the changelog.
+changes:
+ - refactor: "Every single datum no longer does REF(src) on /Destroy to see if it has an open nanoui"
+ - bugfix: "Showing held items no longer causes every recording device to runtime."
+ - refactor: "Every obj/item/Destroy no longer updates the held mob's icon three times."
+ - refactor: "Follow menu is now a global UI and should no longer DDOS the server when 50 people have it open"
+ - refactor: "Follow menu no longer auto-updates the list of mobs while open, use the refresh button."
+ - bugfix: "Fix runtime when a /human without hair or facial hair would be skeletonized"
+ - refactor: "Cleaned up human icon update code. Lying / direction changes no longer cause four update_icon calls. Tailed species turning no longer causes six."
+ - bugfix: "Fix runtime caused by detached / ownerless mechanical hands."
+ - bugfix: "Fix colorspace runtime."
+ - bugfix: "Fix lighting harddel caused by using improper handlers for static lights."
+ - bugfix: "Lifts now grey out the current location, instead of throwing a runtime when you click it."
+ - bugfix: "Fix runtime when a bloodless/fakedeath mob has their pulse taken."
diff --git a/tgui/packages/tgui/interfaces/FollowMenu.tsx b/tgui/packages/tgui/interfaces/FollowMenu.tsx
index be852b9a76d..c772734dfa8 100644
--- a/tgui/packages/tgui/interfaces/FollowMenu.tsx
+++ b/tgui/packages/tgui/interfaces/FollowMenu.tsx
@@ -30,17 +30,20 @@ export const FollowMenu = (props, context) => {