diff --git a/_maps/map_files/wawastation/wawastation.dmm b/_maps/map_files/wawastation/wawastation.dmm
index 7b29696062850..dafa2c4d1a09e 100644
--- a/_maps/map_files/wawastation/wawastation.dmm
+++ b/_maps/map_files/wawastation/wawastation.dmm
@@ -8907,6 +8907,7 @@
/obj/effect/turf_decal/tile/purple/opposingcorners,
/obj/structure/cable,
/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2,
+/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4,
/turf/open/floor/iron/white,
/area/station/science/lobby)
"dkq" = (
@@ -14049,6 +14050,8 @@
/obj/machinery/power/apc/auto_name/directional/south,
/obj/structure/cable,
/obj/effect/decal/cleanable/dirt/dust,
+/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4,
+/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2,
/turf/open/floor/plating,
/area/station/maintenance/department/science)
"eZQ" = (
@@ -17845,6 +17848,8 @@
/area/station/engineering/atmos/upper)
"grl" = (
/obj/structure/cable,
+/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4,
+/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2,
/turf/open/floor/iron/white,
/area/station/science/lobby)
"grm" = (
@@ -19114,6 +19119,8 @@
"gMK" = (
/obj/structure/cable,
/obj/effect/decal/cleanable/dirt/dust,
+/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4,
+/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2,
/turf/open/floor/plating,
/area/station/maintenance/department/science)
"gNd" = (
@@ -20275,6 +20282,12 @@
/obj/structure/lattice,
/turf/open/misc/asteroid/airless,
/area/space/nearstation)
+"hgX" = (
+/obj/effect/decal/cleanable/dirt/dust,
+/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4,
+/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2,
+/turf/open/floor/plating,
+/area/station/maintenance/department/science)
"hhd" = (
/obj/machinery/door/poddoor/shutters{
id = "ordauxgarage";
@@ -26289,6 +26302,8 @@
dir = 1
},
/obj/effect/decal/cleanable/blood/old,
+/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4,
+/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2,
/turf/open/floor/iron/white,
/area/station/science/lobby)
"jrm" = (
@@ -28847,6 +28862,8 @@
/obj/effect/mapping_helpers/airlock/unres{
dir = 1
},
+/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4,
+/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2,
/turf/open/floor/plating,
/area/station/maintenance/department/science)
"kjv" = (
@@ -33126,6 +33143,12 @@
/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4,
/turf/open/floor/iron,
/area/station/hallway/secondary/exit/departure_lounge)
+"lIW" = (
+/obj/item/stack/cable_coil{
+ amount = 1
+ },
+/turf/open/floor/plating/airless,
+/area/station/solars/port/fore)
"lIZ" = (
/obj/effect/turf_decal/sand/plating,
/obj/machinery/vending/boozeomat,
@@ -35988,6 +36011,7 @@
dir = 8
},
/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2,
+/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4,
/turf/open/floor/iron/white,
/area/station/science/lobby)
"mJL" = (
@@ -36694,6 +36718,13 @@
/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2,
/turf/open/floor/carpet,
/area/station/commons/dorms)
+"mXF" = (
+/obj/effect/mapping_helpers/broken_floor,
+/obj/item/stack/cable_coil{
+ amount = 1
+ },
+/turf/open/floor/plating/airless,
+/area/station/solars/starboard/fore)
"mXJ" = (
/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2,
/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4,
@@ -41877,6 +41908,7 @@
/obj/effect/turf_decal/tile/purple/half/contrasted,
/obj/structure/cable,
/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2,
+/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4,
/turf/open/floor/iron/white,
/area/station/science/lobby)
"oUb" = (
@@ -47752,6 +47784,7 @@
"qXy" = (
/obj/structure/cable,
/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2,
+/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4,
/turf/open/floor/iron/white,
/area/station/science/lobby)
"qXB" = (
@@ -48038,13 +48071,6 @@
"rcl" = (
/turf/closed/wall/r_wall,
/area/station/security/execution/transfer)
-"rcp" = (
-/obj/machinery/power/solar{
- id = "forestarboard";
- name = "Fore-Starboard Solar Array"
- },
-/turf/open/floor/iron/solarpanel/airless,
-/area/station/solars/starboard/fore)
"rcs" = (
/obj/effect/decal/cleanable/dirt,
/turf/open/floor/plating,
@@ -49260,6 +49286,11 @@
"ruZ" = (
/turf/closed/wall/r_wall,
/area/station/maintenance/department/engine)
+"rvg" = (
+/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4,
+/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2,
+/turf/open/floor/iron/white,
+/area/station/science/lobby)
"rvo" = (
/obj/machinery/light/small/dim/directional/west,
/obj/effect/turf_decal/tile/green/half/contrasted{
@@ -55454,6 +55485,7 @@
/area/station/hallway/secondary/exit/departure_lounge)
"tAt" = (
/obj/machinery/power/smes,
+/obj/structure/cable,
/turf/open/floor/plating,
/area/station/maintenance/solars/port/aft)
"tAw" = (
@@ -56116,6 +56148,8 @@
"tLH" = (
/obj/item/storage/fancy/candle_box,
/obj/effect/decal/cleanable/dirt/dust,
+/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4,
+/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2,
/turf/open/floor/plating,
/area/station/maintenance/department/science)
"tLI" = (
@@ -58015,6 +58049,13 @@
/obj/machinery/firealarm/directional/south,
/turf/open/floor/iron,
/area/station/hallway/primary/central)
+"urS" = (
+/obj/structure/lattice/catwalk,
+/obj/item/stack/cable_coil{
+ amount = 1
+ },
+/turf/open/space/basic,
+/area/station/solars/port/fore)
"urT" = (
/obj/structure/cable,
/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{
@@ -64657,6 +64698,8 @@
/area/station/command/heads_quarters/captain/private)
"wMB" = (
/obj/effect/turf_decal/siding,
+/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4,
+/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2,
/turf/open/floor/iron/textured,
/area/station/science/lobby)
"wME" = (
@@ -65159,6 +65202,8 @@
"wWY" = (
/obj/effect/decal/cleanable/dirt/dust,
/obj/effect/decal/cleanable/blood/old,
+/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4,
+/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2,
/turf/open/floor/plating,
/area/station/maintenance/department/science)
"wWZ" = (
@@ -77689,7 +77734,7 @@ rGO
opZ
opZ
fYX
-rGO
+urS
opZ
opZ
opZ
@@ -77947,7 +77992,7 @@ sKL
rGO
nMk
rGO
-nMk
+lIW
rGO
sKL
rGO
@@ -78204,7 +78249,7 @@ opZ
opZ
fYX
rGO
-fYX
+opZ
opZ
opZ
opZ
@@ -78460,8 +78505,8 @@ rGO
sKL
rGO
nMk
-rGO
-nMk
+urS
+lIW
rGO
sKL
rGO
@@ -78718,10 +78763,10 @@ opZ
opZ
fYX
rGO
-fYX
opZ
opZ
-fYX
+opZ
+opZ
cLf
iUF
dUc
@@ -102881,7 +102926,7 @@ vxX
vxX
gvF
dnW
-iKc
+rvg
slL
iKc
cRV
@@ -103138,7 +103183,7 @@ uJt
vfJ
gvF
eBY
-iKc
+rvg
vuq
hPH
iKc
@@ -103395,7 +103440,7 @@ wWY
kju
wMB
jrd
-iKc
+rvg
slL
slL
slL
@@ -103648,7 +103693,7 @@ cLf
vxX
uJt
eJr
-uba
+hgX
vfJ
aTU
jUi
@@ -112115,7 +112160,7 @@ cLS
qSb
qSb
qSb
-qSb
+mXF
qSb
hsz
hsz
@@ -112363,7 +112408,7 @@ shs
cLf
pbP
rst
-rcp
+pih
rst
pih
rst
@@ -112620,7 +112665,7 @@ shs
cLf
cLf
cLf
-rcp
+pih
rst
pih
rst
diff --git a/code/__DEFINES/footsteps.dm b/code/__DEFINES/footsteps.dm
index cffe920215335..8dddfceac57df 100644
--- a/code/__DEFINES/footsteps.dm
+++ b/code/__DEFINES/footsteps.dm
@@ -208,3 +208,4 @@ GLOBAL_LIST_INIT(heavyfootstep, list(
'sound/effects/meatslap.ogg'), 100, 0),
))
+#define SHOULD_DISABLE_FOOTSTEPS(source) ((SSlag_switch.measures[DISABLE_FOOTSTEPS] && !(HAS_TRAIT(source, TRAIT_BYPASS_MEASURES))) || HAS_TRAIT(source, TRAIT_SILENT_FOOTSTEPS))
diff --git a/code/__DEFINES/mobs.dm b/code/__DEFINES/mobs.dm
index ac5d51cdc9921..a1496d2e13876 100644
--- a/code/__DEFINES/mobs.dm
+++ b/code/__DEFINES/mobs.dm
@@ -378,6 +378,8 @@
#define SLIPPERY_TURF (1<<5)
/// For mobs who are slippery, this requires the mob holding it to be lying down.
#define SLIPPERY_WHEN_LYING_DOWN (1<<6)
+///Like sliding, but it's short, it doesn't knockdown, it doesn't stun, it just staggers a bit.
+#define WEAK_SLIDE (1<<7)
#define MAX_CHICKENS 50
diff --git a/code/_onclick/hud/hud.dm b/code/_onclick/hud/hud.dm
index d04dafefeb088..ab1e5fccfbb0d 100644
--- a/code/_onclick/hud/hud.dm
+++ b/code/_onclick/hud/hud.dm
@@ -206,6 +206,8 @@ GLOBAL_LIST_INIT(available_ui_styles, list(
SIGNAL_HANDLER
update_parallax_pref() // If your eye changes z level, so should your parallax prefs
var/turf/eye_turf = get_turf(eye)
+ if(!eye_turf)
+ return
SEND_SIGNAL(src, COMSIG_HUD_Z_CHANGED, eye_turf.z)
var/new_offset = GET_TURF_PLANE_OFFSET(eye_turf)
if(current_plane_offset == new_offset)
diff --git a/code/datums/actions/mobs/fire_breath.dm b/code/datums/actions/mobs/fire_breath.dm
index 11ad04fa0df20..e407dafd7cffe 100644
--- a/code/datums/actions/mobs/fire_breath.dm
+++ b/code/datums/actions/mobs/fire_breath.dm
@@ -91,7 +91,7 @@
/datum/action/cooldown/mob_cooldown/fire_breath/mass_fire
name = "Mass Fire"
button_icon = 'icons/effects/fire.dmi'
- button_icon_state = "1"
+ button_icon_state = "light"
desc = "Breathe flames in all directions."
cooldown_time = 10.5 SECONDS
click_to_activate = FALSE
diff --git a/code/datums/ai/monkey/monkey_behaviors.dm b/code/datums/ai/monkey/monkey_behaviors.dm
index 3fb94191cc3cc..229460228401d 100644
--- a/code/datums/ai/monkey/monkey_behaviors.dm
+++ b/code/datums/ai/monkey/monkey_behaviors.dm
@@ -140,10 +140,10 @@
return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED
// check if target has a weapon
- var/holding_weapon = FALSE
+ var/holding_weapon
for(var/obj/item/potential_weapon in target.held_items)
if(!(potential_weapon.item_flags & ABSTRACT))
- holding_weapon = TRUE
+ holding_weapon = potential_weapon
break
var/attack_results = monkey_attack(controller, target, seconds_per_tick, holding_weapon && SPT_PROB(MONKEY_ATTACK_DISARM_PROB, seconds_per_tick), holding_weapon)
diff --git a/code/datums/chatmessage.dm b/code/datums/chatmessage.dm
index e27eb580499d6..312670f7bf39e 100644
--- a/code/datums/chatmessage.dm
+++ b/code/datums/chatmessage.dm
@@ -50,6 +50,8 @@
var/animate_start = 0
/// Our animation lifespan, how long this message will last
var/animate_lifespan = 0
+ /// Callback to finish_image_generation passed to SSrunechat
+ var/datum/callback/finish_callback
/**
* Constructs a chat message overlay
@@ -81,6 +83,10 @@
LAZYREMOVEASSOC(owned_by.seen_messages, message_loc, src)
owned_by.images.Remove(message)
+ if (finish_callback)
+ SSrunechat.message_queue -= finish_callback
+ finish_callback = null
+
owned_by = null
message_loc = null
message = null
@@ -192,13 +198,14 @@
if(!VERB_SHOULD_YIELD)
return finish_image_generation(mheight, target, owner, complete_text, lifespan)
- var/datum/callback/our_callback = CALLBACK(src, PROC_REF(finish_image_generation), mheight, target, owner, complete_text, lifespan)
- SSrunechat.message_queue += our_callback
+ finish_callback = CALLBACK(src, PROC_REF(finish_image_generation), mheight, target, owner, complete_text, lifespan)
+ SSrunechat.message_queue += finish_callback
return
///finishes the image generation after the MeasureText() call in generate_image().
///necessary because after that call the proc can resume at the end of the tick and cause overtime.
/datum/chatmessage/proc/finish_image_generation(mheight, atom/target, mob/owner, complete_text, lifespan)
+ finish_callback = null
var/rough_time = REALTIMEOFDAY
approx_lines = max(1, mheight / CHAT_MESSAGE_APPROX_LHEIGHT)
var/starting_height = target.maptext_height
diff --git a/code/datums/elements/footstep.dm b/code/datums/elements/footstep.dm
index 698f7896a70b4..77a06dcdc4e96 100644
--- a/code/datums/elements/footstep.dm
+++ b/code/datums/elements/footstep.dm
@@ -1,5 +1,3 @@
-#define SHOULD_DISABLE_FOOTSTEPS(source) ((SSlag_switch.measures[DISABLE_FOOTSTEPS] && !(HAS_TRAIT(source, TRAIT_BYPASS_MEASURES))) || HAS_TRAIT(source, TRAIT_SILENT_FOOTSTEPS))
-
///Footstep element. Plays footsteps at parents location when it is appropriate.
/datum/element/footstep
element_flags = ELEMENT_DETACH_ON_HOST_DESTROY|ELEMENT_BESPOKE
@@ -231,5 +229,3 @@
return
playsound(source_loc, footstep_sounds, 50, falloff_distance = 1, vary = sound_vary)
-
-#undef SHOULD_DISABLE_FOOTSTEPS
diff --git a/code/datums/looping_sounds/changeling_absorb.dm b/code/datums/looping_sounds/changeling_absorb.dm
new file mode 100644
index 0000000000000..418c2a8dacf54
--- /dev/null
+++ b/code/datums/looping_sounds/changeling_absorb.dm
@@ -0,0 +1,14 @@
+/datum/looping_sound/changeling_absorb
+ mid_sounds = list(
+ 'sound/effects/changeling_absorb/changeling_absorb1.ogg' = 1,
+ 'sound/effects/changeling_absorb/changeling_absorb2.ogg' = 1,
+ 'sound/effects/changeling_absorb/changeling_absorb3.ogg' = 1,
+ 'sound/effects/changeling_absorb/changeling_absorb4.ogg' = 1,
+ 'sound/effects/changeling_absorb/changeling_absorb5.ogg' = 1,
+ 'sound/effects/changeling_absorb/changeling_absorb6.ogg' = 1,
+ 'sound/effects/changeling_absorb/changeling_absorb7.ogg' = 1,
+ )
+ each_once = TRUE
+ mid_length = 3 SECONDS
+ volume = 80
+ ignore_walls = FALSE
diff --git a/code/datums/sprite_accessories.dm b/code/datums/sprite_accessories.dm
index 9ac059eaac742..0436cfcb1657f 100644
--- a/code/datums/sprite_accessories.dm
+++ b/code/datums/sprite_accessories.dm
@@ -2264,6 +2264,10 @@
name = "Lightbearer"
icon_state = "lightbearer"
+/datum/sprite_accessory/moth_wings/dipped
+ name = "Dipped"
+ icon_state = "dipped"
+
/datum/sprite_accessory/moth_antennae //Finally splitting the sprite
icon = 'icons/mob/human/species/moth/moth_antennae.dmi'
color_src = null
@@ -2355,6 +2359,10 @@
name = "Lightbearer"
icon_state = "lightbearer"
+/datum/sprite_accessory/moth_antennae/dipped
+ name = "Dipped"
+ icon_state = "dipped"
+
/datum/sprite_accessory/moth_markings // the markings that moths can have. finally something other than the boring tan
icon = 'icons/mob/human/species/moth/moth_markings.dmi'
color_src = null
@@ -2418,3 +2426,7 @@
/datum/sprite_accessory/moth_markings/lightbearer
name = "Lightbearer"
icon_state = "lightbearer"
+
+/datum/sprite_accessory/moth_markings/dipped
+ name = "Dipped"
+ icon_state = "dipped"
diff --git a/code/datums/status_effects/debuffs/fire_stacks.dm b/code/datums/status_effects/debuffs/fire_stacks.dm
index 8a629dc14eff7..648f09f31e95f 100644
--- a/code/datums/status_effects/debuffs/fire_stacks.dm
+++ b/code/datums/status_effects/debuffs/fire_stacks.dm
@@ -339,7 +339,7 @@
/datum/status_effect/fire_handler/wet_stacks/proc/become_slippery()
SIGNAL_HANDLER
- slipperiness = owner.AddComponent(/datum/component/slippery, 5 SECONDS, lube_flags = SLIPPERY_WHEN_LYING_DOWN)
+ slipperiness = owner.AddComponent(/datum/component/slippery, 5 SECONDS, lube_flags = SLIPPERY_WHEN_LYING_DOWN|NO_SLIP_WHEN_WALKING|WEAK_SLIDE)
ADD_TRAIT(owner, TRAIT_NO_SLIP_WATER, TRAIT_STATUS_EFFECT(id))
/datum/status_effect/fire_handler/wet_stacks/proc/no_longer_slippery()
diff --git a/code/datums/weather/weather.dm b/code/datums/weather/weather.dm
index 85e5e74b02fba..fde148c51a8b7 100644
--- a/code/datums/weather/weather.dm
+++ b/code/datums/weather/weather.dm
@@ -51,6 +51,8 @@
var/protect_indoors = FALSE
/// Areas to be affected by the weather, calculated when the weather begins
var/list/impacted_areas = list()
+ /// Areas affected by weather have their blend modes changed
+ var/list/impacted_areas_blend_modes = list()
/// Areas that are protected and excluded from the affected areas.
var/list/protected_areas = list()
/// The list of z-levels that this weather is actively affecting
@@ -102,16 +104,19 @@
SEND_GLOBAL_SIGNAL(COMSIG_WEATHER_TELEGRAPH(type), src)
stage = STARTUP_STAGE
var/list/affectareas = list()
- for(var/V in get_areas(area_type))
- affectareas += V
- for(var/V in protected_areas)
- affectareas -= get_areas(V)
- for(var/V in affectareas)
- var/area/A = V
- if(protect_indoors && !A.outdoors)
+ for(var/area/selected_area as anything in get_areas(area_type))
+ affectareas += selected_area
+ for(var/area/protected_area as anything in protected_areas)
+ affectareas -= get_areas(protected_area)
+ for(var/area/affected_area as anything in affectareas)
+ if(protect_indoors && !affected_area.outdoors)
continue
- if(A.z in impacted_z_levels)
- impacted_areas |= A
+
+ for(var/z in impacted_z_levels)
+ if(length(affected_area.turfs_by_zlevel) >= z && length(affected_area.turfs_by_zlevel[z]))
+ impacted_areas |= affected_area
+ continue
+
weather_duration = rand(weather_duration_lower, weather_duration_upper)
SSweather.processing |= src
update_areas()
@@ -230,8 +235,17 @@
for(var/area/impacted as anything in impacted_areas)
if(length(overlay_cache))
impacted.overlays -= overlay_cache
+ if(impacted_areas_blend_modes[impacted])
+ // revert the blend mode to the old state
+ impacted.blend_mode = impacted_areas_blend_modes[impacted]
+ impacted_areas_blend_modes[impacted] = null
if(length(new_overlay_cache))
impacted.overlays += new_overlay_cache
+ // only change the blend mode if it's not default or overlay
+ if(impacted.blend_mode > BLEND_OVERLAY)
+ // save the old blend mode state
+ impacted_areas_blend_modes[impacted] = impacted.blend_mode
+ impacted.blend_mode = BLEND_OVERLAY
overlay_cache = new_overlay_cache
diff --git a/code/game/machinery/computer/arcade/_arcade.dm b/code/game/machinery/computer/arcade/_arcade.dm
index 053ec907f3e63..eb91fa44f1c70 100644
--- a/code/game/machinery/computer/arcade/_arcade.dm
+++ b/code/game/machinery/computer/arcade/_arcade.dm
@@ -85,7 +85,7 @@
for(var/i in 1 to prizes)
user.add_mood_event("arcade", /datum/mood_event/arcade)
if(prob(0.0001)) //1 in a million
- new /obj/item/gun/energy/pulse/prize(src)
+ new /obj/item/gun/energy/pulse/prize(get_turf(src))
visible_message(span_notice("[src] dispenses.. woah, a gun! Way past cool."), span_notice("You hear a chime and a shot."))
user.client.give_award(/datum/award/achievement/misc/pulse, user)
continue
diff --git a/code/game/machinery/computer/telescreen.dm b/code/game/machinery/computer/telescreen.dm
index 1a79aa267887b..f3a6a9879b4d1 100644
--- a/code/game/machinery/computer/telescreen.dm
+++ b/code/game/machinery/computer/telescreen.dm
@@ -45,8 +45,9 @@
var/icon_state_off = "entertainment_blank"
var/icon_state_on = "entertainment"
-/obj/machinery/vending/add_context(atom/source, list/context, obj/item/held_item, mob/user)
+/obj/machinery/computer/security/telescreen/entertainment/add_context(atom/source, list/context, obj/item/held_item, mob/user)
context[SCREENTIP_CONTEXT_CTRL_LMB] = "Toggle mute button"
+ return CONTEXTUAL_SCREENTIP_SET
/obj/machinery/computer/security/telescreen/entertainment/click_ctrl(mob/user)
. = ..()
@@ -64,6 +65,7 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/computer/security/telescreen/entertai
/obj/machinery/computer/security/telescreen/entertainment/Initialize(mapload)
. = ..()
find_and_hang_on_wall()
+ register_context()
speakers = new(src)
/obj/machinery/computer/security/telescreen/entertainment/Destroy()
diff --git a/code/game/machinery/dna_infuser/organ_sets/fish_organs.dm b/code/game/machinery/dna_infuser/organ_sets/fish_organs.dm
index 67fe3a41f7128..7dda9ba15639d 100644
--- a/code/game/machinery/dna_infuser/organ_sets/fish_organs.dm
+++ b/code/game/machinery/dna_infuser/organ_sets/fish_organs.dm
@@ -8,8 +8,8 @@
id = "organ_set_bonus_fish"
tick_interval = 1 SECONDS
organs_needed = 3
- bonus_activate_text = span_notice("Fish DNA is deeply infused with you! While wet, you crawl faster, are slippery, and cannot slip, and it takes longer to dry out. \
- You're also more resistant to high pressure, better at fishing, but less resilient when dry, especially against burns.")
+ bonus_activate_text = span_notice("Fish DNA is deeply infused with you! While wet, you crawl faster, are slippery, cannot slip, and it takes longer to dry out. \
+ You're also resistant to high pressure, better at fishing, but less resilient when dry, especially against burns.")
bonus_deactivate_text = span_notice("You no longer feel as fishy. The moisture around your body begins to dissipate faster...")
bonus_traits = list(
TRAIT_RESISTHIGHPRESSURE,
@@ -34,6 +34,9 @@
if(ishuman(owner))
var/mob/living/carbon/human/human = owner
+ //Fish is slightly weaker to being cooked. oh oh.
+ human.physiology.burn_mod *= 1.15
+ human.physiology.heat_mod *= 1.15
human.physiology.damage_resistance += 8 //base 8% damage resistance, much wow.
if(!HAS_TRAIT(owner, TRAIT_IS_WET))
apply_debuff()
@@ -61,6 +64,8 @@
owner.clear_mood_event("fish_organs_bonus")
if(ishuman(owner))
var/mob/living/carbon/human/human = owner
+ human.physiology.burn_mod /= 1.15
+ human.physiology.heat_mod /= 1.15
human.physiology.damage_resistance -= 8
if(HAS_TRAIT(owner, TRAIT_IS_WET) && istype(owner.get_organ_slot(ORGAN_SLOT_EXTERNAL_TAIL), /obj/item/organ/tail/fish))
remove_speed_buff()
diff --git a/code/game/objects/effects/overlays.dm b/code/game/objects/effects/overlays.dm
index b90ebe54ffaf2..71817de3a1052 100644
--- a/code/game/objects/effects/overlays.dm
+++ b/code/game/objects/effects/overlays.dm
@@ -28,7 +28,7 @@
name = "thermite"
desc = "Looks hot."
icon = 'icons/effects/fire.dmi'
- icon_state = "2" //what?
+ icon_state = "medium" //what?
anchored = TRUE
plane = ABOVE_GAME_PLANE
layer = FLY_LAYER
diff --git a/code/game/objects/effects/temporary_visuals/miscellaneous.dm b/code/game/objects/effects/temporary_visuals/miscellaneous.dm
index ae2ce27b100f6..f132c7a01537d 100644
--- a/code/game/objects/effects/temporary_visuals/miscellaneous.dm
+++ b/code/game/objects/effects/temporary_visuals/miscellaneous.dm
@@ -57,6 +57,12 @@
icon_state = "firing_effect"
duration = 3
+/obj/effect/temp_visual/dir_setting/firing_effect/Initialize(mapload, set_dir)
+ . = ..()
+ if (ismovable(loc))
+ var/atom/movable/spawned_inside = loc
+ spawned_inside.vis_contents += src
+
/obj/effect/temp_visual/dir_setting/firing_effect/setDir(newdir)
switch(newdir)
if(NORTH)
@@ -245,7 +251,7 @@
/obj/effect/temp_visual/fire
icon = 'icons/effects/fire.dmi'
- icon_state = "3"
+ icon_state = "heavy"
light_range = LIGHT_RANGE_FIRE
light_color = LIGHT_COLOR_FIRE
duration = 10
diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm
index 9efc165485a43..cfc5aa6a5153a 100644
--- a/code/game/objects/items.dm
+++ b/code/game/objects/items.dm
@@ -240,8 +240,10 @@
/// Has the item been reskinned?
var/current_skin
- ///// List of options to reskin.
+ /// List of options to reskin.
var/list/unique_reskin
+ /// If reskins change inhands as well
+ var/unique_reskin_changes_inhand = FALSE
/// Do we apply a click cooldown when resisting this object if it is restraining them?
var/resist_cooldown = CLICK_CD_BREAKOUT
diff --git a/code/game/objects/items/defib.dm b/code/game/objects/items/defib.dm
index dd5d78fce0d61..6ccbaa5fa4454 100644
--- a/code/game/objects/items/defib.dm
+++ b/code/game/objects/items/defib.dm
@@ -365,7 +365,7 @@
if(!req_defib)
return
RegisterSignal(user, COMSIG_MOVABLE_MOVED, PROC_REF(check_range))
- RegisterSignal(defib.loc, COMSIG_MOVABLE_MOVED, PROC_REF(check_range))
+ RegisterSignal(defib, COMSIG_MOVABLE_MOVED, PROC_REF(check_range))
/obj/item/shockpaddles/Moved(atom/old_loc, movement_dir, forced, list/old_locs, momentum_change = TRUE)
. = ..()
@@ -430,9 +430,9 @@
/obj/item/shockpaddles/dropped(mob/user)
. = ..()
+ UnregisterSignal(defib, COMSIG_MOVABLE_MOVED)
if(user)
UnregisterSignal(user, COMSIG_MOVABLE_MOVED)
- UnregisterSignal(defib.loc, COMSIG_MOVABLE_MOVED)
if(req_defib)
if(user)
to_chat(user, span_notice("The paddles snap back into the main unit."))
diff --git a/code/game/objects/items/food/pie.dm b/code/game/objects/items/food/pie.dm
index 6d73bc2f5df21..fae0edd7a2020 100644
--- a/code/game/objects/items/food/pie.dm
+++ b/code/game/objects/items/food/pie.dm
@@ -430,6 +430,7 @@
icon_state = "baklavaslice"
tastes = list("nuts" = 1, "pie" = 1)
foodtypes = NUTS | SUGAR
+ crafting_complexity = FOOD_COMPLEXITY_4
/obj/item/food/pie/frenchsilkpie
name = "french silk pie"
diff --git a/code/game/objects/items_reskin.dm b/code/game/objects/items_reskin.dm
index f8bffa7bf5f63..b73df0a487b72 100644
--- a/code/game/objects/items_reskin.dm
+++ b/code/game/objects/items_reskin.dm
@@ -64,6 +64,8 @@
return
current_skin = pick
icon_state = unique_reskin[pick]
+ if (unique_reskin_changes_inhand)
+ inhand_icon_state = icon_state
to_chat(user, "[src] is now skinned as '[pick].'")
SEND_SIGNAL(src, COMSIG_OBJ_RESKIN, user, pick)
diff --git a/code/game/objects/obj_defense.dm b/code/game/objects/obj_defense.dm
index 77f670bf9fc92..45bc7f9110636 100644
--- a/code/game/objects/obj_defense.dm
+++ b/code/game/objects/obj_defense.dm
@@ -1,7 +1,11 @@
-/obj/hitby(atom/movable/AM, skipcatch, hitpush, blocked, datum/thrownthing/throwingdatum)
+/obj/hitby(atom/movable/hit_by, skipcatch, hitpush, blocked, datum/thrownthing/throwingdatum)
..()
- take_damage(AM.throwforce, BRUTE, MELEE, 1, get_dir(src, AM))
+ var/damage_taken = hit_by.throwforce
+ if(isitem(hit_by))
+ var/obj/item/as_item = hit_by
+ damage_taken *= as_item.demolition_mod
+ take_damage(damage_taken, BRUTE, MELEE, 1, get_dir(src, hit_by))
/obj/ex_act(severity, target)
if(resistance_flags & INDESTRUCTIBLE)
diff --git a/code/game/turfs/open/_open.dm b/code/game/turfs/open/_open.dm
index c2b9963c5ed41..06d71c37a15a9 100644
--- a/code/game/turfs/open/_open.dm
+++ b/code/game/turfs/open/_open.dm
@@ -354,13 +354,15 @@
if(lube & SLIDE_ICE)
// Ice slides only go 1 tile, this is so you will slip across ice until you reach a non-slip tile
slide_distance = 1
- else if(HAS_TRAIT(slipper, TRAIT_CURSED))
+ else if(HAS_TRAIT(slipper, TRAIT_CURSED) && !(lube & WEAK_SLIDE))
// When cursed, all slips send you flying
lube |= SLIDE
slide_distance = rand(5, 9)
else if(HAS_TRAIT(slipper, TRAIT_NO_SLIP_SLIDE))
// Stops sliding
slide_distance = 0
+ else if(lube & WEAK_SLIDE)
+ slide_distance = rand(1, 2)
var/obj/buckled_obj
if(slipper.buckled)
@@ -390,10 +392,12 @@
// They need to be kept upright to maintain the combo effect (So don't knockdown)
slipper.Immobilize(1 SECONDS)
slipper.incapacitate(1 SECONDS)
+ else if(lube & WEAK_SLIDE)
+ slipper.adjust_staggered_up_to(STAGGERED_SLOWDOWN_LENGTH, 10 SECONDS)
+ slipper.stop_pulling()
else
slipper.Knockdown(knockdown_amount)
slipper.Paralyze(paralyze_amount)
- slipper.stop_pulling()
if(buckled_obj)
buckled_obj.unbuckle_mob(slipper)
@@ -403,7 +407,7 @@
if(slide_distance)
var/turf/target = get_ranged_target_turf(slipper, olddir, slide_distance)
- if(lube & SLIDE)
+ if(lube & (SLIDE|WEAK_SLIDE))
slipper.AddComponent(/datum/component/force_move, target, TRUE)
else if(lube & SLIDE_ICE)
slipper.AddComponent(/datum/component/force_move, target, FALSE)//spinning would be bad for ice, fucks up the next dir
diff --git a/code/game/turfs/turf.dm b/code/game/turfs/turf.dm
index 9fffce4b28f51..aab0f609d0e3f 100644
--- a/code/game/turfs/turf.dm
+++ b/code/game/turfs/turf.dm
@@ -821,8 +821,8 @@ GLOBAL_LIST_EMPTY(station_turfs)
/turf/proc/add_fishing_spot_comp(datum/source)
SIGNAL_HANDLER
- remove_lazy_fishing()
source.AddComponent(/datum/component/fishing_spot, fish_source)
+ remove_lazy_fishing()
/turf/proc/on_npc_fishing(datum/source, list/fish_spot_container)
SIGNAL_HANDLER
diff --git a/code/modules/antagonists/changeling/powers/absorb.dm b/code/modules/antagonists/changeling/powers/absorb.dm
index 167371b4d675d..d8ebc7c599803 100644
--- a/code/modules/antagonists/changeling/powers/absorb.dm
+++ b/code/modules/antagonists/changeling/powers/absorb.dm
@@ -7,6 +7,7 @@
req_human = TRUE
///if we're currently absorbing, used for sanity
var/is_absorbing = FALSE
+ var/datum/looping_sound/changeling_absorb/absorbing_loop
/datum/action/changeling/absorb_dna/can_sting(mob/living/carbon/owner)
if(!..())
@@ -59,6 +60,7 @@
if(target.mind && owner.mind)//if the victim and owner have minds
absorb_memories(target)
+ qdel(absorbing_loop)
is_absorbing = FALSE
changeling.adjust_chemicals(10)
@@ -146,6 +148,7 @@
if(2)
owner.visible_message(span_warning("[owner] extends a proboscis!"), span_notice("We extend a proboscis."))
if(3)
+ absorbing_loop = new(owner, start_immediately = TRUE)
owner.visible_message(span_danger("[owner] stabs [target] with the proboscis!"), span_notice("We stab [target] with the proboscis."))
to_chat(target, span_userdanger("You feel a sharp stabbing pain!"))
target.take_overall_damage(40)
@@ -153,6 +156,7 @@
SSblackbox.record_feedback("nested tally", "changeling_powers", 1, list("Absorb DNA", "[absorbing_iteration]"))
if(!do_after(owner, 15 SECONDS, target, hidden = TRUE))
owner.balloon_alert(owner, "interrupted!")
+ qdel(absorbing_loop)
is_absorbing = FALSE
return FALSE
return TRUE
diff --git a/code/modules/antagonists/heretic/heretic_antag.dm b/code/modules/antagonists/heretic/heretic_antag.dm
index fe7a6f1b125b4..8466eaf3130f2 100644
--- a/code/modules/antagonists/heretic/heretic_antag.dm
+++ b/code/modules/antagonists/heretic/heretic_antag.dm
@@ -7,6 +7,8 @@
* Used in creating spooky-text for heretic ascension announcements.
*/
/proc/generate_heretic_text(length = 25)
+ if(!isnum(length)) // stupid thing so we can use this directly in replacetext
+ length = 25
. = ""
for(var/i in 1 to length)
. += pick("!", "$", "^", "@", "&", "#", "*", "(", ")", "?")
diff --git a/code/modules/antagonists/heretic/heretic_knowledge.dm b/code/modules/antagonists/heretic/heretic_knowledge.dm
index 0e445c862f495..a0d77682cd8d4 100644
--- a/code/modules/antagonists/heretic/heretic_knowledge.dm
+++ b/code/modules/antagonists/heretic/heretic_knowledge.dm
@@ -665,8 +665,14 @@
cost = 2
priority = MAX_KNOWLEDGE_PRIORITY + 1 // Yes, the final ritual should be ABOVE the max priority.
required_atoms = list(/mob/living/carbon/human = 3)
- //use this to store the achievement typepath
+ /// The typepath of the achievement to grant upon successful ascension.
var/datum/award/achievement/misc/ascension_achievement
+ /// The text of the ascension announcement.
+ /// %NAME% is replaced with the heretic's real name,
+ /// and %SPOOKY% is replaced with output from [generate_heretic_text]
+ var/announcement_text
+ /// The sound that's played for the ascension announcement.
+ var/announcement_sound
/datum/heretic_knowledge/ultimate/on_research(mob/user, datum/antagonist/heretic/our_heretic)
. = ..()
@@ -727,6 +733,13 @@
source = user,
header = "A Heretic is Ascending!",
)
+ priority_announce(
+ text = replacetext(replacetext(announcement_text, "%NAME%", user.real_name), "%SPOOKY%", GLOBAL_PROC_REF(generate_heretic_text)),
+ title = generate_heretic_text(),
+ sound = announcement_sound,
+ color_override = "pink",
+ )
+
if(!isnull(ascension_achievement))
user.client?.give_award(ascension_achievement, user)
heretic_datum.increase_rust_strength()
diff --git a/code/modules/antagonists/heretic/knowledge/ash_lore.dm b/code/modules/antagonists/heretic/knowledge/ash_lore.dm
index 3b5b80a621461..9d657c7b3e726 100644
--- a/code/modules/antagonists/heretic/knowledge/ash_lore.dm
+++ b/code/modules/antagonists/heretic/knowledge/ash_lore.dm
@@ -163,6 +163,8 @@
WITNESS MY ASCENSION, THE ASHY LANTERN BLAZES ONCE MORE!"
ascension_achievement = /datum/award/achievement/misc/ash_ascension
+ announcement_text = "%SPOOKY% Fear the blaze, for the Ashlord, %NAME% has ascended! The flames shall consume all! %SPOOKY%"
+ announcement_sound = 'sound/music/antag/heretic/ascend_ash.ogg'
/// A static list of all traits we apply on ascension.
var/static/list/traits_to_apply = list(
TRAIT_BOMBIMMUNE,
@@ -187,13 +189,6 @@
/datum/heretic_knowledge/ultimate/ash_final/on_finished_recipe(mob/living/user, list/selected_atoms, turf/loc)
. = ..()
- priority_announce(
- text = "[generate_heretic_text()] Fear the blaze, for the Ashlord, [user.real_name] has ascended! The flames shall consume all! [generate_heretic_text()]",
- title = "[generate_heretic_text()]",
- sound = 'sound/music/antag/heretic/ascend_ash.ogg',
- color_override = "pink",
- )
-
var/datum/action/cooldown/spell/fire_sworn/circle_spell = new(user.mind)
circle_spell.Grant(user)
@@ -209,5 +204,4 @@
var/datum/action/cooldown/spell/aoe/fiery_rebirth/fiery_rebirth = locate() in user.actions
fiery_rebirth?.cooldown_time *= 0.16
- if(length(traits_to_apply))
- user.add_traits(traits_to_apply, MAGIC_TRAIT)
+ user.add_traits(traits_to_apply, type)
diff --git a/code/modules/antagonists/heretic/knowledge/blade_lore.dm b/code/modules/antagonists/heretic/knowledge/blade_lore.dm
index dcca07b00af70..993aa20c4287e 100644
--- a/code/modules/antagonists/heretic/knowledge/blade_lore.dm
+++ b/code/modules/antagonists/heretic/knowledge/blade_lore.dm
@@ -380,6 +380,8 @@
I AM UNMATCHED! A STORM OF STEEL AND SILVER IS UPON US! WITNESS MY ASCENSION!"
ascension_achievement = /datum/award/achievement/misc/blade_ascension
+ announcement_text = "%SPOOKY% Master of blades, the Torn Champion's disciple, %NAME% has ascended! Their steel is that which will cut reality in a maelstom of silver! %SPOOKY%"
+ announcement_sound = 'sound/music/antag/heretic/ascend_blade.ogg'
/datum/heretic_knowledge/ultimate/blade_final/is_valid_sacrifice(mob/living/carbon/human/sacrifice)
. = ..()
@@ -390,13 +392,7 @@
/datum/heretic_knowledge/ultimate/blade_final/on_finished_recipe(mob/living/user, list/selected_atoms, turf/loc)
. = ..()
- priority_announce(
- text = "[generate_heretic_text()] Master of blades, the Torn Champion's disciple, [user.real_name] has ascended! Their steel is that which will cut reality in a maelstom of silver! [generate_heretic_text()]",
- title = "[generate_heretic_text()]",
- sound = 'sound/music/antag/heretic/ascend_blade.ogg',
- color_override = "pink",
- )
- ADD_TRAIT(user, TRAIT_NEVER_WOUNDED, name)
+ ADD_TRAIT(user, TRAIT_NEVER_WOUNDED, type)
RegisterSignal(user, COMSIG_HERETIC_BLADE_ATTACK, PROC_REF(on_eldritch_blade))
user.apply_status_effect(/datum/status_effect/protective_blades/recharging, null, 8, 30, 0.25 SECONDS, /obj/effect/floating_blade, 1 MINUTES)
user.add_stun_absorption(
diff --git a/code/modules/antagonists/heretic/knowledge/cosmic_lore.dm b/code/modules/antagonists/heretic/knowledge/cosmic_lore.dm
index 90fe514cde946..d545e258a302e 100644
--- a/code/modules/antagonists/heretic/knowledge/cosmic_lore.dm
+++ b/code/modules/antagonists/heretic/knowledge/cosmic_lore.dm
@@ -219,6 +219,8 @@
WITNESS MY ASCENSION!"
ascension_achievement = /datum/award/achievement/misc/cosmic_ascension
+ announcement_text = "%SPOOKY% A Star Gazer has arrived into the station, %NAME% has ascended! This station is the domain of the Cosmos! %SPOOKY%"
+ announcement_sound = 'sound/music/antag/heretic/ascend_cosmic.ogg'
/// A static list of command we can use with our mob.
var/static/list/star_gazer_commands = list(
/datum/pet_command/idle,
@@ -236,12 +238,6 @@
/datum/heretic_knowledge/ultimate/cosmic_final/on_finished_recipe(mob/living/user, list/selected_atoms, turf/loc)
. = ..()
- priority_announce(
- text = "[generate_heretic_text()] A Star Gazer has arrived into the station, [user.real_name] has ascended! This station is the domain of the Cosmos! [generate_heretic_text()]",
- title = "[generate_heretic_text()]",
- sound = 'sound/music/antag/heretic/ascend_cosmic.ogg',
- color_override = "pink",
- )
var/mob/living/basic/heretic_summon/star_gazer/star_gazer_mob = new /mob/living/basic/heretic_summon/star_gazer(loc)
star_gazer_mob.maxHealth = INFINITY
star_gazer_mob.health = INFINITY
diff --git a/code/modules/antagonists/heretic/knowledge/flesh_lore.dm b/code/modules/antagonists/heretic/knowledge/flesh_lore.dm
index 57e60c46b6367..cfcd6ea9ceda1 100644
--- a/code/modules/antagonists/heretic/knowledge/flesh_lore.dm
+++ b/code/modules/antagonists/heretic/knowledge/flesh_lore.dm
@@ -288,20 +288,14 @@
Reality will bend to THE LORD OF THE NIGHT or be unraveled! WITNESS MY ASCENSION!"
required_atoms = list(/mob/living/carbon/human = 4)
ascension_achievement = /datum/award/achievement/misc/flesh_ascension
+ announcement_text = "%SPOOKY% Ever coiling vortex. Reality unfolded. ARMS OUTREACHED, THE LORD OF THE NIGHT, %NAME% has ascended! Fear the ever twisting hand! %SPOOKY%"
+ announcement_sound = 'sound/music/antag/heretic/ascend_flesh.ogg'
/datum/heretic_knowledge/ultimate/flesh_final/on_finished_recipe(mob/living/user, list/selected_atoms, turf/loc)
. = ..()
- priority_announce(
- text = "[generate_heretic_text()] Ever coiling vortex. Reality unfolded. ARMS OUTREACHED, THE LORD OF THE NIGHT, [user.real_name] has ascended! Fear the ever twisting hand! [generate_heretic_text()]",
- title = "[generate_heretic_text()]",
- sound = 'sound/music/antag/heretic/ascend_flesh.ogg',
- color_override = "pink",
- )
-
var/datum/action/cooldown/spell/shapeshift/shed_human_form/worm_spell = new(user.mind)
worm_spell.Grant(user)
-
var/datum/antagonist/heretic/heretic_datum = GET_HERETIC(user)
var/datum/heretic_knowledge/limited_amount/flesh_grasp/grasp_ghoul = heretic_datum.get_knowledge(/datum/heretic_knowledge/limited_amount/flesh_grasp)
grasp_ghoul.limit *= 3
diff --git a/code/modules/antagonists/heretic/knowledge/lock_lore.dm b/code/modules/antagonists/heretic/knowledge/lock_lore.dm
index 6333e9a8fa4fc..96c6110f6df79 100644
--- a/code/modules/antagonists/heretic/knowledge/lock_lore.dm
+++ b/code/modules/antagonists/heretic/knowledge/lock_lore.dm
@@ -176,6 +176,8 @@
The Labyrinth will be Locked no more, and freedom will be ours! WITNESS US!"
required_atoms = list(/mob/living/carbon/human = 3)
ascension_achievement = /datum/award/achievement/misc/lock_ascension
+ announcement_text = "Delta-class dimensional anomaly detec%SPOOKY% Reality rended, torn. Gates open, doors open, %NAME% has ascended! Fear the tide! %SPOOKY%"
+ announcement_sound = 'sound/music/antag/heretic/ascend_knock.ogg'
/datum/heretic_knowledge/ultimate/lock_final/recipe_snowflake_check(mob/living/user, list/atoms, list/selected_atoms, turf/loc)
. = ..()
@@ -198,13 +200,6 @@
/datum/heretic_knowledge/ultimate/lock_final/on_finished_recipe(mob/living/user, list/selected_atoms, turf/loc)
. = ..()
- priority_announce(
- text = "Delta-class dimensional anomaly detec[generate_heretic_text()] Reality rended, torn. Gates open, doors open, [user.real_name] has ascended! Fear the tide! [generate_heretic_text()]",
- title = "[generate_heretic_text()]",
- sound = 'sound/music/antag/heretic/ascend_knock.ogg',
- color_override = "pink",
- )
-
// buffs
var/datum/action/cooldown/spell/shapeshift/eldritch/ascension/transform_spell = new(user.mind)
transform_spell.Grant(user)
diff --git a/code/modules/antagonists/heretic/knowledge/moon_lore.dm b/code/modules/antagonists/heretic/knowledge/moon_lore.dm
index 9628305f50b46..c5a6930eab799 100644
--- a/code/modules/antagonists/heretic/knowledge/moon_lore.dm
+++ b/code/modules/antagonists/heretic/knowledge/moon_lore.dm
@@ -162,6 +162,9 @@
WITNESS MY ASCENSION, THE MOON SMILES ONCE MORE AND FOREVER MORE IT SHALL!"
ascension_achievement = /datum/award/achievement/misc/moon_ascension
+ announcement_text = "%SPOOKY% Laugh, for the ringleader %NAME% has ascended! \
+ The truth shall finally devour the lie! %SPOOKY%"
+ announcement_sound = 'sound/music/antag/heretic/ascend_moon.ogg'
/datum/heretic_knowledge/ultimate/moon_final/is_valid_sacrifice(mob/living/sacrifice)
@@ -174,15 +177,7 @@
/datum/heretic_knowledge/ultimate/moon_final/on_finished_recipe(mob/living/user, list/selected_atoms, turf/loc)
. = ..()
- priority_announce(
- text = "[generate_heretic_text()] Laugh, for the ringleader [user.real_name] has ascended! \
- The truth shall finally devour the lie! [generate_heretic_text()]",
- title = "[generate_heretic_text()]",
- sound = 'sound/music/antag/heretic/ascend_moon.ogg',
- color_override = "pink",
- )
-
- ADD_TRAIT(user, TRAIT_MADNESS_IMMUNE, REF(src))
+ ADD_TRAIT(user, TRAIT_MADNESS_IMMUNE, type)
user.mind.add_antag_datum(/datum/antagonist/lunatic/master)
RegisterSignal(user, COMSIG_LIVING_LIFE, PROC_REF(on_life))
diff --git a/code/modules/antagonists/heretic/knowledge/rust_lore.dm b/code/modules/antagonists/heretic/knowledge/rust_lore.dm
index f624767f33e82..41db760f53ae6 100644
--- a/code/modules/antagonists/heretic/knowledge/rust_lore.dm
+++ b/code/modules/antagonists/heretic/knowledge/rust_lore.dm
@@ -168,6 +168,8 @@
The Blacksmith forges ahead! Rusted Hills, CALL MY NAME! WITNESS MY ASCENSION!"
ascension_achievement = /datum/award/achievement/misc/rust_ascension
+ announcement_text = "%SPOOKY% Fear the decay, for the Rustbringer, %NAME% has ascended! None shall escape the corrosion! %SPOOKY%"
+ announcement_sound = 'sound/music/antag/heretic/ascend_rust.ogg'
/// If TRUE, then immunities are currently active.
var/immunities_active = FALSE
/// A typepath to an area that we must finish the ritual in.
@@ -208,12 +210,6 @@
/datum/heretic_knowledge/ultimate/rust_final/on_finished_recipe(mob/living/user, list/selected_atoms, turf/loc)
. = ..()
- priority_announce(
- text = "[generate_heretic_text()] Fear the decay, for the Rustbringer, [user.real_name] has ascended! None shall escape the corrosion! [generate_heretic_text()]",
- title = "[generate_heretic_text()]",
- sound = 'sound/music/antag/heretic/ascend_rust.ogg',
- color_override = "pink",
- )
trigger(loc)
RegisterSignal(user, COMSIG_MOVABLE_MOVED, PROC_REF(on_move))
RegisterSignal(user, COMSIG_LIVING_LIFE, PROC_REF(on_life))
diff --git a/code/modules/antagonists/heretic/knowledge/void_lore.dm b/code/modules/antagonists/heretic/knowledge/void_lore.dm
index 14e2ffe0e9ad5..0bb54d6d15798 100644
--- a/code/modules/antagonists/heretic/knowledge/void_lore.dm
+++ b/code/modules/antagonists/heretic/knowledge/void_lore.dm
@@ -180,6 +180,8 @@
as the world is destroyed before our eyes. The void will return all to nothing, WITNESS MY ASCENSION!"
ascension_achievement = /datum/award/achievement/misc/void_ascension
+ announcement_text = "%SPOOKY% The nobleman of void %NAME% has arrived, stepping along the Waltz that ends worlds! %SPOOKY%"
+ announcement_sound = 'sound/music/antag/heretic/ascend_void.ogg'
///soundloop for the void theme
var/datum/looping_sound/void_loop/sound_loop
///Reference to the ongoing voidstrom that surrounds the heretic
@@ -201,13 +203,7 @@
/datum/heretic_knowledge/ultimate/void_final/on_finished_recipe(mob/living/user, list/selected_atoms, turf/loc)
. = ..()
- priority_announce(
- text = "[generate_heretic_text()] The nobleman of void [user.real_name] has arrived, stepping along the Waltz that ends worlds! [generate_heretic_text()]",
- title = "[generate_heretic_text()]",
- sound = 'sound/music/antag/heretic/ascend_void.ogg',
- color_override = "pink",
- )
- user.add_traits(list(TRAIT_RESISTLOWPRESSURE, TRAIT_NEGATES_GRAVITY, TRAIT_MOVE_FLYING, TRAIT_FREE_HYPERSPACE_MOVEMENT), MAGIC_TRAIT)
+ user.add_traits(list(TRAIT_RESISTLOWPRESSURE, TRAIT_NEGATES_GRAVITY, TRAIT_MOVE_FLYING, TRAIT_FREE_HYPERSPACE_MOVEMENT), type)
// Let's get this show on the road!
sound_loop = new(user, TRUE, TRUE)
diff --git a/code/modules/atmospherics/environmental/LINDA_fire.dm b/code/modules/atmospherics/environmental/LINDA_fire.dm
index c2ffe56fc5769..ae6054c042fe3 100644
--- a/code/modules/atmospherics/environmental/LINDA_fire.dm
+++ b/code/modules/atmospherics/environmental/LINDA_fire.dm
@@ -94,7 +94,7 @@
anchored = TRUE
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
icon = 'icons/effects/fire.dmi'
- icon_state = "1"
+ icon_state = "light"
layer = GASFIRE_LAYER
plane = ABOVE_GAME_PLANE
blend_mode = BLEND_ADD
diff --git a/code/modules/food_and_drinks/machinery/coffeemaker.dm b/code/modules/food_and_drinks/machinery/coffeemaker.dm
index c6f8ba92f2af6..51280fd87d6d8 100644
--- a/code/modules/food_and_drinks/machinery/coffeemaker.dm
+++ b/code/modules/food_and_drinks/machinery/coffeemaker.dm
@@ -128,7 +128,7 @@
. = ..()
if(. == SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN)
return
- if(!can_interact(user) || !user.can_perform_action(src, ALLOW_SILICON_REACH|FORBID_TELEKINESIS_REACH))
+ if(!can_interact(user) || !user.can_perform_action(src, FORBID_TELEKINESIS_REACH|SILENT_ADJACENCY))
return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN
if(brewing)
return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN
@@ -285,7 +285,7 @@
/obj/machinery/coffeemaker/ui_interact(mob/user) // The microwave Menu //I am reasonably certain that this is not a microwave //I am positively certain that this is not a microwave
. = ..()
- if(brewing || !user.can_perform_action(src, ALLOW_SILICON_REACH))
+ if(brewing || !user.can_perform_action(src, SILENT_ADJACENCY))
return
var/list/options = list()
@@ -325,7 +325,7 @@
choice = show_radial_menu(user, src, options, require_near = !HAS_SILICON_ACCESS(user))
// post choice verification
- if(brewing || (isAI(user) && machine_stat & NOPOWER) || !user.can_perform_action(src, ALLOW_SILICON_REACH))
+ if(brewing || (isAI(user) && machine_stat & NOPOWER) || !user.can_perform_action(src, SILENT_ADJACENCY))
return
switch(choice)
diff --git a/code/modules/meteors/meteor_types.dm b/code/modules/meteors/meteor_types.dm
index ba135081532da..287a93821aebd 100644
--- a/code/modules/meteors/meteor_types.dm
+++ b/code/modules/meteors/meteor_types.dm
@@ -76,8 +76,12 @@
if(!isatom(chasing))
return
var/datum/move_loop/new_loop = GLOB.move_manager.move_towards(src, chasing, delay, home, lifetime)
- if(!new_loop)
- return
+ if(new_loop)
+ RegisterSignal(new_loop, COMSIG_MOVELOOP_STOP, PROC_REF(on_loop_stopped))
+
+/obj/effect/meteor/proc/on_loop_stopped(datum/source)
+ SIGNAL_HANDLER
+ qdel(src)
///Deals with what happens when we stop moving, IE we die
/obj/effect/meteor/proc/moved_off_z()
diff --git a/code/modules/mob/living/basic/icemoon/ice_whelp/ice_whelp_abilities.dm b/code/modules/mob/living/basic/icemoon/ice_whelp/ice_whelp_abilities.dm
index d4a05bf227ede..617295ef6ba56 100644
--- a/code/modules/mob/living/basic/icemoon/ice_whelp/ice_whelp_abilities.dm
+++ b/code/modules/mob/living/basic/icemoon/ice_whelp/ice_whelp_abilities.dm
@@ -23,7 +23,7 @@
name = "Fire all directions"
desc = "Unleash lines of cold fire in all directions"
button_icon = 'icons/effects/fire.dmi'
- button_icon_state = "1"
+ button_icon_state = "light"
cooldown_time = 4 SECONDS
click_to_activate = FALSE
fire_range = 6
diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/drake.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/drake.dm
index 1e539bcd05625..a5feaad351fd3 100644
--- a/code/modules/mob/living/simple_animal/hostile/megafauna/drake.dm
+++ b/code/modules/mob/living/simple_animal/hostile/megafauna/drake.dm
@@ -237,7 +237,7 @@
desc = "An ash drakes true flame."
name = "Fire Barrier"
icon = 'icons/effects/fire.dmi'
- icon_state = "1"
+ icon_state = "light"
anchored = TRUE
opacity = FALSE
density = TRUE
diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm
index b736d8184060f..0ff10d1f1dcd3 100644
--- a/code/modules/mob/mob.dm
+++ b/code/modules/mob/mob.dm
@@ -624,7 +624,7 @@
return
/mob/living/handle_eye_contact(mob/living/examined_mob)
- if(!istype(examined_mob) || src == examined_mob || examined_mob.stat >= UNCONSCIOUS || !client)
+ if(!istype(examined_mob) || src == examined_mob || examined_mob.stat >= UNCONSCIOUS || !client || is_blind())
return
var/imagined_eye_contact = FALSE
@@ -640,12 +640,16 @@
// check to see if their face is blocked or, if not, a signal blocks it
if(examined_mob.is_face_visible() && SEND_SIGNAL(src, COMSIG_MOB_EYECONTACT, examined_mob, TRUE) != COMSIG_BLOCK_EYECONTACT)
- var/msg = span_smallnotice("You make eye contact with [examined_mob].")
- addtimer(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(to_chat), src, msg), 0.3 SECONDS) // so the examine signal has time to fire and this will print after
-
- if(!imagined_eye_contact && is_face_visible() && SEND_SIGNAL(examined_mob, COMSIG_MOB_EYECONTACT, src, FALSE) != COMSIG_BLOCK_EYECONTACT)
- var/msg = span_smallnotice("[src] makes eye contact with you.")
- addtimer(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(to_chat), examined_mob, msg), 0.3 SECONDS)
+ var/obj/item/clothing/eye_cover = examined_mob.is_eyes_covered()
+ if (!eye_cover || (!eye_cover.tint && !eye_cover.flash_protect))
+ var/msg = span_smallnotice("You make eye contact with [examined_mob].")
+ addtimer(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(to_chat), src, msg), 0.3 SECONDS) // so the examine signal has time to fire and this will print after
+
+ if(!imagined_eye_contact && is_face_visible() && !examined_mob.is_blind() && SEND_SIGNAL(examined_mob, COMSIG_MOB_EYECONTACT, src, FALSE) != COMSIG_BLOCK_EYECONTACT)
+ var/obj/item/clothing/eye_cover = is_eyes_covered()
+ if (!eye_cover || (!eye_cover.tint && !eye_cover.flash_protect))
+ var/msg = span_smallnotice("[src] makes eye contact with you.")
+ addtimer(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(to_chat), examined_mob, msg), 0.3 SECONDS)
/**
* Called by using Activate Held Object with an empty hand/limb
diff --git a/code/modules/mod/modules/modules_maint.dm b/code/modules/mod/modules/modules_maint.dm
index cd5a575302d9f..124deb1bd66c6 100644
--- a/code/modules/mod/modules/modules_maint.dm
+++ b/code/modules/mod/modules/modules_maint.dm
@@ -318,11 +318,15 @@
if(istype(current_turf))
current_turf.zFall(mod.wearer, falling_from_move = TRUE)
-/obj/item/mod/module/atrocinator/proc/check_upstairs()
+/obj/item/mod/module/atrocinator/proc/check_upstairs(atom/movable/source, atom/oldloc, direction, forced, list/old_locs, momentum_change)
SIGNAL_HANDLER
if(you_fucked_up || mod.wearer.has_gravity() > NEGATIVE_GRAVITY)
return
+
+ if (forced || SHOULD_DISABLE_FOOTSTEPS(mod.wearer))
+ return
+
var/turf/open/current_turf = get_turf(mod.wearer)
var/turf/open/openspace/turf_above = get_step_multiz(mod.wearer, UP)
if(current_turf && istype(turf_above))
diff --git a/code/modules/paperwork/clipboard.dm b/code/modules/paperwork/clipboard.dm
index 7750b3926465f..968a093684b60 100644
--- a/code/modules/paperwork/clipboard.dm
+++ b/code/modules/paperwork/clipboard.dm
@@ -19,6 +19,7 @@
"Black" = "clipboard_black",
"White" = "clipboard_white",
)
+ unique_reskin_changes_inhand = TRUE
/// The stored pen
var/obj/item/pen/pen
diff --git a/code/modules/projectiles/ammunition/_firing.dm b/code/modules/projectiles/ammunition/_firing.dm
index 5ea2da3513d75..5a704354ed3cb 100644
--- a/code/modules/projectiles/ammunition/_firing.dm
+++ b/code/modules/projectiles/ammunition/_firing.dm
@@ -83,7 +83,7 @@
if(loaded_projectile.firer)
firing_dir = get_dir(fired_from, target)
if(!loaded_projectile.suppressed && firing_effect_type && !tk_firing(user, fired_from))
- new firing_effect_type(get_turf(src), firing_dir)
+ new firing_effect_type(user || get_turf(src), firing_dir)
var/direct_target
if(target && curloc.Adjacent(targloc, target=targloc, mover=src)) //if the target is right on our location or adjacent (including diagonally if reachable) we'll skip the travelling code in the proj's fire()
diff --git a/code/modules/projectiles/projectile.dm b/code/modules/projectiles/projectile.dm
index cbe396e07735f..f5c62e1d05986 100644
--- a/code/modules/projectiles/projectile.dm
+++ b/code/modules/projectiles/projectile.dm
@@ -610,7 +610,7 @@
var/mob/living/living_target = target
living_target.block_projectile_effects()
return FALSE
- if(!ignore_source_check && firer)
+ if(!ignore_source_check && firer && !direct_target)
if(target == firer || (target == firer.loc && ismecha(firer.loc)) || (target in firer.buckled_mobs))
return FALSE
if(ismob(firer))
diff --git a/code/modules/projectiles/projectile/special/temperature.dm b/code/modules/projectiles/projectile/special/temperature.dm
index 43d7968b9ae72..ce95ff585e07e 100644
--- a/code/modules/projectiles/projectile/special/temperature.dm
+++ b/code/modules/projectiles/projectile/special/temperature.dm
@@ -36,6 +36,13 @@
icon_state = "lava"
temperature = 100 // Raise the body temp by 100 points
+/obj/projectile/temp/hot/on_hit(atom/target, blocked = FALSE, pierce_hit)
+ . = ..()
+
+ if(isliving(target))
+ var/mob/living/living_target = target
+ living_target.adjust_wet_stacks(-10)
+
/obj/projectile/temp/cryo
name = "cryo beam"
range = 9
diff --git a/code/modules/reagents/chemistry/machinery/reagentgrinder.dm b/code/modules/reagents/chemistry/machinery/reagentgrinder.dm
index 7716784e4b438..7bf1c06541f38 100644
--- a/code/modules/reagents/chemistry/machinery/reagentgrinder.dm
+++ b/code/modules/reagents/chemistry/machinery/reagentgrinder.dm
@@ -90,10 +90,14 @@
for(var/obj/item/target in src)
if((target in component_parts) || target == beaker)
continue
- to_process["[target.name]"] += 1
+ var/amount = 1
+ if (isstack(target))
+ var/obj/item/stack/target_stack = target
+ amount = target_stack.amount
+ to_process["[target.name]"] += amount
total_weight += target.w_class
if(to_process.len)
- . += span_notice("Currently holding.")
+ . += span_notice("Currently holding:")
for(var/target_name as anything in to_process)
. += span_notice("[to_process[target_name]] [target_name]")
. += span_notice("Filled to [round((total_weight / maximum_weight) * 100)]% capacity.")
diff --git a/code/modules/surgery/organs/_organ.dm b/code/modules/surgery/organs/_organ.dm
index b8784dfdea036..1f036ad3be9bb 100644
--- a/code/modules/surgery/organs/_organ.dm
+++ b/code/modules/surgery/organs/_organ.dm
@@ -85,6 +85,7 @@ INITIALIZE_IMMEDIATE(/obj/item/organ)
if(bodypart_overlay)
setup_bodypart_overlay()
+ START_PROCESSING(SSobj, src)
/obj/item/organ/Destroy()
if(bodypart_owner && !owner && !QDELETED(bodypart_owner))
@@ -136,14 +137,43 @@ INITIALIZE_IMMEDIATE(/obj/item/organ)
if(!IS_ROBOTIC_ORGAN(src) && (clean_types & CLEAN_TYPE_BLOOD))
add_blood_DNA(blood_dna_info)
-/obj/item/organ/process(seconds_per_tick, times_fired)
- return
+/obj/item/organ/proc/on_death(seconds_per_tick, times_fired) //runs decay when outside of a person
+ if(organ_flags & (ORGAN_ROBOTIC | ORGAN_FROZEN))
+ return
-/obj/item/organ/proc/on_death(seconds_per_tick, times_fired)
- return
+ if(owner)
+ if(owner.bodytemperature > T0C)
+ var/air_temperature_factor = min((owner.bodytemperature - T0C) / 20, 1)
+ apply_organ_damage(decay_factor * maxHealth * seconds_per_tick * air_temperature_factor)
+ else
+ var/datum/gas_mixture/exposed_air = return_air()
+ if(exposed_air && exposed_air.temperature > T0C)
+ var/air_temperature_factor = min((exposed_air.temperature - T0C) / 20, 1)
+ apply_organ_damage(decay_factor * maxHealth * seconds_per_tick * air_temperature_factor)
-/obj/item/organ/proc/on_life(seconds_per_tick, times_fired)
- return
+/obj/item/organ/proc/on_life(seconds_per_tick, times_fired) //repair organ damage if the organ is not failing
+ if(organ_flags & ORGAN_FAILING)
+ handle_failing_organs(seconds_per_tick)
+ return
+
+ if(failure_time > 0)
+ failure_time--
+
+ if(organ_flags & ORGAN_EMP) //Synthetic organ has been emped, is now failing.
+ apply_organ_damage(decay_factor * maxHealth * seconds_per_tick)
+ return
+
+ if(!damage) // No sense healing if you're not even hurt bro
+ return
+
+ if(IS_ROBOTIC_ORGAN(src)) // Robotic organs don't naturally heal
+ return
+
+ ///Damage decrements by a percent of its maxhealth
+ var/healing_amount = healing_factor
+ ///Damage decrements again by a percent of its maxhealth, up to a total of 4 extra times depending on the owner's health
+ healing_amount += (owner.satiety > 0) ? (4 * healing_factor * owner.satiety / MAX_SATIETY) : 0
+ apply_organ_damage(-healing_amount * maxHealth * seconds_per_tick, damage) // pass curent damage incase we are over cap
/obj/item/organ/examine(mob/user)
. = ..()
@@ -162,11 +192,14 @@ INITIALIZE_IMMEDIATE(/obj/item/organ)
///Used as callbacks by object pooling
/obj/item/organ/proc/exit_wardrobe()
- return
+ START_PROCESSING(SSobj, src)
//See above
/obj/item/organ/proc/enter_wardrobe()
- return
+ STOP_PROCESSING(SSobj, src)
+
+/obj/item/organ/process(seconds_per_tick, times_fired)
+ on_death(seconds_per_tick, times_fired) //Kinda hate doing it like this, but I really don't want to call process directly.
/obj/item/organ/proc/OnEatFrom(eater, feeder)
useable = FALSE //You can't use it anymore after eating it you spaztic
@@ -284,8 +317,14 @@ INITIALIZE_IMMEDIATE(/obj/item/organ)
ears.Insert(src)
ears.adjustEarDamage(-INFINITY, -INFINITY) // actually do: set_organ_damage(0) and deaf = 0
+///Organs don't die instantly, and neither should you when you get fucked up
/obj/item/organ/proc/handle_failing_organs(seconds_per_tick)
- return
+ if(owner.stat == DEAD)
+ return
+
+ failure_time += seconds_per_tick
+ organ_failure(seconds_per_tick)
+
/** organ_failure
* generic proc for handling dying organs
diff --git a/code/modules/surgery/organs/internal/_internal_organ.dm b/code/modules/surgery/organs/internal/_internal_organ.dm
deleted file mode 100644
index 20b9f8f90f162..0000000000000
--- a/code/modules/surgery/organs/internal/_internal_organ.dm
+++ /dev/null
@@ -1,86 +0,0 @@
-/obj/item/organ
- name = "organ"
-
-/obj/item/organ/Initialize(mapload)
- . = ..()
- START_PROCESSING(SSobj, src)
-
-/obj/item/organ/on_mob_insert(mob/living/carbon/organ_owner, special, movement_flags)
- . = ..()
-
- // organs_slot must ALWAYS be ordered in the same way as organ_process_order
- // Otherwise life processing breaks down
- sortTim(owner.organs_slot, GLOBAL_PROC_REF(cmp_organ_slot_asc))
-
- STOP_PROCESSING(SSobj, src)
-
-/obj/item/organ/on_mob_remove(mob/living/carbon/organ_owner, special = FALSE, movement_flags)
- . = ..()
-
- if((organ_flags & ORGAN_VITAL) && !special && !HAS_TRAIT(organ_owner, TRAIT_GODMODE))
- if(organ_owner.stat != DEAD)
- organ_owner.investigate_log("has been killed by losing a vital organ ([src]).", INVESTIGATE_DEATHS)
- organ_owner.death()
-
- START_PROCESSING(SSobj, src)
-
-/obj/item/organ/process(seconds_per_tick, times_fired)
- on_death(seconds_per_tick, times_fired) //Kinda hate doing it like this, but I really don't want to call process directly.
-
-/obj/item/organ/on_death(seconds_per_tick, times_fired) //runs decay when outside of a person
- if(organ_flags & (ORGAN_ROBOTIC | ORGAN_FROZEN))
- return
-
- if(owner)
- if(owner.bodytemperature > T0C)
- var/air_temperature_factor = min((owner.bodytemperature - T0C) / 20, 1)
- apply_organ_damage(decay_factor * maxHealth * seconds_per_tick * air_temperature_factor)
- else
- var/datum/gas_mixture/exposed_air = return_air()
- if(exposed_air && exposed_air.temperature > T0C)
- var/air_temperature_factor = min((exposed_air.temperature - T0C) / 20, 1)
- apply_organ_damage(decay_factor * maxHealth * seconds_per_tick * air_temperature_factor)
-
-/// Called once every life tick on every organ in a carbon's body
-/// NOTE: THIS IS VERY HOT. Be careful what you put in here
-/// To give you some scale, if there's 100 carbons in the game, they each have maybe 9 organs
-/// So that's 900 calls to this proc every life process. Please don't be dumb
-/obj/item/organ/on_life(seconds_per_tick, times_fired) //repair organ damage if the organ is not failing
- if(organ_flags & ORGAN_FAILING)
- handle_failing_organs(seconds_per_tick)
- return
-
- if(failure_time > 0)
- failure_time--
-
- if(organ_flags & ORGAN_EMP) //Synthetic organ has been emped, is now failing.
- apply_organ_damage(decay_factor * maxHealth * seconds_per_tick)
- return
-
- if(!damage) // No sense healing if you're not even hurt bro
- return
-
- if(IS_ROBOTIC_ORGAN(src)) // Robotic organs don't naturally heal
- return
-
- ///Damage decrements by a percent of its maxhealth
- var/healing_amount = healing_factor
- ///Damage decrements again by a percent of its maxhealth, up to a total of 4 extra times depending on the owner's health
- healing_amount += (owner.satiety > 0) ? (4 * healing_factor * owner.satiety / MAX_SATIETY) : 0
- apply_organ_damage(-healing_amount * maxHealth * seconds_per_tick, damage) // pass curent damage incase we are over cap
-
-///Used as callbacks by object pooling
-/obj/item/organ/exit_wardrobe()
- START_PROCESSING(SSobj, src)
-
-//See above
-/obj/item/organ/enter_wardrobe()
- STOP_PROCESSING(SSobj, src)
-
-///Organs don't die instantly, and neither should you when you get fucked up
-/obj/item/organ/handle_failing_organs(seconds_per_tick)
- if(owner.stat == DEAD)
- return
-
- failure_time += seconds_per_tick
- organ_failure(seconds_per_tick)
diff --git a/code/modules/surgery/organs/organ_movement.dm b/code/modules/surgery/organs/organ_movement.dm
index fa76c8180cdcb..69dd5b78b8a5e 100644
--- a/code/modules/surgery/organs/organ_movement.dm
+++ b/code/modules/surgery/organs/organ_movement.dm
@@ -107,6 +107,12 @@
SEND_SIGNAL(src, COMSIG_ORGAN_IMPLANTED, organ_owner)
SEND_SIGNAL(organ_owner, COMSIG_CARBON_GAIN_ORGAN, src, special)
+ // organs_slot must ALWAYS be ordered in the same way as organ_process_order
+ // Otherwise life processing breaks down
+ sortTim(owner.organs_slot, GLOBAL_PROC_REF(cmp_organ_slot_asc))
+
+ STOP_PROCESSING(SSobj, src)
+
/// Insert an organ into a limb, assume the limb as always detached and include no owner operations here (except the get_bodypart helper here I guess)
/// Give EITHER a limb OR a limb owner
/obj/item/organ/proc/bodypart_insert(obj/item/bodypart/bodypart, mob/living/carbon/limb_owner, movement_flags)
@@ -153,9 +159,7 @@
organ_owner.organs -= src
owner = null
-
on_mob_remove(organ_owner, special, movement_flags)
-
return TRUE
/// Called after the organ is removed from a mob.
@@ -204,6 +208,13 @@
if(LAZYLEN(diseases_to_add))
AddComponent(/datum/component/infective, diseases_to_add)
+ if((organ_flags & ORGAN_VITAL) && !special && !HAS_TRAIT(organ_owner, TRAIT_GODMODE))
+ if(organ_owner.stat != DEAD)
+ organ_owner.investigate_log("has been killed by losing a vital organ ([src]).", INVESTIGATE_DEATHS)
+ organ_owner.death()
+
+ START_PROCESSING(SSobj, src)
+
/// Called to remove an organ from a limb. Do not put any mob operations here (except the bodypart_getter at the start)
/// Give EITHER a limb OR a limb_owner
/obj/item/organ/proc/bodypart_remove(obj/item/bodypart/limb, mob/living/carbon/limb_owner, movement_flags)
diff --git a/code/modules/vehicles/mecha/equipment/weapons/weapons.dm b/code/modules/vehicles/mecha/equipment/weapons/weapons.dm
index cf042033cba10..c62b2a0d9ce45 100644
--- a/code/modules/vehicles/mecha/equipment/weapons/weapons.dm
+++ b/code/modules/vehicles/mecha/equipment/weapons/weapons.dm
@@ -74,7 +74,7 @@
projectile_obj.hit_prone_targets = shooter.combat_mode
projectile_obj.fire()
if(!projectile_obj.suppressed && firing_effect_type)
- new firing_effect_type(get_turf(src), chassis.dir)
+ new firing_effect_type(chassis || get_turf(src), chassis.dir)
playsound(chassis, fire_sound, 50, TRUE)
log_combat(source, target, "fired [projectile_obj] at", src, "from [chassis] at [get_area_name(src, TRUE)]")
diff --git a/html/changelogs/AutoChangeLog-pr-87740.yml b/html/changelogs/AutoChangeLog-pr-87740.yml
deleted file mode 100644
index 1221facbb1341..0000000000000
--- a/html/changelogs/AutoChangeLog-pr-87740.yml
+++ /dev/null
@@ -1,6 +0,0 @@
-author: "SmArtKar"
-delete-after: True
-changes:
- - qol: "Projectiles now visually impact their targets instead of disappearing about a tile short of it."
- - bugfix: "Fixed multiple minor issues with projectile behavior"
- - refactor: "Completely rewrote almost all of our projectile code - if anything broke or started looking/behaving oddly, make an issue report!"
\ No newline at end of file
diff --git a/html/changelogs/AutoChangeLog-pr-87764.yml b/html/changelogs/AutoChangeLog-pr-87764.yml
deleted file mode 100644
index acbb17758af6c..0000000000000
--- a/html/changelogs/AutoChangeLog-pr-87764.yml
+++ /dev/null
@@ -1,6 +0,0 @@
-author: "Ben10Omintrix"
-delete-after: True
-changes:
- - bugfix: "fixes the chipped quirk displaying the skill chip's typepath rather than its name"
- - bugfix: "fixes chipped quirk's itchy effect not working"
- - bugfix: "the chipped quirk's itchy effect now goes away when the skillchip is removed"
\ No newline at end of file
diff --git a/html/changelogs/AutoChangeLog-pr-87913.yml b/html/changelogs/AutoChangeLog-pr-87913.yml
deleted file mode 100644
index a3728e89bc96d..0000000000000
--- a/html/changelogs/AutoChangeLog-pr-87913.yml
+++ /dev/null
@@ -1,4 +0,0 @@
-author: "Ben10Omintrix"
-delete-after: True
-changes:
- - refactor: "projectile dampeners have been refactored. please report any bugs"
\ No newline at end of file
diff --git a/html/changelogs/AutoChangeLog-pr-88058.yml b/html/changelogs/AutoChangeLog-pr-88058.yml
new file mode 100644
index 0000000000000..4fa0223761707
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-88058.yml
@@ -0,0 +1,5 @@
+author: "Mifutus"
+delete-after: True
+changes:
+ - rscadd: "Added new moth customizations available in the character creation under the name \"Dipped\""
+ - image: "added icons for the moth wings, antennae and markings\n:cl:"
\ No newline at end of file
diff --git a/html/changelogs/AutoChangeLog-pr-88065.yml b/html/changelogs/AutoChangeLog-pr-88065.yml
new file mode 100644
index 0000000000000..137a5dcb4a02d
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-88065.yml
@@ -0,0 +1,6 @@
+author: "Ghommie"
+delete-after: True
+changes:
+ - balance: "Nerfed slipperiness from fish infusion. It no longer knockdowns but it staggers and slides the user one or two tiles away."
+ - balance: "Added a slight natural weakness to fire/heat to the fish infusion, which, taking the minor general damage resistance resistance when wet, is pretty mild."
+ - balance: "hot temperature projectiles from the temperature gun (and watchers I think) also dry living creatures hit by them."
\ No newline at end of file
diff --git a/html/changelogs/AutoChangeLog-pr-88072.yml b/html/changelogs/AutoChangeLog-pr-88072.yml
new file mode 100644
index 0000000000000..dfc9728aad8b4
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-88072.yml
@@ -0,0 +1,4 @@
+author: "SmArtKar"
+delete-after: True
+changes:
+ - image: "Muzzle flash now is attached to your sprite, meaning you won't run over it if you fire while moving"
\ No newline at end of file
diff --git a/html/changelogs/AutoChangeLog-pr-88086.yml b/html/changelogs/AutoChangeLog-pr-88086.yml
deleted file mode 100644
index ed78288b3be77..0000000000000
--- a/html/changelogs/AutoChangeLog-pr-88086.yml
+++ /dev/null
@@ -1,4 +0,0 @@
-author: "thimothymtorres"
-delete-after: True
-changes:
- - bugfix: "Fix wrong status effect for watery tile"
\ No newline at end of file
diff --git a/html/changelogs/AutoChangeLog-pr-88090.yml b/html/changelogs/AutoChangeLog-pr-88090.yml
deleted file mode 100644
index 6ea4dd864a7fa..0000000000000
--- a/html/changelogs/AutoChangeLog-pr-88090.yml
+++ /dev/null
@@ -1,4 +0,0 @@
-author: "lovegreenstuff"
-delete-after: True
-changes:
- - bugfix: "synthmeat is no longer an nft"
\ No newline at end of file
diff --git a/html/changelogs/AutoChangeLog-pr-88097.yml b/html/changelogs/AutoChangeLog-pr-88097.yml
deleted file mode 100644
index 61304e825ffb0..0000000000000
--- a/html/changelogs/AutoChangeLog-pr-88097.yml
+++ /dev/null
@@ -1,4 +0,0 @@
-author: "SmArtKar"
-delete-after: True
-changes:
- - bugfix: "Fixed a rare runtime in jetpack component code"
\ No newline at end of file
diff --git a/html/changelogs/AutoChangeLog-pr-88099.yml b/html/changelogs/AutoChangeLog-pr-88099.yml
deleted file mode 100644
index 95c5f4edc254d..0000000000000
--- a/html/changelogs/AutoChangeLog-pr-88099.yml
+++ /dev/null
@@ -1,4 +0,0 @@
-author: "SmArtKar"
-delete-after: True
-changes:
- - bugfix: "Organ manipulation can be completed once again and doesn't cause you to be un-melee-able in some cases."
\ No newline at end of file
diff --git a/html/changelogs/AutoChangeLog-pr-88100.yml b/html/changelogs/AutoChangeLog-pr-88100.yml
deleted file mode 100644
index cfc2f7649d8ed..0000000000000
--- a/html/changelogs/AutoChangeLog-pr-88100.yml
+++ /dev/null
@@ -1,4 +0,0 @@
-author: "SmArtKar"
-delete-after: True
-changes:
- - bugfix: "Fixed full augmentation scan experiment being uncompletable"
\ No newline at end of file
diff --git a/html/changelogs/AutoChangeLog-pr-88102.yml b/html/changelogs/AutoChangeLog-pr-88102.yml
deleted file mode 100644
index c04d08c991874..0000000000000
--- a/html/changelogs/AutoChangeLog-pr-88102.yml
+++ /dev/null
@@ -1,4 +0,0 @@
-author: "timothymtorres, SmArtKar"
-delete-after: True
-changes:
- - bugfix: "Fix chewable bubblegum not metabolizing due to microdose"
\ No newline at end of file
diff --git a/html/changelogs/AutoChangeLog-pr-88104.yml b/html/changelogs/AutoChangeLog-pr-88104.yml
deleted file mode 100644
index 1d2da746e338e..0000000000000
--- a/html/changelogs/AutoChangeLog-pr-88104.yml
+++ /dev/null
@@ -1,4 +0,0 @@
-author: "SmArtKar"
-delete-after: True
-changes:
- - bugfix: "Fixed parsnip sabre not receiving a jousting component"
\ No newline at end of file
diff --git a/html/changelogs/AutoChangeLog-pr-88111.yml b/html/changelogs/AutoChangeLog-pr-88111.yml
deleted file mode 100644
index 51d16028801e1..0000000000000
--- a/html/changelogs/AutoChangeLog-pr-88111.yml
+++ /dev/null
@@ -1,4 +0,0 @@
-author: "timothymtorres"
-delete-after: True
-changes:
- - bugfix: "Fix coffee maker smoke particles not deleting"
\ No newline at end of file
diff --git a/html/changelogs/AutoChangeLog-pr-88114.yml b/html/changelogs/AutoChangeLog-pr-88114.yml
deleted file mode 100644
index 8c6ca0cf3a0cd..0000000000000
--- a/html/changelogs/AutoChangeLog-pr-88114.yml
+++ /dev/null
@@ -1,4 +0,0 @@
-author: "timothymtorres"
-delete-after: True
-changes:
- - bugfix: "Fix fireplace particles runtimes."
\ No newline at end of file
diff --git a/html/changelogs/AutoChangeLog-pr-88118.yml b/html/changelogs/AutoChangeLog-pr-88118.yml
new file mode 100644
index 0000000000000..f82d4e2c0fe0f
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-88118.yml
@@ -0,0 +1,4 @@
+author: "Auris456852"
+delete-after: True
+changes:
+ - bugfix: "Makes a sliced baklava pie keep its complexity after slicing"
\ No newline at end of file
diff --git a/html/changelogs/AutoChangeLog-pr-88119.yml b/html/changelogs/AutoChangeLog-pr-88119.yml
new file mode 100644
index 0000000000000..13d9297440793
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-88119.yml
@@ -0,0 +1,4 @@
+author: "timothymtorres"
+delete-after: True
+changes:
+ - bugfix: "Fix weather effects ignoring certain areas like space."
\ No newline at end of file
diff --git a/html/changelogs/AutoChangeLog-pr-88120.yml b/html/changelogs/AutoChangeLog-pr-88120.yml
new file mode 100644
index 0000000000000..c8eb7ab41a8e5
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-88120.yml
@@ -0,0 +1,4 @@
+author: "Dawnseer"
+delete-after: True
+changes:
+ - bugfix: "fixed some erronous spriting on the zippo"
\ No newline at end of file
diff --git a/html/changelogs/AutoChangeLog-pr-88123.yml b/html/changelogs/AutoChangeLog-pr-88123.yml
new file mode 100644
index 0000000000000..e9586c31e5e78
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-88123.yml
@@ -0,0 +1,4 @@
+author: "SmArtKar"
+delete-after: True
+changes:
+ - image: "Changing clipboard skins now changes the inhands sprite as well"
\ No newline at end of file
diff --git a/html/changelogs/AutoChangeLog-pr-88127.yml b/html/changelogs/AutoChangeLog-pr-88127.yml
new file mode 100644
index 0000000000000..00f1b2cc53f7a
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-88127.yml
@@ -0,0 +1,4 @@
+author: "SmArtKar"
+delete-after: True
+changes:
+ - bugfix: "Fixed a runtime caused by logging out while your runechat message was appearing."
\ No newline at end of file
diff --git a/html/changelogs/AutoChangeLog-pr-88129.yml b/html/changelogs/AutoChangeLog-pr-88129.yml
new file mode 100644
index 0000000000000..d86daaa1bc14f
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-88129.yml
@@ -0,0 +1,4 @@
+author: "SmArtKar"
+delete-after: True
+changes:
+ - bugfix: "Fixed atrocinator module footstep spam when you're moving on a tram"
\ No newline at end of file
diff --git a/html/changelogs/AutoChangeLog-pr-88130.yml b/html/changelogs/AutoChangeLog-pr-88130.yml
new file mode 100644
index 0000000000000..cb093fb25d7db
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-88130.yml
@@ -0,0 +1,4 @@
+author: "SmArtKar"
+delete-after: True
+changes:
+ - bugfix: "Fixed meteors freezing in place if they continiously miss the station on a looping z level"
\ No newline at end of file
diff --git a/html/changelogs/AutoChangeLog-pr-88132.yml b/html/changelogs/AutoChangeLog-pr-88132.yml
new file mode 100644
index 0000000000000..59786eca83a0f
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-88132.yml
@@ -0,0 +1,4 @@
+author: "SmArtKar"
+delete-after: True
+changes:
+ - code_imp: "Cleaned up organ code"
\ No newline at end of file
diff --git a/html/changelogs/AutoChangeLog-pr-88133.yml b/html/changelogs/AutoChangeLog-pr-88133.yml
new file mode 100644
index 0000000000000..102bfe9adce67
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-88133.yml
@@ -0,0 +1,4 @@
+author: "grungussuss"
+delete-after: True
+changes:
+ - sound: "changelings now have a sound for absorbing"
\ No newline at end of file
diff --git a/html/changelogs/AutoChangeLog-pr-88139.yml b/html/changelogs/AutoChangeLog-pr-88139.yml
new file mode 100644
index 0000000000000..549d5583fa485
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-88139.yml
@@ -0,0 +1,4 @@
+author: "mc-oofert"
+delete-after: True
+changes:
+ - bugfix: "fixed some wiring on wawastation, added an additional distro/scrubbers connection to sciences network"
\ No newline at end of file
diff --git a/html/changelogs/AutoChangeLog-pr-88140.yml b/html/changelogs/AutoChangeLog-pr-88140.yml
new file mode 100644
index 0000000000000..38d16cbe558d6
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-88140.yml
@@ -0,0 +1,4 @@
+author: "timothymtorres"
+delete-after: True
+changes:
+ - bugfix: "Fix coffee maker items teleporting to AI/Cyborg locations"
\ No newline at end of file
diff --git a/html/changelogs/AutoChangeLog-pr-88141.yml b/html/changelogs/AutoChangeLog-pr-88141.yml
new file mode 100644
index 0000000000000..3a595c93e9e0c
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-88141.yml
@@ -0,0 +1,4 @@
+author: "mc-oofert"
+delete-after: True
+changes:
+ - bugfix: "damage done by thrown objects to objects respects their demolition modifier"
\ No newline at end of file
diff --git a/html/changelogs/AutoChangeLog-pr-88142.yml b/html/changelogs/AutoChangeLog-pr-88142.yml
new file mode 100644
index 0000000000000..6e51235fa05b8
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-88142.yml
@@ -0,0 +1,5 @@
+author: "SmArtKar"
+delete-after: True
+changes:
+ - bugfix: "Blind people no longer make eye contact with their hands"
+ - bugfix: "Blindfolds and other sorts of opaque eye coverage now prevent eye contact from occuring"
\ No newline at end of file
diff --git a/html/changelogs/AutoChangeLog-pr-88146.yml b/html/changelogs/AutoChangeLog-pr-88146.yml
new file mode 100644
index 0000000000000..0d3cd43f0c22e
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-88146.yml
@@ -0,0 +1,5 @@
+author: "Mifutus"
+delete-after: True
+changes:
+ - bugfix: "fixed the pulse rifle not spawning when won"
+ - code_imp: "added get_turf to the pulserifle when the odds are beat.\n:cl:"
\ No newline at end of file
diff --git a/html/changelogs/AutoChangeLog-pr-88147.yml b/html/changelogs/AutoChangeLog-pr-88147.yml
new file mode 100644
index 0000000000000..7f0b84ab8d4cd
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-88147.yml
@@ -0,0 +1,4 @@
+author: "SmArtKar"
+delete-after: True
+changes:
+ - bugfix: "Fixed a random zero in nuke ops uplink UI"
\ No newline at end of file
diff --git a/html/changelogs/AutoChangeLog-pr-88148.yml b/html/changelogs/AutoChangeLog-pr-88148.yml
new file mode 100644
index 0000000000000..8861b436989fc
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-88148.yml
@@ -0,0 +1,4 @@
+author: "EnterTheJake"
+delete-after: True
+changes:
+ - image: "Heretic's Moon Blade has received a new sprite."
\ No newline at end of file
diff --git a/html/changelogs/AutoChangeLog-pr-88149.yml b/html/changelogs/AutoChangeLog-pr-88149.yml
new file mode 100644
index 0000000000000..3b4701923978f
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-88149.yml
@@ -0,0 +1,4 @@
+author: "Absolucy"
+delete-after: True
+changes:
+ - refactor: "Cleaned up code relating to heretic ascension announcements and traits."
\ No newline at end of file
diff --git a/html/changelogs/AutoChangeLog-pr-88154.yml b/html/changelogs/AutoChangeLog-pr-88154.yml
new file mode 100644
index 0000000000000..657dc850c2723
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-88154.yml
@@ -0,0 +1,4 @@
+author: "SmArtKar"
+delete-after: True
+changes:
+ - qol: "Reagent grinders display number of material sheets they hold instead of defaulting to 1"
\ No newline at end of file
diff --git a/html/changelogs/AutoChangeLog-pr-88155.yml b/html/changelogs/AutoChangeLog-pr-88155.yml
new file mode 100644
index 0000000000000..044b3923208c9
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-88155.yml
@@ -0,0 +1,4 @@
+author: "GoblinBackwards"
+delete-after: True
+changes:
+ - bugfix: "fixed the fire effect not appearing on burning gasses"
\ No newline at end of file
diff --git a/html/changelogs/AutoChangeLog-pr-88163.yml b/html/changelogs/AutoChangeLog-pr-88163.yml
new file mode 100644
index 0000000000000..7541c67527e3c
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-88163.yml
@@ -0,0 +1,4 @@
+author: "SmArtKar"
+delete-after: True
+changes:
+ - bugfix: "Fixed some issues with defib paddle retraction."
\ No newline at end of file
diff --git a/html/changelogs/AutoChangeLog-pr-88174.yml b/html/changelogs/AutoChangeLog-pr-88174.yml
new file mode 100644
index 0000000000000..3efa289952b89
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-88174.yml
@@ -0,0 +1,4 @@
+author: "SmArtKar"
+delete-after: True
+changes:
+ - bugfix: "Fixed fishing turfs not lazyloading"
\ No newline at end of file
diff --git a/html/changelogs/archive/2024-11.yml b/html/changelogs/archive/2024-11.yml
index 671fbfc440c68..1178bed657af7 100644
--- a/html/changelogs/archive/2024-11.yml
+++ b/html/changelogs/archive/2024-11.yml
@@ -844,3 +844,32 @@
- bugfix: inducers can be inserted into storage objects again
- bugfix: fixes grown foods(like pineapples) getting deleted sometimes inside crates
and stuff
+2024-11-24:
+ Ben10Omintrix:
+ - bugfix: fixes the chipped quirk displaying the skill chip's typepath rather than
+ its name
+ - bugfix: fixes chipped quirk's itchy effect not working
+ - bugfix: the chipped quirk's itchy effect now goes away when the skillchip is removed
+ - refactor: projectile dampeners have been refactored. please report any bugs
+ SmArtKar:
+ - qol: Projectiles now visually impact their targets instead of disappearing about
+ a tile short of it.
+ - bugfix: Fixed multiple minor issues with projectile behavior
+ - refactor: Completely rewrote almost all of our projectile code - if anything broke
+ or started looking/behaving oddly, make an issue report!
+ - bugfix: Fixed full augmentation scan experiment being uncompletable
+ - bugfix: Organ manipulation can be completed once again and doesn't cause you to
+ be un-melee-able in some cases.
+ - bugfix: Fixed a rare runtime in jetpack component code
+ - bugfix: Fixed parsnip sabre not receiving a jousting component
+ grungussuss:
+ - bugfix: entertainment screens now properly show their tooltip for muting sound
+ lovegreenstuff:
+ - bugfix: synthmeat is no longer an nft
+ thimothymtorres:
+ - bugfix: Fix wrong status effect for watery tile
+ timothymtorres:
+ - bugfix: Fix coffee maker smoke particles not deleting
+ - bugfix: Fix fireplace particles runtimes.
+ timothymtorres, SmArtKar:
+ - bugfix: Fix chewable bubblegum not metabolizing due to microdose
diff --git a/icons/effects/fire.dmi b/icons/effects/fire.dmi
index 113e16163ecdc..b48164f8795a1 100644
Binary files a/icons/effects/fire.dmi and b/icons/effects/fire.dmi differ
diff --git a/icons/mob/human/species/moth/moth_antennae.dmi b/icons/mob/human/species/moth/moth_antennae.dmi
index a40013e93576f..e6d024668084b 100644
Binary files a/icons/mob/human/species/moth/moth_antennae.dmi and b/icons/mob/human/species/moth/moth_antennae.dmi differ
diff --git a/icons/mob/human/species/moth/moth_markings.dmi b/icons/mob/human/species/moth/moth_markings.dmi
index a6ebc2cedb517..1c8173eaf3903 100644
Binary files a/icons/mob/human/species/moth/moth_markings.dmi and b/icons/mob/human/species/moth/moth_markings.dmi differ
diff --git a/icons/mob/human/species/moth/moth_wings.dmi b/icons/mob/human/species/moth/moth_wings.dmi
index 91c0d8b2b2cd1..1d3aaea5e776d 100644
Binary files a/icons/mob/human/species/moth/moth_wings.dmi and b/icons/mob/human/species/moth/moth_wings.dmi differ
diff --git a/icons/mob/inhands/64x64_lefthand.dmi b/icons/mob/inhands/64x64_lefthand.dmi
index e5dc62260453a..d46d2b439f514 100644
Binary files a/icons/mob/inhands/64x64_lefthand.dmi and b/icons/mob/inhands/64x64_lefthand.dmi differ
diff --git a/icons/mob/inhands/64x64_righthand.dmi b/icons/mob/inhands/64x64_righthand.dmi
index 5f153cece749c..8adb31df8546d 100644
Binary files a/icons/mob/inhands/64x64_righthand.dmi and b/icons/mob/inhands/64x64_righthand.dmi differ
diff --git a/icons/mob/inhands/items_lefthand.dmi b/icons/mob/inhands/items_lefthand.dmi
index f38ce00161941..82f46b35c6cc1 100644
Binary files a/icons/mob/inhands/items_lefthand.dmi and b/icons/mob/inhands/items_lefthand.dmi differ
diff --git a/icons/mob/inhands/items_righthand.dmi b/icons/mob/inhands/items_righthand.dmi
index 4639b290fe371..b2e2fc8033b89 100644
Binary files a/icons/mob/inhands/items_righthand.dmi and b/icons/mob/inhands/items_righthand.dmi differ
diff --git a/icons/obj/weapons/khopesh.dmi b/icons/obj/weapons/khopesh.dmi
index 20b084396aa6d..257ccc800dfb8 100644
Binary files a/icons/obj/weapons/khopesh.dmi and b/icons/obj/weapons/khopesh.dmi differ
diff --git a/sound/effects/changeling_absorb/attribution.txt b/sound/effects/changeling_absorb/attribution.txt
new file mode 100644
index 0000000000000..8fb03b4f01c22
--- /dev/null
+++ b/sound/effects/changeling_absorb/attribution.txt
@@ -0,0 +1,2 @@
+changeling_absorb 1-7 made by sadboysuss
+license: CC-BY-SA
\ No newline at end of file
diff --git a/sound/effects/changeling_absorb/changeling_absorb1.ogg b/sound/effects/changeling_absorb/changeling_absorb1.ogg
new file mode 100644
index 0000000000000..1ce7457a2d9a3
Binary files /dev/null and b/sound/effects/changeling_absorb/changeling_absorb1.ogg differ
diff --git a/sound/effects/changeling_absorb/changeling_absorb2.ogg b/sound/effects/changeling_absorb/changeling_absorb2.ogg
new file mode 100644
index 0000000000000..86bb2495cd1d8
Binary files /dev/null and b/sound/effects/changeling_absorb/changeling_absorb2.ogg differ
diff --git a/sound/effects/changeling_absorb/changeling_absorb3.ogg b/sound/effects/changeling_absorb/changeling_absorb3.ogg
new file mode 100644
index 0000000000000..2a0dcedaf61bd
Binary files /dev/null and b/sound/effects/changeling_absorb/changeling_absorb3.ogg differ
diff --git a/sound/effects/changeling_absorb/changeling_absorb4.ogg b/sound/effects/changeling_absorb/changeling_absorb4.ogg
new file mode 100644
index 0000000000000..ea3cc51e43bb3
Binary files /dev/null and b/sound/effects/changeling_absorb/changeling_absorb4.ogg differ
diff --git a/sound/effects/changeling_absorb/changeling_absorb5.ogg b/sound/effects/changeling_absorb/changeling_absorb5.ogg
new file mode 100644
index 0000000000000..761f29a8cd89b
Binary files /dev/null and b/sound/effects/changeling_absorb/changeling_absorb5.ogg differ
diff --git a/sound/effects/changeling_absorb/changeling_absorb6.ogg b/sound/effects/changeling_absorb/changeling_absorb6.ogg
new file mode 100644
index 0000000000000..10e70742e6704
Binary files /dev/null and b/sound/effects/changeling_absorb/changeling_absorb6.ogg differ
diff --git a/sound/effects/changeling_absorb/changeling_absorb7.ogg b/sound/effects/changeling_absorb/changeling_absorb7.ogg
new file mode 100644
index 0000000000000..7a1fd52fa932f
Binary files /dev/null and b/sound/effects/changeling_absorb/changeling_absorb7.ogg differ
diff --git a/tgstation.dme b/tgstation.dme
index 781a991b10054..75e742ff190f1 100644
--- a/tgstation.dme
+++ b/tgstation.dme
@@ -1662,6 +1662,7 @@
#include "code\datums\looping_sounds\acid.dm"
#include "code\datums\looping_sounds\breathing.dm"
#include "code\datums\looping_sounds\burning.dm"
+#include "code\datums\looping_sounds\changeling_absorb.dm"
#include "code\datums\looping_sounds\choking.dm"
#include "code\datums\looping_sounds\cyborg.dm"
#include "code\datums\looping_sounds\item_sounds.dm"
@@ -6134,7 +6135,6 @@
#include "code\modules\surgery\organs\external\wings\functional_wings.dm"
#include "code\modules\surgery\organs\external\wings\moth_wings.dm"
#include "code\modules\surgery\organs\external\wings\wings.dm"
-#include "code\modules\surgery\organs\internal\_internal_organ.dm"
#include "code\modules\surgery\organs\internal\appendix\_appendix.dm"
#include "code\modules\surgery\organs\internal\appendix\appendix_golem.dm"
#include "code\modules\surgery\organs\internal\cyberimp\augments_arms.dm"
diff --git a/tgui/packages/tgui/interfaces/Uplink/index.tsx b/tgui/packages/tgui/interfaces/Uplink/index.tsx
index 5bf52394f2cb0..2294059a6ae71 100644
--- a/tgui/packages/tgui/interfaces/Uplink/index.tsx
+++ b/tgui/packages/tgui/interfaces/Uplink/index.tsx
@@ -353,7 +353,7 @@ export class Uplink extends Component<{}, UplinkState> {
)}
- {(primary_objectives || has_objectives) && (
+ {!!(primary_objectives || has_objectives) && (
{primary_objectives && (