diff --git a/code/__DEFINES/dcs/signals/signals_shuttle.dm b/code/__DEFINES/dcs/signals/signals_shuttle.dm
new file mode 100644
index 0000000000000..336117fb86861
--- /dev/null
+++ b/code/__DEFINES/dcs/signals/signals_shuttle.dm
@@ -0,0 +1,7 @@
+// Shuttle signals. this file is empty because shuttle code is ancient, feel free to
+// add more signals where its appropriate to have them
+
+/// Called when the shuttle tries to move. Do not return anything to continue with default behaviour (always allow) : ()
+#define COMSIG_SHUTTLE_SHOULD_MOVE "shuttle_should_move"
+ /// Return this when the shuttle move should be blocked.
+ #define BLOCK_SHUTTLE_MOVE (1<<0)
diff --git a/code/__DEFINES/mobs.dm b/code/__DEFINES/mobs.dm
index 11182e1ea2f6e..07ffee2890f3a 100644
--- a/code/__DEFINES/mobs.dm
+++ b/code/__DEFINES/mobs.dm
@@ -452,7 +452,7 @@
#define DOOR_CRUSH_DAMAGE 15 //the amount of damage that airlocks deal when they crush you
#define HUNGER_FACTOR 0.05 //factor at which mob nutrition decreases
-#define ETHEREAL_DISCHARGE_RATE (8e-4 * STANDARD_CELL_CHARGE) // Rate at which ethereal stomach charge decreases
+#define ETHEREAL_DISCHARGE_RATE (8e-3 * STANDARD_CELL_CHARGE) // Rate at which ethereal stomach charge decreases
/// How much nutrition eating clothes as moth gives and drains
#define CLOTHING_NUTRITION_GAIN 15
#define REAGENTS_METABOLISM 0.2 //How many units of reagent are consumed per second, by default.
diff --git a/code/__DEFINES/traits/declarations.dm b/code/__DEFINES/traits/declarations.dm
index 21c239c59b914..7a20d3ea4c91e 100644
--- a/code/__DEFINES/traits/declarations.dm
+++ b/code/__DEFINES/traits/declarations.dm
@@ -1377,6 +1377,9 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai
///Trait given to mobs that can dig
#define TRAIT_MOB_CAN_DIG "mob_can_dig"
+/// This atom has a tether attached to it
+#define TRAIT_TETHER_ATTACHED "tether_attached"
+
/**
*
* This trait is used in some interactions very high in the interaction chain to allow
diff --git a/code/_globalvars/traits/_traits.dm b/code/_globalvars/traits/_traits.dm
index f5d79447f56a2..fb53fc6cad0ef 100644
--- a/code/_globalvars/traits/_traits.dm
+++ b/code/_globalvars/traits/_traits.dm
@@ -34,6 +34,7 @@ GLOBAL_LIST_INIT(traits_by_type, list(
"TRAIT_STICKERED" = TRAIT_STICKERED,
"TRAIT_UNHITTABLE_BY_PROJECTILES" = TRAIT_UNHITTABLE_BY_PROJECTILES,
"TRAIT_UNLINKABLE_FISHING_SPOT" = TRAIT_UNLINKABLE_FISHING_SPOT,
+ "TRAIT_TETHER_ATTACHED" = TRAIT_TETHER_ATTACHED,
),
/atom/movable = list(
"TRAIT_ACTIVE_STORAGE" = TRAIT_ACTIVE_STORAGE,
diff --git a/code/controllers/subsystem/processing/fishing.dm b/code/controllers/subsystem/processing/fishing.dm
index 3f0433b21b9e8..dd4dc3775359b 100644
--- a/code/controllers/subsystem/processing/fishing.dm
+++ b/code/controllers/subsystem/processing/fishing.dm
@@ -37,7 +37,7 @@ PROCESSING_SUBSYSTEM_DEF(fishing)
unknown_icon.Blend(questionmark, ICON_OVERLAY, x = width, y = height)
cached_unknown_fish_icons[fish_type] = icon2base64(unknown_icon)
- var/obj/item/fish/fish = new fish_type(null, FALSE)
+ var/obj/item/fish/fish = new fish_type
spawned_fish += fish
var/list/properties = list()
fish_properties[fish_type] = properties
diff --git a/code/datums/components/tether.dm b/code/datums/components/tether.dm
index b9eb40647acd1..ba11306cd8936 100644
--- a/code/datums/components/tether.dm
+++ b/code/datums/components/tether.dm
@@ -15,8 +15,13 @@
var/datum/beam/tether_beam
/// Tether module if we were created by one
var/obj/item/mod/module/tether/parent_module
+ /// Source, if any, for TRAIT_TETHER_ATTACHED we add
+ var/tether_trait_source
+ /// If TRUE, only add TRAIT_TETHER_ATTACHED to our parent
+ var/no_target_trait
-/datum/component/tether/Initialize(atom/tether_target, max_dist = 7, tether_name, atom/embed_target = null, start_distance = null, parent_module = null)
+/datum/component/tether/Initialize(atom/tether_target, max_dist = 7, tether_name, atom/embed_target = null, start_distance = null, \
+ parent_module = null, tether_trait_source = null, no_target_trait = FALSE)
if(!ismovable(parent) || !istype(tether_target) || !tether_target.loc)
return COMPONENT_INCOMPATIBLE
@@ -24,6 +29,8 @@
src.embed_target = embed_target
src.max_dist = max_dist
src.parent_module = parent_module
+ src.tether_trait_source = tether_trait_source
+ src.no_target_trait = no_target_trait
cur_dist = max_dist
if (start_distance != null)
cur_dist = start_distance
@@ -34,6 +41,10 @@
src.tether_name = initial(tmp.name)
else
src.tether_name = tether_name
+ if (!isnull(tether_trait_source))
+ ADD_TRAIT(parent, TRAIT_TETHER_ATTACHED, tether_trait_source)
+ if (!no_target_trait)
+ ADD_TRAIT(tether_target, TRAIT_TETHER_ATTACHED, tether_trait_source)
/datum/component/tether/RegisterWithParent()
RegisterSignal(parent, COMSIG_MOVABLE_PRE_MOVE, PROC_REF(check_tether))
@@ -54,8 +65,12 @@
/datum/component/tether/UnregisterFromParent()
UnregisterSignal(parent, list(COMSIG_MOVABLE_PRE_MOVE, COMSIG_MOVABLE_MOVED))
+ if (!isnull(tether_trait_source))
+ REMOVE_TRAIT(parent, TRAIT_TETHER_ATTACHED, tether_trait_source)
if (!QDELETED(tether_target))
UnregisterSignal(tether_target, list(COMSIG_MOVABLE_PRE_MOVE, COMSIG_MOVABLE_MOVED, COMSIG_QDELETING))
+ if (!isnull(tether_trait_source) && !no_target_trait)
+ REMOVE_TRAIT(tether_target, TRAIT_TETHER_ATTACHED, tether_trait_source)
if (!QDELETED(tether_beam))
UnregisterSignal(tether_beam.visuals, list(COMSIG_CLICK, COMSIG_QDELETING))
qdel(tether_beam)
@@ -143,12 +158,23 @@
INVOKE_ASYNC(src, PROC_REF(process_beam_click), source, location, params, user)
/datum/component/tether/proc/process_beam_click(atom/source, atom/location, params, mob/user)
- if (!location.can_interact(user))
+ var/turf/nearest_turf
+ for (var/turf/line_turf in get_line(get_turf(parent), get_turf(tether_target)))
+ if (user.CanReach(line_turf))
+ nearest_turf = line_turf
+ break
+
+ if (isnull(nearest_turf))
return
+
+ if (!user.can_perform_action(nearest_turf))
+ nearest_turf.balloon_alert(user, "cannot reach!")
+ return
+
var/list/modifiers = params2list(params)
if(LAZYACCESS(modifiers, CTRL_CLICK))
location.balloon_alert(user, "cutting the tether...")
- if (!do_after(user, 1 SECONDS, user))
+ if (!do_after(user, 2 SECONDS, user))
return
qdel(src)
diff --git a/code/datums/looping_sounds/projectiles.dm b/code/datums/looping_sounds/projectiles.dm
index 6bc9a466ea144..ca96df698e921 100644
--- a/code/datums/looping_sounds/projectiles.dm
+++ b/code/datums/looping_sounds/projectiles.dm
@@ -1,4 +1,4 @@
/datum/looping_sound/moon_parade
mid_sounds = list('sound/effects/moon_parade_soundloop.ogg' = 1)
- mid_length = 0
+ mid_length = 2 SECONDS
volume = 20
diff --git a/code/game/objects/effects/step_triggers.dm b/code/game/objects/effects/step_triggers.dm
index 31ca55a54fb7b..0920b8e8b72a8 100644
--- a/code/game/objects/effects/step_triggers.dm
+++ b/code/game/objects/effects/step_triggers.dm
@@ -17,15 +17,15 @@
/obj/effect/step_trigger/proc/Trigger(atom/movable/A)
return 0
-/obj/effect/step_trigger/proc/on_entered(datum/source, H as mob|obj)
+/obj/effect/step_trigger/proc/on_entered(datum/source, atom/movable/entering)
SIGNAL_HANDLER
- if(!H || H == src)
+ if(!entering || entering == src || entering.invisibility >= INVISIBILITY_ABSTRACT || istype(entering, /atom/movable/mirage_holder)) //dont teleport ourselves, abstract objects, and mirage holders due to init shenanigans
return
- if(isobserver(H) && !affect_ghosts)
+ if(isobserver(entering) && !affect_ghosts)
return
- if(!ismob(H) && mobs_only)
+ if(!ismob(entering) && mobs_only)
return
- INVOKE_ASYNC(src, PROC_REF(Trigger), H)
+ INVOKE_ASYNC(src, PROC_REF(Trigger), entering)
/obj/effect/step_trigger/singularity_act()
@@ -144,7 +144,7 @@
var/teleport_x_offset = 0
var/teleport_y_offset = 0
-/obj/effect/step_trigger/teleporter/offset/on_entered(datum/source, H as mob|obj, atom/old_loc)
+/obj/effect/step_trigger/teleporter/offset/on_entered(datum/source, atom/movable/entered, atom/old_loc)
if(!old_loc?.Adjacent(loc)) // prevents looping, if we were teleported into this then the old loc is usually not adjacent
return
return ..()
diff --git a/code/game/objects/items/food/misc.dm b/code/game/objects/items/food/misc.dm
index 379169e6f7350..24472eb5e7a4d 100644
--- a/code/game/objects/items/food/misc.dm
+++ b/code/game/objects/items/food/misc.dm
@@ -366,25 +366,27 @@
foodtypes = DAIRY
w_class = WEIGHT_CLASS_SMALL
dog_fashion = /datum/dog_fashion/head/butter
+ var/can_stick = TRUE
/obj/item/food/butter/examine(mob/user)
. = ..()
- . += span_notice("If you had a rod you could make butter on a stick.")
+ if (can_stick)
+ . += span_notice("If you had a rod you could make butter on a stick.")
/obj/item/food/butter/attackby(obj/item/item, mob/user, params)
- if(istype(item, /obj/item/stack/rods))
- var/obj/item/stack/rods/rods = item
- if(!rods.use(1))//borgs can still fail this if they have no metal
- to_chat(user, span_warning("You do not have enough iron to put [src] on a stick!"))
- return ..()
- to_chat(user, span_notice("You stick the rod into the stick of butter."))
- var/obj/item/food/butter/on_a_stick/new_item = new(usr.loc)
- var/replace = (user.get_inactive_held_item() == rods)
- if(!rods && replace)
- user.put_in_hands(new_item)
- qdel(src)
- return TRUE
- ..()
+ if(!istype(item, /obj/item/stack/rods) || !can_stick)
+ return ..()
+ var/obj/item/stack/rods/rods = item
+ if(!rods.use(1))//borgs can still fail this if they have no metal
+ to_chat(user, span_warning("You do not have enough iron to put [src] on a stick!"))
+ return ..()
+ to_chat(user, span_notice("You stick the rod into the stick of butter."))
+ user.temporarilyRemoveItemFromInventory(src)
+ var/obj/item/food/butter/on_a_stick/new_item = new(drop_location())
+ if (user.CanReach(new_item))
+ user.put_in_hands(new_item)
+ qdel(src)
+ return TRUE
/obj/item/food/butter/on_a_stick //there's something so special about putting it on a stick.
name = "butter on a stick"
@@ -393,6 +395,7 @@
trash_type = /obj/item/stack/rods
food_flags = FOOD_FINGER_FOOD
venue_value = FOOD_PRICE_CHEAP
+ can_stick = FALSE
/obj/item/food/butter/make_processable()
AddElement(/datum/element/processable, TOOL_KNIFE, /obj/item/food/butterslice, 3, 3 SECONDS, table_required = TRUE, screentip_verb = "Slice")
diff --git a/code/game/objects/items/puzzle_pieces.dm b/code/game/objects/items/puzzle_pieces.dm
index a008acedb6d1c..a7bd4da85aebf 100644
--- a/code/game/objects/items/puzzle_pieces.dm
+++ b/code/game/objects/items/puzzle_pieces.dm
@@ -454,9 +454,10 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/puzzle/password, 32)
"green",
"blue",
"yellow",
- "orange",
- "brown",
+ COLOR_ORANGE, // orange is also not valid
+ COLOR_BROWN, // brown is NOT a valid byond color
"gray",
+ "purple",
)
for(var/digit in 0 to 9)
digit_to_color["[digit]"] = pick_n_take(possible_colors)
diff --git a/code/game/objects/structures/grille.dm b/code/game/objects/structures/grille.dm
index 4aaba04bc1835..c5a94edfdfdae 100644
--- a/code/game/objects/structures/grille.dm
+++ b/code/game/objects/structures/grille.dm
@@ -53,7 +53,8 @@
/obj/structure/grille/examine(mob/user)
. = ..()
-
+ if(resistance_flags & INDESTRUCTIBLE)
+ return
if(anchored)
. += span_notice("It's secured in place with screws. The rods look like they could be cut through.")
else
diff --git a/code/game/objects/structures/window.dm b/code/game/objects/structures/window.dm
index b3a3ea310386a..71c3ef9b6713b 100644
--- a/code/game/objects/structures/window.dm
+++ b/code/game/objects/structures/window.dm
@@ -513,6 +513,9 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/structure/window/unanchored/spawner, 0)
return FALSE
/obj/structure/window/reinforced/attackby_secondary(obj/item/tool, mob/user, params)
+ if(resistance_flags & INDESTRUCTIBLE)
+ balloon_alert(user, "too resilient!")
+ return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN
switch(state)
if(RWINDOW_SECURE)
if(tool.tool_behaviour == TOOL_WELDER)
@@ -591,7 +594,8 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/structure/window/unanchored/spawner, 0)
/obj/structure/window/reinforced/examine(mob/user)
. = ..()
-
+ if(resistance_flags & INDESTRUCTIBLE)
+ return
switch(state)
if(RWINDOW_SECURE)
. += span_notice("It's been screwed in with one way screws, you'd need to heat them to have any chance of backing them out.")
diff --git a/code/modules/awaymissions/mission_code/murderdome.dm b/code/modules/awaymissions/mission_code/murderdome.dm
index a59a491d4926f..f80c4c12ca113 100644
--- a/code/modules/awaymissions/mission_code/murderdome.dm
+++ b/code/modules/awaymissions/mission_code/murderdome.dm
@@ -1,19 +1,14 @@
/obj/structure/window/reinforced/fulltile/indestructible
name = "robust window"
+ move_resist = MOVE_FORCE_OVERPOWERING
flags_1 = PREVENT_CLICK_UNDER_1
resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF
-/obj/structure/window/reinforced/fulltile/indestructible/screwdriver_act(mob/living/user, obj/item/tool)
- return NONE
-
-/obj/structure/window/reinforced/fulltile/indestructible/wrench_act(mob/living/user, obj/item/tool)
- return NONE
-
-/obj/structure/window/reinforced/fulltile/indestructible/crowbar_act(mob/living/user, obj/item/tool)
- return NONE
/obj/structure/grille/indestructible
+ desc = "A STRONG framework of hardened plasteel rods, that you cannot possibly get through. If you were an engineer you would be drooling over its construction right now."
+ move_resist = MOVE_FORCE_OVERPOWERING
obj_flags = CONDUCTS_ELECTRICITY
resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF
diff --git a/code/modules/clothing/under/jobs/centcom.dm b/code/modules/clothing/under/jobs/centcom.dm
index da1fe5d7a1d76..ccd268eb7641d 100644
--- a/code/modules/clothing/under/jobs/centcom.dm
+++ b/code/modules/clothing/under/jobs/centcom.dm
@@ -60,6 +60,7 @@
desc = "A dark colored uniform worn by CentCom's conscripted military forces."
icon_state = "military"
inhand_icon_state = "bl_suit"
+ can_adjust = FALSE
armor_type = /datum/armor/clothing_under/centcom_military
/datum/armor/clothing_under/centcom_military
diff --git a/code/modules/fishing/fishing_rod.dm b/code/modules/fishing/fishing_rod.dm
index 08482ac6be59b..a4b1e5924f8f3 100644
--- a/code/modules/fishing/fishing_rod.dm
+++ b/code/modules/fishing/fishing_rod.dm
@@ -830,11 +830,12 @@
/obj/projectile/fishing_cast
name = "fishing hook"
icon = 'icons/obj/fishing.dmi'
- icon_state = "hook_projectile"
+ icon_state = "hook"
damage = 0
range = 5
suppressed = SUPPRESSED_VERY
can_hit_turfs = TRUE
+ projectile_angle = 180
var/obj/item/fishing_rod/owner
var/datum/beam/our_line
@@ -842,7 +843,6 @@
/obj/projectile/fishing_cast/fire(angle, atom/direct_target)
if(owner.hook)
icon_state = owner.hook.icon_state
- transform = transform.Scale(1, -1)
. = ..()
if(!QDELETED(src))
our_line = owner.create_fishing_line(src, firer)
diff --git a/code/modules/fishing/sources/source_types.dm b/code/modules/fishing/sources/source_types.dm
index b14ec608558d1..014474f9c8f9e 100644
--- a/code/modules/fishing/sources/source_types.dm
+++ b/code/modules/fishing/sources/source_types.dm
@@ -29,7 +29,7 @@
/obj/item/fish/swordfish = 5 MINUTES,
/obj/structure/mystery_box/fishing = 32 MINUTES,
)
- fishing_difficulty = FISHING_DEFAULT_DIFFICULTY + 5
+ fishing_difficulty = FISHING_DEFAULT_DIFFICULTY + 15
fish_source_flags = FISH_SOURCE_FLAG_EXPLOSIVE_MALUS
/datum/fish_source/ocean/beach
@@ -48,7 +48,7 @@
/obj/item/fish/chasm_crab/ice = 2,
/obj/item/fish/boned = 1,
)
- fishing_difficulty = FISHING_DEFAULT_DIFFICULTY + 20
+ fishing_difficulty = FISHING_DEFAULT_DIFFICULTY + 30
/datum/fish_source/river
catalog_description = "River water"
@@ -74,7 +74,7 @@
fish_count_regen = list(
/obj/item/fish/pike = 4 MINUTES,
)
- fishing_difficulty = FISHING_DEFAULT_DIFFICULTY + 5
+ fishing_difficulty = FISHING_DEFAULT_DIFFICULTY + 15
fish_source_flags = FISH_SOURCE_FLAG_EXPLOSIVE_MALUS
/datum/fish_source/sand
@@ -87,7 +87,7 @@
/obj/item/fish/bumpy = 10,
/obj/item/coin/gold = 3,
)
- fishing_difficulty = FISHING_DEFAULT_DIFFICULTY + 20
+ fishing_difficulty = FISHING_DEFAULT_DIFFICULTY + 30
fish_source_flags = FISH_SOURCE_FLAG_EXPLOSIVE_MALUS
/datum/fish_source/cursed_spring
@@ -102,7 +102,7 @@
fish_counts = list(
/obj/item/fishing_rod/telescopic/master = 1,
)
- fishing_difficulty = FISHING_DEFAULT_DIFFICULTY + 25
+ fishing_difficulty = FISHING_DEFAULT_DIFFICULTY + 35
fish_source_flags = FISH_SOURCE_FLAG_EXPLOSIVE_MALUS
/datum/fish_source/portal
@@ -154,7 +154,7 @@
/obj/item/stack/sheet/bone = 5,
)
catalog_description = "Chasm dimension (Fishing portal generator)"
- fishing_difficulty = FISHING_DEFAULT_DIFFICULTY + 10
+ fishing_difficulty = FISHING_DEFAULT_DIFFICULTY + 20
radial_name = "Chasm"
overlay_state = "portal_chasm"
radial_state = "ground_hole"
@@ -182,7 +182,7 @@
/obj/item/fish/swordfish = 5 MINUTES,
)
catalog_description = "Ocean dimension (Fishing portal generator)"
- fishing_difficulty = FISHING_DEFAULT_DIFFICULTY + 10
+ fishing_difficulty = FISHING_DEFAULT_DIFFICULTY + 20
radial_name = "Ocean"
overlay_state = "portal_ocean"
radial_state = "seaboat"
@@ -205,7 +205,7 @@
/obj/item/stack/ore/bluespace_crystal = 10,
)
catalog_description = "Hyperspace dimension (Fishing portal generator)"
- fishing_difficulty = FISHING_DEFAULT_DIFFICULTY + 10
+ fishing_difficulty = FISHING_DEFAULT_DIFFICULTY + 20
radial_name = "Hyperspace"
overlay_state = "portal_hyperspace"
radial_state = "space_rocket"
@@ -231,7 +231,7 @@
)
catalog_description = "Syndicate dimension (Fishing portal generator)"
radial_name = "Syndicate"
- fishing_difficulty = FISHING_DEFAULT_DIFFICULTY + 15
+ fishing_difficulty = FISHING_DEFAULT_DIFFICULTY + 25
overlay_state = "portal_syndicate"
radial_state = "syndi_snake"
@@ -324,7 +324,7 @@
/obj/item/fish/chasm_crab = 15,
/datum/chasm_detritus = 30,
)
- fishing_difficulty = FISHING_DEFAULT_DIFFICULTY + 5
+ fishing_difficulty = FISHING_DEFAULT_DIFFICULTY + 15
/datum/fish_source/chasm/on_start_fishing(obj/item/fishing_rod/rod, mob/fisherman, atom/parent)
. = ..()
@@ -362,7 +362,7 @@
fish_count_regen = list(
/obj/structure/closet/crate/necropolis/tendril = 27 MINUTES,
)
- fishing_difficulty = FISHING_DEFAULT_DIFFICULTY + 10
+ fishing_difficulty = FISHING_DEFAULT_DIFFICULTY + 20
fish_source_flags = FISH_SOURCE_FLAG_EXPLOSIVE_MALUS
/datum/fish_source/lavaland/reason_we_cant_fish(obj/item/fishing_rod/rod, mob/fisherman, atom/parent)
@@ -404,7 +404,7 @@
/obj/item/fish/ratfish = 10,
/obj/item/fish/slimefish = 4,
)
- fishing_difficulty = FISHING_DEFAULT_DIFFICULTY + 10
+ fishing_difficulty = FISHING_DEFAULT_DIFFICULTY + 20
/datum/fish_source/toilet
catalog_description = "Station toilets"
@@ -422,7 +422,7 @@
/obj/item/storage/wallet/money = 2,
/obj/item/survivalcapsule/fishing = 1,
)
- fishing_difficulty = FISHING_EASY_DIFFICULTY //For beginners
+ fishing_difficulty = FISHING_EASY_DIFFICULTY + 10
/datum/fish_source/holographic
catalog_description = "Holographic water"
@@ -435,7 +435,7 @@
/obj/item/fish/holo/checkered = 5,
/obj/item/fish/holo/halffish = 5,
)
- fishing_difficulty = FISHING_EASY_DIFFICULTY
+ fishing_difficulty = FISHING_EASY_DIFFICULTY + 10
fish_source_flags = FISH_SOURCE_FLAG_NO_BLUESPACE_ROD
/datum/fish_source/holographic/on_fishing_spot_init(datum/component/fishing_spot/spot)
@@ -492,7 +492,7 @@
fish_count_regen = list(
/obj/item/fish/mastodon = 8 MINUTES,
)
- fishing_difficulty = FISHING_DEFAULT_DIFFICULTY + 15
+ fishing_difficulty = FISHING_DEFAULT_DIFFICULTY + 25
/datum/fish_source/hydro_tray
catalog_description = "Hydroponics trays"
@@ -515,7 +515,7 @@
/mob/living/basic/frog = 1,
/mob/living/basic/axolotl = 1,
)
- fishing_difficulty = FISHING_EASY_DIFFICULTY - 5
+ fishing_difficulty = FISHING_EASY_DIFFICULTY + 5
/datum/fish_source/hydro_tray/generate_wiki_contents(datum/autowiki/fish_sources/wiki)
var/list/data = list()
@@ -624,7 +624,7 @@
fish_count_regen = list(
/mob/living/basic/carp/mega = 9 MINUTES,
)
- fishing_difficulty = FISHING_DEFAULT_DIFFICULTY + 18
+ fishing_difficulty = FISHING_DEFAULT_DIFFICULTY + 28
/datum/fish_source/deepfryer
catalog_description = "Deep Fryers"
@@ -647,7 +647,7 @@
/obj/item/fish/fryish/fritterish = 6 MINUTES,
/obj/item/fish/fryish/nessie = 22 MINUTES,
)
- fishing_difficulty = FISHING_DEFAULT_DIFFICULTY + 13
+ fishing_difficulty = FISHING_DEFAULT_DIFFICULTY + 23
/datum/fish_source/surgery
catalog_description = "Surgery"
@@ -656,7 +656,7 @@
background = "background_lavaland" //Kinda red.
fish_table = list(FISHING_RANDOM_ORGAN = 10)
//This should get you below zero difficulty and skip the minigame phase, unless you're wearing something that counteracts this.
- fishing_difficulty = -20
+ fishing_difficulty = -10
//The range for waiting is also a bit narrower, so it cannot take as few as 3 seconds or as many as 25 to snatch an organ.
wait_time_range = list(6 SECONDS, 12 SECONDS)
@@ -706,7 +706,7 @@
FISHING_DUD = 10,
)
fish_source_flags = FISH_SOURCE_FLAG_NO_BLUESPACE_ROD|FISH_SOURCE_FLAG_IGNORE_HIDDEN_ON_CATALOG
- fishing_difficulty = FISHING_EASY_DIFFICULTY - 5
+ fishing_difficulty = FISHING_EASY_DIFFICULTY + 5
#undef RANDOM_AQUARIUM_FISH
@@ -756,7 +756,7 @@
fish_count_regen = list(
/obj/item/fish/sacabambaspis = 4 MINUTES,
)
- fishing_difficulty = FISHING_DEFAULT_DIFFICULTY + 20
+ fishing_difficulty = FISHING_DEFAULT_DIFFICULTY + 30
fish_source_flags = FISH_SOURCE_FLAG_EXPLOSIVE_MALUS
/datum/fish_source/tizira
@@ -771,5 +771,5 @@
/obj/item/fish/moonfish/dwarf = 2,
/obj/item/fish/moonfish = 2,
)
- fishing_difficulty = FISHING_DEFAULT_DIFFICULTY + 10
+ fishing_difficulty = FISHING_DEFAULT_DIFFICULTY + 20
fish_source_flags = FISH_SOURCE_FLAG_EXPLOSIVE_MALUS
diff --git a/code/modules/mapfluff/ruins/objects_and_mobs/museum.dm b/code/modules/mapfluff/ruins/objects_and_mobs/museum.dm
index c8b504b72e572..58d5754ccccf3 100644
--- a/code/modules/mapfluff/ruins/objects_and_mobs/museum.dm
+++ b/code/modules/mapfluff/ruins/objects_and_mobs/museum.dm
@@ -77,16 +77,16 @@
name = /obj/machinery/atmospherics/components/unary/vent_scrubber::name
desc = /obj/machinery/atmospherics/components/unary/vent_scrubber::desc
icon = /obj/machinery/atmospherics/components/unary/vent_scrubber::icon
- layer = /obj/machinery/atmospherics/components/unary/vent_scrubber::layer
- plane = /obj/machinery/atmospherics/components/unary/vent_scrubber::plane
+ layer = ABOVE_OPEN_TURF_LAYER
+ plane = FLOOR_PLANE
icon_state = "scrub_on"
/obj/structure/fluff/fake_vent
name = /obj/machinery/atmospherics/components/unary/vent_pump::name
desc = /obj/machinery/atmospherics/components/unary/vent_pump::desc
icon = /obj/machinery/atmospherics/components/unary/vent_pump::icon
- layer = /obj/machinery/atmospherics/components/unary/vent_pump::layer
- plane = /obj/machinery/atmospherics/components/unary/vent_pump::plane
+ layer = ABOVE_OPEN_TURF_LAYER
+ plane = FLOOR_PLANE
icon_state = "vent_out"
/turf/open/mirage
diff --git a/code/modules/mining/laborcamp/laborstacker.dm b/code/modules/mining/laborcamp/laborstacker.dm
index e7966764b6a96..75d532249f492 100644
--- a/code/modules/mining/laborcamp/laborstacker.dm
+++ b/code/modules/mining/laborcamp/laborstacker.dm
@@ -12,16 +12,30 @@
var/obj/machinery/mineral/stacking_machine/laborstacker/stacking_machine
/// Needed to send messages to sec radio
var/obj/item/radio/security_radio
+ /// Whether the claim console initiated the launch.
+ var/initiated_launch = FALSE
+ /// Cooldown for console says.
+ COOLDOWN_DECLARE(say_cooldown)
/obj/machinery/mineral/labor_claim_console/Initialize(mapload)
. = ..()
security_radio = new /obj/item/radio(src)
security_radio.set_listening(FALSE)
locate_stacking_machine()
+ if(!SSshuttle.initialized)
+ RegisterSignal(SSshuttle, COMSIG_SUBSYSTEM_POST_INITIALIZE, PROC_REF(register_shuttle_signal))
+ else
+ register_shuttle_signal()
//If we can't find a stacking machine end it all ok?
if(!stacking_machine)
return INITIALIZE_HINT_QDEL
+/obj/machinery/mineral/labor_claim_console/proc/register_shuttle_signal()
+ SIGNAL_HANDLER
+ var/obj/docking_port/mobile/laborshuttle = SSshuttle.getShuttle("laborcamp")
+ RegisterSignal(laborshuttle, COMSIG_SHUTTLE_SHOULD_MOVE, PROC_REF(on_laborshuttle_can_move))
+ UnregisterSignal(SSshuttle, COMSIG_SUBSYSTEM_POST_INITIALIZE)
+
/obj/machinery/mineral/labor_claim_console/Destroy()
QDEL_NULL(security_radio)
if(stacking_machine)
@@ -86,23 +100,34 @@
var/obj/item/card/id/advanced/prisoner/worn_prisoner_id = worn_id
worn_prisoner_id.points += stacking_machine.points
stacking_machine.points = 0
- to_chat(user_mob, span_notice("Points transferred."))
+ say("Points transferred.")
return TRUE
else
- to_chat(user_mob, span_alert("No valid id for point transfer detected."))
+ if(COOLDOWN_FINISHED(src, say_cooldown))
+ say("No valid id for point transfer detected.")
+ COOLDOWN_START(src, say_cooldown, 2 SECONDS)
if("move_shuttle")
- if(!alone_in_area(get_area(src), user_mob))
- to_chat(user_mob, span_alert("Prisoners are only allowed to be released while alone."))
+ var/list/labor_shuttle_mobs = find_labor_shuttle_mobs()
+ if(length(labor_shuttle_mobs) > 1 || labor_shuttle_mobs[1] != user_mob)
+ if(COOLDOWN_FINISHED(src, say_cooldown))
+ say("Prisoners may only be released one at a time.")
+ COOLDOWN_START(src, say_cooldown, 2 SECONDS)
return
switch(SSshuttle.moveShuttle("laborcamp", "laborcamp_home", TRUE))
if(1)
- to_chat(user_mob, span_alert("Shuttle not found."))
+ if(COOLDOWN_FINISHED(src, say_cooldown))
+ say("Shuttle not found.")
+ COOLDOWN_START(src, say_cooldown, 2 SECONDS)
if(2)
- to_chat(user_mob, span_alert("Shuttle already at station."))
+ if(COOLDOWN_FINISHED(src, say_cooldown))
+ say("Shuttle already at station.")
+ COOLDOWN_START(src, say_cooldown, 2 SECONDS)
if(3)
- to_chat(user_mob, span_alert("No permission to dock could be granted."))
+ if(COOLDOWN_FINISHED(src, say_cooldown))
+ say("No permission to dock could be granted.")
+ COOLDOWN_START(src, say_cooldown, 2 SECONDS)
else
if(!(obj_flags & EMAGGED))
security_radio.set_frequency(FREQ_SECURITY)
@@ -111,9 +136,29 @@
security_radio.talk_into(src, "[user_mob.name] returned to the station. Minerals and Prisoner ID card ready for retrieval.", FREQ_SECURITY)
user_mob.log_message("has completed their labor points goal and is now sending the gulag shuttle back to the station.", LOG_GAME)
- to_chat(user_mob, span_notice("Shuttle received message and will be sent shortly."))
+ say("Labor sentence finished, shuttle returning.")
+ initiated_launch = TRUE
return TRUE
+/obj/machinery/mineral/labor_claim_console/proc/find_labor_shuttle_mobs()
+ var/list/prisoners = mobs_in_area_type(list(get_area(src)))
+
+ // security personnel and nonhumans do not count towards this
+ for(var/mob/living/mob as anything in prisoners)
+ var/obj/item/card/id/card = mob.get_idcard(FALSE)
+ if(!ishuman(mob) || (ACCESS_BRIG in card?.GetAccess()))
+ prisoners -= mob
+
+ return prisoners
+
+/obj/machinery/mineral/labor_claim_console/proc/on_laborshuttle_can_move(obj/docking_port/mobile/source)
+ SIGNAL_HANDLER
+
+ if(initiated_launch && length(find_labor_shuttle_mobs()) > 1)
+ initiated_launch = FALSE
+ say("Takeoff aborted. Prisoners may only be released one at a time.")
+ return BLOCK_SHUTTLE_MOVE
+
/obj/machinery/mineral/labor_claim_console/proc/locate_stacking_machine()
stacking_machine = locate(/obj/machinery/mineral/stacking_machine) in dview(2, get_turf(src))
if(stacking_machine)
diff --git a/code/modules/mod/modules/modules_engineering.dm b/code/modules/mod/modules/modules_engineering.dm
index abe09594500c1..ea12a61e5b4d4 100644
--- a/code/modules/mod/modules/modules_engineering.dm
+++ b/code/modules/mod/modules/modules_engineering.dm
@@ -91,6 +91,13 @@
cooldown_time = 1.5 SECONDS
required_slots = list(ITEM_SLOT_GLOVES)
+/obj/item/mod/module/tether/used()
+ if(HAS_TRAIT_FROM(mod.wearer, TRAIT_TETHER_ATTACHED, REF(src)))
+ balloon_alert(mod.wearer, "already tethered!")
+ playsound(src, 'sound/items/weapons/gun/general/dry_fire.ogg', 25, TRUE)
+ return FALSE
+ return ..()
+
/obj/item/mod/module/tether/on_select_use(atom/target)
. = ..()
if(!.)
@@ -139,7 +146,10 @@
/obj/projectile/tether/proc/on_embedded(datum/source, obj/item/payload, atom/hit)
SIGNAL_HANDLER
- firer.AddComponent(/datum/component/tether, hit, 7, "MODtether", payload, parent_module = parent_module)
+ if (HAS_TRAIT_FROM(hit, TRAIT_TETHER_ATTACHED, REF(parent_module)))
+ return
+
+ firer.AddComponent(/datum/component/tether, hit, 7, "MODtether", payload, parent_module = parent_module, tether_trait_source = REF(parent_module))
/obj/projectile/tether/Moved(atom/old_loc, movement_dir, forced, list/old_locs, momentum_change)
. = ..()
@@ -161,7 +171,12 @@
return
if (istype(target, /obj/item/tether_anchor) || isstructure(target) || ismachinery(target))
- firer.AddComponent(/datum/component/tether, target, 7, "MODtether", parent_module = parent_module)
+ if(HAS_TRAIT_FROM(target, TRAIT_TETHER_ATTACHED, REF(parent_module)))
+ return
+ var/avoid_target_trait = FALSE
+ if (istype(target, /obj/item/tether_anchor))
+ avoid_target_trait = TRUE
+ firer.AddComponent(/datum/component/tether, target, 7, "MODtether", parent_module = parent_module, tether_trait_source = REF(parent_module), no_target_trait = avoid_target_trait)
return
var/hitx = impact_x
@@ -182,7 +197,7 @@
anchor.pixel_x = hitx
anchor.pixel_y = hity
anchor.anchored = TRUE
- firer.AddComponent(/datum/component/tether, anchor, 7, "MODtether", parent_module = parent_module)
+ firer.AddComponent(/datum/component/tether, anchor, 7, "MODtether", parent_module = parent_module, tether_trait_source = REF(parent_module))
/obj/projectile/tether/Destroy()
QDEL_NULL(line)
@@ -210,8 +225,12 @@
if (!can_interact(user) || !user.CanReach(src) || !isturf(loc))
return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN
+ if(HAS_TRAIT_FROM(user, TRAIT_TETHER_ATTACHED, REF(src)))
+ balloon_alert(user, "already tethered!")
+ return
+
balloon_alert(user, "attached tether")
- user.AddComponent(/datum/component/tether, src, 7, "tether")
+ user.AddComponent(/datum/component/tether, src, 7, "tether", tether_trait_source = REF(src))
return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN
/obj/item/tether_anchor/mouse_drop_receive(atom/target, mob/user, params)
@@ -221,9 +240,13 @@
if (!isliving(target) || !target.CanReach(src))
return
+ if(HAS_TRAIT_FROM(target, TRAIT_TETHER_ATTACHED, REF(src)))
+ balloon_alert(user, "already tethered!")
+ return
+
if (target == user)
balloon_alert(user, "attached tether")
- user.AddComponent(/datum/component/tether, src, 7, "tether")
+ user.AddComponent(/datum/component/tether, src, 7, "tether", tether_trait_source = REF(src), no_target_trait = TRUE)
return
balloon_alert(user, "attaching tether...")
@@ -231,9 +254,13 @@
if (!do_after(user, 5 SECONDS, target))
return
+ if(HAS_TRAIT_FROM(target, TRAIT_TETHER_ATTACHED, REF(src)))
+ balloon_alert(user, "already tethered!")
+ return
+
balloon_alert(user, "attached tether")
to_chat(target, span_userdanger("[user] attaches a tether to you!"))
- target.AddComponent(/datum/component/tether, src, 7, "tether")
+ target.AddComponent(/datum/component/tether, src, 7, "tether", tether_trait_source = REF(src), no_target_trait = TRUE)
/datum/embed_data/tether_projectile
embed_chance = 65 //spiky
diff --git a/code/modules/paperwork/paper.dm b/code/modules/paperwork/paper.dm
index 525cb8aac2310..4ef8ee396f780 100644
--- a/code/modules/paperwork/paper.dm
+++ b/code/modules/paperwork/paper.dm
@@ -634,7 +634,7 @@
var/stamp_icon_state = stamp_info["stamp_icon_state"]
if (LAZYLEN(raw_stamp_data) >= MAX_PAPER_STAMPS)
- to_chat(usr, pick("You try to stamp but you miss!", "There is no where else you can stamp!"))
+ to_chat(usr, pick("You try to stamp but you miss!", "There is nowhere else you can stamp!"))
return TRUE
add_stamp(stamp_class, stamp_x, stamp_y, stamp_rotation, stamp_icon_state)
@@ -649,7 +649,7 @@
var/this_input_length = length_char(paper_input)
if(this_input_length == 0)
- to_chat(user, pick("Writing block strikes again!", "You forgot to write anthing!"))
+ to_chat(user, pick("Writing block strikes again!", "You forgot to write anything!"))
return TRUE
// If the paper is on an unwritable noticeboard, this usually shouldn't be possible.
diff --git a/code/modules/projectiles/projectile.dm b/code/modules/projectiles/projectile.dm
index 43ef0eee70fe5..44498febc402d 100644
--- a/code/modules/projectiles/projectile.dm
+++ b/code/modules/projectiles/projectile.dm
@@ -112,6 +112,8 @@
var/nondirectional_sprite = FALSE
/// Random spread done projectile-side for convinience
var/spread = 0
+ /// Additional rotation for the projectile, in case it uses some object's sprite
+ var/projectile_angle = 0
/// Gliding does not enjoy something getting moved multiple turfs in a tick, which is why we animate it manually
animate_movement = NO_STEPS
@@ -773,7 +775,7 @@
stack_trace("WARNING: Projectile [type] deleted due to being unable to resolve a target after angle was null!")
qdel(src)
return
- var/turf/target = locate(clamp(starting + xo, 1, world.maxx), clamp(starting + yo, 1, world.maxy), starting.z)
+ var/turf/target = locate(clamp(starting.x + xo, 1, world.maxx), clamp(starting.y + yo, 1, world.maxy), starting.z)
set_angle(get_angle(src, target))
if (spread)
set_angle(angle + (rand() - 0.5) * spread)
@@ -815,7 +817,7 @@
if (angle == new_angle)
return
if(!nondirectional_sprite)
- transform = transform.TurnTo(angle, new_angle)
+ transform = transform.TurnTo(angle, new_angle + projectile_angle)
angle = new_angle
if(movement_vector)
movement_vector.set_angle(new_angle)
@@ -827,7 +829,7 @@
if (angle == new_angle)
return
if(!nondirectional_sprite)
- transform = transform.TurnTo(angle, new_angle)
+ transform = transform.TurnTo(angle, new_angle + projectile_angle)
free_hitscan_forceMove = TRUE
forceMove(center_turf)
entry_x = 0
diff --git a/code/modules/reagents/chemistry/reagents/drinks/alcohol_reagents.dm b/code/modules/reagents/chemistry/reagents/drinks/alcohol_reagents.dm
index 74ffea08af70d..76c88142c92f8 100644
--- a/code/modules/reagents/chemistry/reagents/drinks/alcohol_reagents.dm
+++ b/code/modules/reagents/chemistry/reagents/drinks/alcohol_reagents.dm
@@ -2655,7 +2655,7 @@
var/mob/living/carbon/exposed_carbon = exposed_mob
var/obj/item/organ/stomach/ethereal/stomach = exposed_carbon.get_organ_slot(ORGAN_SLOT_STOMACH)
if(istype(stomach))
- stomach.adjust_charge(reac_volume * 0.02 * ETHEREAL_CHARGE_NORMAL)
+ stomach.adjust_charge(reac_volume * 0.001 * ETHEREAL_CHARGE_NORMAL)
/datum/reagent/consumable/ethanol/telepole
name = "Telepole"
@@ -2675,7 +2675,7 @@
var/mob/living/carbon/exposed_carbon = exposed_mob
var/obj/item/organ/stomach/ethereal/stomach = exposed_carbon.get_organ_slot(ORGAN_SLOT_STOMACH)
if(istype(stomach))
- stomach.adjust_charge(reac_volume * 0.05 * ETHEREAL_CHARGE_NORMAL)
+ stomach.adjust_charge(reac_volume * 0.008 * ETHEREAL_CHARGE_NORMAL)
/datum/reagent/consumable/ethanol/pod_tesla
name = "Pod Tesla"
@@ -2702,7 +2702,7 @@
var/mob/living/carbon/exposed_carbon = exposed_mob
var/obj/item/organ/stomach/ethereal/stomach = exposed_carbon.get_organ_slot(ORGAN_SLOT_STOMACH)
if(istype(stomach))
- stomach.adjust_charge(reac_volume * 0.1 * ETHEREAL_CHARGE_NORMAL)
+ stomach.adjust_charge(reac_volume * 0.03 * ETHEREAL_CHARGE_NORMAL)
// Welcome to the Blue Room Bar and Grill, home to Mars' finest cocktails
/datum/reagent/consumable/ethanol/rice_beer
diff --git a/code/modules/shuttle/shuttle.dm b/code/modules/shuttle/shuttle.dm
index b853d949d464c..dd82bdf7051af 100644
--- a/code/modules/shuttle/shuttle.dm
+++ b/code/modules/shuttle/shuttle.dm
@@ -644,6 +644,9 @@
//this is a hook for custom behaviour. Maybe at some point we could add checks to see if engines are intact
/obj/docking_port/mobile/proc/canMove()
+ SHOULD_CALL_PARENT(TRUE)
+ if(SEND_SIGNAL(src, COMSIG_SHUTTLE_SHOULD_MOVE) & BLOCK_SHUTTLE_MOVE)
+ return FALSE
return TRUE
//this is to check if this shuttle can physically dock at dock stationary_dock
diff --git a/code/modules/shuttle/supply.dm b/code/modules/shuttle/supply.dm
index 665a9c4024172..192cc44dd94f0 100644
--- a/code/modules/shuttle/supply.dm
+++ b/code/modules/shuttle/supply.dm
@@ -55,9 +55,11 @@ GLOBAL_LIST_INIT(blacklisted_cargo_types, typecacheof(list(
SSshuttle.supply = src
/obj/docking_port/mobile/supply/canMove()
+ . = ..()
+ if(!.)
+ return FALSE
if(is_station_level(z))
return check_blacklist(shuttle_areas)
- return ..()
/obj/docking_port/mobile/supply/proc/check_blacklist(areaInstances)
for(var/area/shuttle_area as anything in areaInstances)
diff --git a/code/modules/vehicles/mecha/_mecha.dm b/code/modules/vehicles/mecha/_mecha.dm
index ccb211a2a6678..301f3a7115891 100644
--- a/code/modules/vehicles/mecha/_mecha.dm
+++ b/code/modules/vehicles/mecha/_mecha.dm
@@ -836,7 +836,7 @@
/obj/vehicle/sealed/mecha/on_saboteur(datum/source, disrupt_duration)
. = ..()
- if(mecha_flags &= HAS_LIGHTS && light_on)
+ if((mecha_flags & HAS_LIGHTS) && light_on)
set_light_on(FALSE)
return TRUE
diff --git a/code/modules/vehicles/mecha/equipment/tools/mining_tools.dm b/code/modules/vehicles/mecha/equipment/tools/mining_tools.dm
index cdbf45362e41b..b1585f679a22c 100644
--- a/code/modules/vehicles/mecha/equipment/tools/mining_tools.dm
+++ b/code/modules/vehicles/mecha/equipment/tools/mining_tools.dm
@@ -11,7 +11,6 @@
icon_state = "mecha_drill"
equipment_slot = MECHA_UTILITY
can_be_toggled = TRUE
- active = FALSE
equip_cooldown = 15
energy_drain = 0.01 * STANDARD_CELL_CHARGE
force = 15
@@ -112,6 +111,10 @@
if(target_obj.resistance_flags & (UNACIDABLE | INDESTRUCTIBLE))
return
+ // Check if we can even use the equipment to begin with.
+ if(!action_checks(target))
+ return
+
// You can't drill harder by clicking more.
if(DOING_INTERACTION_WITH_TARGET(source, target) && do_after_cooldown(target, source, DOAFTER_SOURCE_MECHADRILL))
return
@@ -124,10 +127,6 @@
// Drilling a turf is a one-and-done procedure.
if(isturf(target))
- // Check if we can even use the equipment to begin with.
- if(!action_checks(target))
- return
-
var/turf/T = target
T.drill_act(src, source)
diff --git a/html/changelogs/AutoChangeLog-pr-87747.yml b/html/changelogs/AutoChangeLog-pr-87747.yml
deleted file mode 100644
index c31da63a14399..0000000000000
--- a/html/changelogs/AutoChangeLog-pr-87747.yml
+++ /dev/null
@@ -1,15 +0,0 @@
-author: "timothymtorres"
-delete-after: True
-changes:
- - rscadd: "The revenant defile spell now affects showers by removing all water recyclers and reagents that gets replaced with blood."
- - rscadd: "Showering in clean water (+70%) results in positive mood/regen/stamina effects. It will wash off the mob."
- - rscadd: "Showering in dirty water results in negative mood effects and disgust. It will NOT wash off the mob."
- - rscadd: "Showering with radioactive reagents (+20%) results in the preventing the shower from washing off the radiation."
- - rscadd: "Showering in blood (+70%) results in severe negative mood effects and disgust. (unless you are morbid, evil, or undead then it's considered positive) It will cover the mob in blood."
- - rscadd: "Water effects that interact with a mob from touch or vapor (showering/spray bottles/etc.) will now heal sleep, unconsciousness, confusion, drowsiness, jitters, dizziness, and drunkenness."
- - bugfix: "Fix bloody showers not covering objects in blood."
- - bugfix: "Tossing or spraying a container full of blood now covers objects/mobs in blood"
- - bugfix: "Fix wrong status effect for watery tile"
- - image: "Add new alert icons for bloody/dirty showers"
- - code_imp: "Refactored some expose_obj reagent code to support method types."
- - code_imp: "Improved mood typecasting for owner to allow checking of mob biotypes."
\ No newline at end of file
diff --git a/html/changelogs/AutoChangeLog-pr-88196.yml b/html/changelogs/AutoChangeLog-pr-88196.yml
new file mode 100644
index 0000000000000..0b3fa848bc7a9
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-88196.yml
@@ -0,0 +1,4 @@
+author: "norsvenska"
+delete-after: True
+changes:
+ - spellcheck: "You are no longer faced with a typo after either not writing on paper, or attempting to stamp a paper that's been stamped too many times."
\ No newline at end of file
diff --git a/html/changelogs/AutoChangeLog-pr-88263.yml b/html/changelogs/AutoChangeLog-pr-88263.yml
deleted file mode 100644
index 4676ef4e79c09..0000000000000
--- a/html/changelogs/AutoChangeLog-pr-88263.yml
+++ /dev/null
@@ -1,4 +0,0 @@
-author: "SmArtKar"
-delete-after: True
-changes:
- - bugfix: "Fixed plasmamen envirosuits being unrepairable"
\ No newline at end of file
diff --git a/html/changelogs/AutoChangeLog-pr-88264.yml b/html/changelogs/AutoChangeLog-pr-88264.yml
deleted file mode 100644
index 5f2a45c86d698..0000000000000
--- a/html/changelogs/AutoChangeLog-pr-88264.yml
+++ /dev/null
@@ -1,4 +0,0 @@
-author: "SmArtKar, Kapu"
-delete-after: True
-changes:
- - bugfix: "Atmospheric tanks no longer fetch icons every tick"
\ No newline at end of file
diff --git a/html/changelogs/AutoChangeLog-pr-88270.yml b/html/changelogs/AutoChangeLog-pr-88270.yml
deleted file mode 100644
index a41b80a16f429..0000000000000
--- a/html/changelogs/AutoChangeLog-pr-88270.yml
+++ /dev/null
@@ -1,4 +0,0 @@
-author: "SmArtKar"
-delete-after: True
-changes:
- - bugfix: "Fixed cargo ticket and pet adventure drone loot pools not working"
\ No newline at end of file
diff --git a/html/changelogs/AutoChangeLog-pr-88271.yml b/html/changelogs/AutoChangeLog-pr-88271.yml
deleted file mode 100644
index 7390d0b42203b..0000000000000
--- a/html/changelogs/AutoChangeLog-pr-88271.yml
+++ /dev/null
@@ -1,4 +0,0 @@
-author: "larentoun"
-delete-after: True
-changes:
- - bugfix: "Printed Moth X-Ray eyes are now correctly named, instead of being just \"robotic eyes\""
\ No newline at end of file
diff --git a/html/changelogs/AutoChangeLog-pr-88273.yml b/html/changelogs/AutoChangeLog-pr-88273.yml
deleted file mode 100644
index 74a9cb80c78fc..0000000000000
--- a/html/changelogs/AutoChangeLog-pr-88273.yml
+++ /dev/null
@@ -1,4 +0,0 @@
-author: "larentoun"
-delete-after: True
-changes:
- - bugfix: "Printed advanced robotic right leg now has correct name, instead of being \"heavy\""
\ No newline at end of file
diff --git a/html/changelogs/AutoChangeLog-pr-88280.yml b/html/changelogs/AutoChangeLog-pr-88280.yml
new file mode 100644
index 0000000000000..b1d694362bef4
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-88280.yml
@@ -0,0 +1,5 @@
+author: "SmArtKar"
+delete-after: True
+changes:
+ - qol: "Mining drills are now active by default"
+ - bugfix: "Fixes mining drill displaying drilling messages while inactive"
\ No newline at end of file
diff --git a/html/changelogs/AutoChangeLog-pr-88287.yml b/html/changelogs/AutoChangeLog-pr-88287.yml
new file mode 100644
index 0000000000000..f56dc91c73179
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-88287.yml
@@ -0,0 +1,5 @@
+author: "mc-oofert"
+delete-after: True
+changes:
+ - bugfix: "fixed the museum password puzzle (to the cafeteria), and the scrubbers and vents there now look correctly (also fixed a rare visual bug)"
+ - bugfix: "it is now harder to bypass indestructible windows and grilles (those are placed there for a reason, you know!)"
\ No newline at end of file
diff --git a/html/changelogs/AutoChangeLog-pr-88289.yml b/html/changelogs/AutoChangeLog-pr-88289.yml
new file mode 100644
index 0000000000000..4335f68afb41a
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-88289.yml
@@ -0,0 +1,5 @@
+author: "SmArtKar"
+delete-after: True
+changes:
+ - bugfix: "You cannot have more than one MODtether (excluding manual connections)"
+ - qol: "Tethers are easier to cut (require less pixelhunting)"
\ No newline at end of file
diff --git a/html/changelogs/AutoChangeLog-pr-88294.yml b/html/changelogs/AutoChangeLog-pr-88294.yml
new file mode 100644
index 0000000000000..c65b6e1ac862f
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-88294.yml
@@ -0,0 +1,4 @@
+author: "Ghommie"
+delete-after: True
+changes:
+ - balance: "brought fishing difficulty of all fishing spots a bit closer to their original value following a small oopsie that made them unexpectingly easier for more than two months."
\ No newline at end of file
diff --git a/html/changelogs/AutoChangeLog-pr-88296.yml b/html/changelogs/AutoChangeLog-pr-88296.yml
new file mode 100644
index 0000000000000..d2cd58ee55fe4
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-88296.yml
@@ -0,0 +1,4 @@
+author: "Ghommie"
+delete-after: True
+changes:
+ - bugfix: "Fixed fishing lures."
\ No newline at end of file
diff --git a/html/changelogs/AutoChangeLog-pr-88297.yml b/html/changelogs/AutoChangeLog-pr-88297.yml
new file mode 100644
index 0000000000000..c26c801622468
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-88297.yml
@@ -0,0 +1,4 @@
+author: "SmArtKar"
+delete-after: True
+changes:
+ - bugfix: "Fixed flipped fishing hooks"
\ No newline at end of file
diff --git a/html/changelogs/AutoChangeLog-pr-88298.yml b/html/changelogs/AutoChangeLog-pr-88298.yml
new file mode 100644
index 0000000000000..52340e98d2352
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-88298.yml
@@ -0,0 +1,4 @@
+author: "SmArtKar"
+delete-after: True
+changes:
+ - bugfix: "Fixed lunar parade soundloop"
\ No newline at end of file
diff --git a/html/changelogs/AutoChangeLog-pr-88299.yml b/html/changelogs/AutoChangeLog-pr-88299.yml
new file mode 100644
index 0000000000000..6c22baf083193
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-88299.yml
@@ -0,0 +1,4 @@
+author: "OrionTheFox"
+delete-after: True
+changes:
+ - bugfix: "fixed the \"tactical combat/engineering uniform\" allowing toggling with no alt sprite"
\ No newline at end of file
diff --git a/html/changelogs/AutoChangeLog-pr-88301.yml b/html/changelogs/AutoChangeLog-pr-88301.yml
new file mode 100644
index 0000000000000..934ae26dc9a21
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-88301.yml
@@ -0,0 +1,4 @@
+author: "SmArtKar"
+delete-after: True
+changes:
+ - bugfix: "You can no longer stick a butter on a stick on a stick"
\ No newline at end of file
diff --git a/html/changelogs/AutoChangeLog-pr-88304.yml b/html/changelogs/AutoChangeLog-pr-88304.yml
new file mode 100644
index 0000000000000..fde2324baadf9
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-88304.yml
@@ -0,0 +1,4 @@
+author: "githubuser4141"
+delete-after: True
+changes:
+ - bugfix: "fixes splinter cell pistols causing mechs to suddenly have all their flags deleted"
\ No newline at end of file
diff --git a/html/changelogs/archive/2024-12.yml b/html/changelogs/archive/2024-12.yml
new file mode 100644
index 0000000000000..82bac40d727ea
--- /dev/null
+++ b/html/changelogs/archive/2024-12.yml
@@ -0,0 +1,41 @@
+2024-12-01:
+ KingkumaArt:
+ - bugfix: Etherials no longer lose overcharge really slowly.
+ - bugfix: Etherial Wine/Telepole no longer overcharges etherials with one sip.
+ OrionTheFox:
+ - image: resprited the (Analog) Wall Clock
+ SmArtKar:
+ - bugfix: Fixed cargo ticket and pet adventure drone loot pools not working
+ - bugfix: Fixed plasmamen envirosuits being unrepairable
+ SmArtKar, Kapu:
+ - bugfix: Atmospheric tanks no longer fetch icons every tick
+ distributivgesetz:
+ - bugfix: The labor shuttle can no longer be cheesed by piggybacking a prisoner
+ who has completed their sentence.
+ larentoun:
+ - bugfix: Printed advanced robotic right leg now has correct name, instead of being
+ "heavy"
+ - bugfix: Printed Moth X-Ray eyes are now correctly named, instead of being just
+ "robotic eyes"
+ timothymtorres:
+ - rscadd: The revenant defile spell now affects showers by removing all water recyclers
+ and reagents that gets replaced with blood.
+ - rscadd: Showering in clean water (+70%) results in positive mood/regen/stamina
+ effects. It will wash off the mob.
+ - rscadd: Showering in dirty water results in negative mood effects and disgust.
+ It will NOT wash off the mob.
+ - rscadd: Showering with radioactive reagents (+20%) results in the preventing the
+ shower from washing off the radiation.
+ - rscadd: Showering in blood (+70%) results in severe negative mood effects and
+ disgust. (unless you are morbid, evil, or undead then it's considered positive)
+ It will cover the mob in blood.
+ - rscadd: Water effects that interact with a mob from touch or vapor (showering/spray
+ bottles/etc.) will now heal sleep, unconsciousness, confusion, drowsiness, jitters,
+ dizziness, and drunkenness.
+ - bugfix: Fix bloody showers not covering objects in blood.
+ - bugfix: Tossing or spraying a container full of blood now covers objects/mobs
+ in blood
+ - bugfix: Fix wrong status effect for watery tile
+ - image: Add new alert icons for bloody/dirty showers
+ - code_imp: Refactored some expose_obj reagent code to support method types.
+ - code_imp: Improved mood typecasting for owner to allow checking of mob biotypes.
diff --git a/icons/obj/clothing/modsuit/mod_modules.dmi b/icons/obj/clothing/modsuit/mod_modules.dmi
index 9811af0b54838..f91f9f0b9dcaf 100644
Binary files a/icons/obj/clothing/modsuit/mod_modules.dmi and b/icons/obj/clothing/modsuit/mod_modules.dmi differ
diff --git a/icons/obj/fishing.dmi b/icons/obj/fishing.dmi
index ac307ae23842d..58ab9944366dd 100644
Binary files a/icons/obj/fishing.dmi and b/icons/obj/fishing.dmi differ
diff --git a/icons/obj/signs.dmi b/icons/obj/signs.dmi
index 4e0ce76cd8672..1f844f2a2cac4 100644
Binary files a/icons/obj/signs.dmi and b/icons/obj/signs.dmi differ
diff --git a/tgstation.dme b/tgstation.dme
index badbd9edab5f9..820c3cc79c191 100644
--- a/tgstation.dme
+++ b/tgstation.dme
@@ -355,6 +355,7 @@
#include "code\__DEFINES\dcs\signals\signals_restaurant.dm"
#include "code\__DEFINES\dcs\signals\signals_scangate.dm"
#include "code\__DEFINES\dcs\signals\signals_screentips.dm"
+#include "code\__DEFINES\dcs\signals\signals_shuttle.dm"
#include "code\__DEFINES\dcs\signals\signals_spatial_grid.dm"
#include "code\__DEFINES\dcs\signals\signals_species.dm"
#include "code\__DEFINES\dcs\signals\signals_spell.dm"