From f3df7ccb1e6185ef1181c388ad0af410118a9772 Mon Sep 17 00:00:00 2001 From: Changelogs Date: Mon, 30 Sep 2024 01:04:44 +0000 Subject: [PATCH 01/12] Automatic changelog compile [ci skip] --- html/changelogs/AutoChangeLog-pr-3136.yml | 4 ---- html/changelogs/AutoChangeLog-pr-3350.yml | 4 ---- html/changelogs/AutoChangeLog-pr-3364.yml | 4 ---- html/changelogs/AutoChangeLog-pr-3422.yml | 4 ---- html/changelogs/AutoChangeLog-pr-3428.yml | 4 ---- html/changelogs/AutoChangeLog-pr-3454.yml | 4 ---- html/changelogs/archive/2024-09.yml | 11 +++++++++++ 7 files changed, 11 insertions(+), 24 deletions(-) delete mode 100644 html/changelogs/AutoChangeLog-pr-3136.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-3350.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-3364.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-3422.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-3428.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-3454.yml diff --git a/html/changelogs/AutoChangeLog-pr-3136.yml b/html/changelogs/AutoChangeLog-pr-3136.yml deleted file mode 100644 index 1c06ebef6c3e..000000000000 --- a/html/changelogs/AutoChangeLog-pr-3136.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: Thera-Pissed -changes: - - {rscadd: 'New wasteplanet ruin, the abandoned Miskilamo shipbreaking yard!'} -delete-after: true diff --git a/html/changelogs/AutoChangeLog-pr-3350.yml b/html/changelogs/AutoChangeLog-pr-3350.yml deleted file mode 100644 index 8869478b429b..000000000000 --- a/html/changelogs/AutoChangeLog-pr-3350.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: FalloutFalcon -changes: - - {bugfix: condiment packs are no longer invisible and missing names} -delete-after: true diff --git a/html/changelogs/AutoChangeLog-pr-3364.yml b/html/changelogs/AutoChangeLog-pr-3364.yml deleted file mode 100644 index 7c6b1f04c8a7..000000000000 --- a/html/changelogs/AutoChangeLog-pr-3364.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: MassiveMen -changes: - - {rscadd: Added the fire axe to the black market uplink} -delete-after: true diff --git a/html/changelogs/AutoChangeLog-pr-3422.yml b/html/changelogs/AutoChangeLog-pr-3422.yml deleted file mode 100644 index 6bb9c3e4e60d..000000000000 --- a/html/changelogs/AutoChangeLog-pr-3422.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: Bjarl -changes: - - {rscdel: The Elephant Graveyard ruin has been taken out back} -delete-after: true diff --git a/html/changelogs/AutoChangeLog-pr-3428.yml b/html/changelogs/AutoChangeLog-pr-3428.yml deleted file mode 100644 index ecad99d43c1d..000000000000 --- a/html/changelogs/AutoChangeLog-pr-3428.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: FalloutFalcon -changes: - - {bugfix: sawnoff weapons made from init now function correctly} -delete-after: true diff --git a/html/changelogs/AutoChangeLog-pr-3454.yml b/html/changelogs/AutoChangeLog-pr-3454.yml deleted file mode 100644 index 9e1b731951c9..000000000000 --- a/html/changelogs/AutoChangeLog-pr-3454.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: Bjarl -changes: - - {bugfix: m90 posters are real again} -delete-after: true diff --git a/html/changelogs/archive/2024-09.yml b/html/changelogs/archive/2024-09.yml index 0beabb6bcc8b..52b3cbfbf679 100644 --- a/html/changelogs/archive/2024-09.yml +++ b/html/changelogs/archive/2024-09.yml @@ -207,3 +207,14 @@ 2024-09-29: fighterslam: - balance: Modernizes and slightly buffs the Ranger. +2024-09-30: + Bjarl: + - rscdel: The Elephant Graveyard ruin has been taken out back + - bugfix: m90 posters are real again + FalloutFalcon: + - bugfix: sawnoff weapons made from init now function correctly + - bugfix: condiment packs are no longer invisible and missing names + MassiveMen: + - rscadd: Added the fire axe to the black market uplink + Thera-Pissed: + - rscadd: New wasteplanet ruin, the abandoned Miskilamo shipbreaking yard! From c8515f48a5f21290e2e416bf7595f760d20d7ac5 Mon Sep 17 00:00:00 2001 From: Erika Fox <94164348+Bjarl@users.noreply.github.com> Date: Mon, 30 Sep 2024 12:07:33 -0400 Subject: [PATCH 02/12] Anti-Radiation Foam (#3366) ## About The Pull Request Buyable foam that destroys radiation emitters, and decontaminates objects very efficiently. ## Why It's Good For The Game Makes wasteplanet survival less of a hassle when prepared ## Changelog :cl: Erika Fox add: Anti-Radiation Foam is now available at the outpost /:cl: --- code/game/objects/effects/decals/cleanable.dm | 5 +-- .../effects/effect_system/effects_foam.dm | 29 +++++++++++++-- code/game/objects/items/tanks/watertank.dm | 33 +++++++++++++++++ code/modules/cargo/packs/tools.dm | 11 ++++++ .../chemistry/reagents/other_reagents.dm | 35 +++++++++++++++++++ code/modules/reagents/reagent_dispenser.dm | 6 ++++ 6 files changed, 115 insertions(+), 4 deletions(-) diff --git a/code/game/objects/effects/decals/cleanable.dm b/code/game/objects/effects/decals/cleanable.dm index 4161403fefd9..3ec6f58aa7b1 100644 --- a/code/game/objects/effects/decals/cleanable.dm +++ b/code/game/objects/effects/decals/cleanable.dm @@ -89,8 +89,9 @@ /obj/effect/decal/cleanable/wash(clean_types) ..() if(!(flags_1 & INITIALIZED_1)) - return FALSE - qdel(src) + return + if(clean_types in list(CLEAN_WASH, CLEAN_SCRUB)) + qdel(src) return TRUE /obj/effect/decal/cleanable/proc/can_bloodcrawl_in() diff --git a/code/game/objects/effects/effect_system/effects_foam.dm b/code/game/objects/effects/effect_system/effects_foam.dm index 51020d8f60dc..5fedeb47e455 100644 --- a/code/game/objects/effects/effect_system/effects_foam.dm +++ b/code/game/objects/effects/effect_system/effects_foam.dm @@ -48,13 +48,11 @@ /obj/effect/particle_effect/foam/firefighting/kill_foam() STOP_PROCESSING(SSfastprocess, src) - if(absorbed_plasma) var/obj/effect/decal/cleanable/plasma/P = (locate(/obj/effect/decal/cleanable/plasma) in get_turf(src)) if(!P) P = new(loc) P.reagents.add_reagent(/datum/reagent/stable_plasma, absorbed_plasma) - flick("[icon_state]-disolve", src) QDEL_IN(src, 5) @@ -67,6 +65,33 @@ /obj/effect/particle_effect/foam/firefighting/temperature_expose(datum/gas_mixture/air, exposed_temperature, exposed_volume) return + +/obj/effect/particle_effect/foam/antirad + name = "antiradiation foam" + lifetime = 80 + amount = 0 //no spread + slippery_foam = FALSE + color = "#A6FAFF55" + + +/obj/effect/particle_effect/foam/antirad/process() + ..() + + var/turf/open/T = get_turf(src) + var/obj/effect/radiation/rads = (locate(/obj/effect/radiation) in T) + if(rads && istype(T)) + rads.rad_power = rads.rad_power * rand(0.8, 0.95) + if (rads.rad_power <= RAD_BACKGROUND_RADIATION) + new /obj/effect/decal/cleanable/greenglow/filled(loc) + qdel(rads) + for(var/obj/things in get_turf(src)) + things.wash(CLEAN_TYPE_RADIATION) + +/obj/effect/particle_effect/foam/antirad/kill_foam() + STOP_PROCESSING(SSfastprocess, src) + flick("[icon_state]-disolve", src) + QDEL_IN(src, 5) + /obj/effect/particle_effect/foam/metal name = "aluminium foam" metal = ALUMINIUM_FOAM diff --git a/code/game/objects/items/tanks/watertank.dm b/code/game/objects/items/tanks/watertank.dm index 50f709dcd65f..23fe0852c353 100644 --- a/code/game/objects/items/tanks/watertank.dm +++ b/code/game/objects/items/tanks/watertank.dm @@ -175,6 +175,39 @@ amount_per_transfer_from_this = (amount_per_transfer_from_this == 10 ? 5 : 10) to_chat(user, "You [amount_per_transfer_from_this == 10 ? "remove" : "fix"] the nozzle. You'll now use [amount_per_transfer_from_this] units per spray.") +//radiation cleanup pack + +/obj/item/watertank/anti_rad + name = "radiation foam pack" + desc = "A pressurized backpack tank with sprayer nozzle, intended to clean up radioactive hazards." + item_state = "waterbackpackatmos" + icon_state = "waterbackpackatmos" + volume = 200 + slowdown = 0.3 + +/obj/item/watertank/anti_rad/Initialize() + . = ..() + reagents.add_reagent(/datum/reagent/anti_radiation_foam, 200) + + +/obj/item/reagent_containers/spray/mister/anti_rad + name = "spray nozzle" + desc = "A heavy duty nozzle attached to a radiation foam tank." + icon_state = "atmos_nozzle" + item_state = "nozzleatmos" + amount_per_transfer_from_this = 5 + possible_transfer_amounts = list() + current_range = 6 + spray_range = 6 + + +/obj/item/watertank/anti_rad/make_noz() + return new /obj/item/reagent_containers/spray/mister/anti_rad(src) + +/obj/item/reagent_containers/spray/mister/anti_rad/attack_self(mob/user) + amount_per_transfer_from_this = (amount_per_transfer_from_this == 10 ? 5 : 10) + to_chat(user, "You [amount_per_transfer_from_this == 10 ? "tigten" : "loosen"] the nozzle. You'll now use [amount_per_transfer_from_this] units per spray.") + //ATMOS FIRE FIGHTING BACKPACK #define EXTINGUISHER 0 diff --git a/code/modules/cargo/packs/tools.dm b/code/modules/cargo/packs/tools.dm index 25ed4aaab554..e4081a448e0b 100644 --- a/code/modules/cargo/packs/tools.dm +++ b/code/modules/cargo/packs/tools.dm @@ -146,3 +146,14 @@ contains = list(/obj/structure/reagent_dispensers/foamtank) crate_name = "foam tank crate" crate_type = /obj/structure/closet/crate/large + +/datum/supply_pack/tools/radfoamtank + name = "Radiation Foam Tank Crate" + desc = "Contains a tank of anti-radiation foam. Pressurized sprayer included!" + cost = 1500 + contains = list( + /obj/item/watertank/anti_rad, + /obj/structure/reagent_dispensers/foamtank/antirad + ) + crate_name = "foam tank crate" + crate_type = /obj/structure/closet/crate/large diff --git a/code/modules/reagents/chemistry/reagents/other_reagents.dm b/code/modules/reagents/chemistry/reagents/other_reagents.dm index 11306b441f1e..e0d4e2a86606 100644 --- a/code/modules/reagents/chemistry/reagents/other_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/other_reagents.dm @@ -2526,3 +2526,38 @@ description = "Bacteria native to the Saint-Roumain Militia home planet." color = "#5a4f42" taste_description = "sour" + +//anti rad foam +/datum/reagent/anti_radiation_foam + name = "Anti-Radiation Foam" + description = "A tried and tested foam, used for decontaminating nuclear disasters." + reagent_state = LIQUID + color = "#A6FAFF55" + taste_description = "bitter, foamy awfulness." + +/datum/reagent/anti_radiation_foam/expose_turf(turf/open/T, reac_volume) + if (!istype(T)) + return + + if(reac_volume >= 1) + var/obj/effect/particle_effect/foam/antirad/F = (locate(/obj/effect/particle_effect/foam/antirad) in T) + if(!F) + F = new(T) + else if(istype(F)) + F.lifetime = initial(F.lifetime) //the foam is what does the cleaning here + +/datum/reagent/anti_radiation_foam/expose_obj(obj/O, reac_volume) + O.wash(CLEAN_RAD) + +/datum/reagent/anti_radiation_foam/expose_mob(mob/living/M, method=TOUCH, reac_volume) + if(method in list(TOUCH, VAPOR)) + M.radiation = M.radiation - rand(max(M.radiation * 0.95, M.radiation)) //get the hose + M.ExtinguishMob() + ..() + + +/datum/reagent/anti_radiation_foam/on_mob_life(mob/living/carbon/M) + M.adjustToxLoss(0.5, 200) + M.adjust_disgust(4) + ..() + . = 1 diff --git a/code/modules/reagents/reagent_dispenser.dm b/code/modules/reagents/reagent_dispenser.dm index fafd67305c9c..54d2fc182398 100644 --- a/code/modules/reagents/reagent_dispenser.dm +++ b/code/modules/reagents/reagent_dispenser.dm @@ -58,6 +58,12 @@ reagent_id = /datum/reagent/firefighting_foam tank_volume = 500 +/obj/structure/reagent_dispensers/foamtank/antirad + name = "anti-radiation foam tank" + desc = "A tank full of decontamination foam" + reagent_id = /datum/reagent/anti_radiation_foam + tank_volume = 1000 + /obj/structure/reagent_dispensers/fueltank name = "fuel tank" desc = "A tank full of industrial welding fuel. Do not consume." From fc810c5bd284afbb0b79485d042e337742a7d476 Mon Sep 17 00:00:00 2001 From: Changelogs Date: Mon, 30 Sep 2024 11:29:02 -0500 Subject: [PATCH 03/12] Automatic changelog generation for PR #3366 [ci skip] --- html/changelogs/AutoChangeLog-pr-3366.yml | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 html/changelogs/AutoChangeLog-pr-3366.yml diff --git a/html/changelogs/AutoChangeLog-pr-3366.yml b/html/changelogs/AutoChangeLog-pr-3366.yml new file mode 100644 index 000000000000..f1b353bf3387 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-3366.yml @@ -0,0 +1,4 @@ +author: Erika Fox +changes: + - {rscadd: Anti-Radiation Foam is now available at the outpost} +delete-after: true From 92df9a186805a6d0cb48053b0a95cedd60d4b0b8 Mon Sep 17 00:00:00 2001 From: Sadhorizon <108196626+Sadhorizon@users.noreply.github.com> Date: Mon, 30 Sep 2024 18:11:36 +0200 Subject: [PATCH 04/12] Secbelts can now hold knives. (#3455) ## About The Pull Request Title. ## Why It's Good For The Game A knife is a pretty common piece of sec gear in the frontier actually. ## Changelog :cl: tweak: You can now put knives in secbelts and the subtypes of secbelts. fix: You can now fit all knives in mining webbings. /:cl: --- code/game/objects/items/storage/belt.dm | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/code/game/objects/items/storage/belt.dm b/code/game/objects/items/storage/belt.dm index c2679adf8ae9..52a6fdf8738e 100644 --- a/code/game/objects/items/storage/belt.dm +++ b/code/game/objects/items/storage/belt.dm @@ -275,6 +275,7 @@ STR.set_holdable(list( /obj/item/melee/baton, /obj/item/melee/classic_baton, + /obj/item/melee/knife, /obj/item/grenade, /obj/item/reagent_containers/spray/pepper, /obj/item/restraints/handcuffs, @@ -367,7 +368,7 @@ /obj/item/storage/fancy/cigarettes, /obj/item/reagent_containers/food/drinks/bottle, /obj/item/stack/medical, - /obj/item/melee/knife/kitchen, + /obj/item/melee/knife, /obj/item/reagent_containers/hypospray, /obj/item/gps, /obj/item/storage/bag/ore, From f616ac19e71faa430564f217f571619eaabe08a5 Mon Sep 17 00:00:00 2001 From: Changelogs Date: Mon, 30 Sep 2024 11:42:47 -0500 Subject: [PATCH 05/12] Automatic changelog generation for PR #3455 [ci skip] --- html/changelogs/AutoChangeLog-pr-3455.yml | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 html/changelogs/AutoChangeLog-pr-3455.yml diff --git a/html/changelogs/AutoChangeLog-pr-3455.yml b/html/changelogs/AutoChangeLog-pr-3455.yml new file mode 100644 index 000000000000..0351ddf280b1 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-3455.yml @@ -0,0 +1,5 @@ +author: Sadhorizon +changes: + - {tweak: You can now put knives in secbelts and the subtypes of secbelts.} + - {bugfix: You can now fit all knives in mining webbings.} +delete-after: true From c1706207847e8ff94ac2aaafe225f083aeb5c814 Mon Sep 17 00:00:00 2001 From: Erika Fox <94164348+Bjarl@users.noreply.github.com> Date: Mon, 30 Sep 2024 12:15:01 -0400 Subject: [PATCH 06/12] Cabinet Refactor (#3378) ## About The Pull Request Mildly refactors fireaxe cabinets to allow them to be subtyped with different items. Also adds an is_wielded proc to most weapons that can be wielded to prevent potential weirdness with this down the line. ## Why It's Good For The Game Cabinets are soulful ## Changelog :cl: Erika Fox code: Fireaxe cabinets have been repathed, and now function as a more general cabinet object. please report any inconsistencies with behavior /:cl: --------- Signed-off-by: FalloutFalcon <86381784+FalloutFalcon@users.noreply.github.com> Co-authored-by: FalloutFalcon Co-authored-by: FalloutFalcon <86381784+FalloutFalcon@users.noreply.github.com> --- .../JungleRuins/jungle_paradise.dmm | 2 +- .../SpaceRuins/singularity_lab.dmm | 6 +- .../independent/independent_lagoon.dmm | 2 +- _maps/shuttles/inteq/inteq_talos.dmm | 2 +- .../shuttles/nanotrasen/nanotrasen_heron.dmm | 2 +- .../shuttles/nanotrasen/nanotrasen_osprey.dmm | 2 +- .../nanotrasen/nanotrasen_skipper.dmm | 2 +- _maps/shuttles/pirate/pirate_libertatia.dmm | 2 +- .../syndicate/syndicate_gorlex_komodo.dmm | 2 +- .../syndicate/syndicate_twinkleshine.dmm | 2 +- code/__DEFINES/dcs/signals/signals.dm | 1 + code/__DEFINES/traits.dm | 1 + code/__HELPERS/unsorted.dm | 2 +- code/datums/components/twohanded.dm | 5 +- code/game/machinery/doors/airlock.dm | 2 +- code/game/objects/items/defib.dm | 13 -- code/game/objects/items/melee/chainsaw.dm | 20 +- code/game/objects/items/melee/dualsaber.dm | 22 +- .../game/objects/items/melee/energyhalberd.dm | 23 +- code/game/objects/items/melee/fireaxe.dm | 22 +- code/game/objects/items/melee/spear.dm | 17 +- code/game/objects/items/melee/sword.dm | 22 +- code/game/objects/items/storage/secure.dm | 2 +- code/game/objects/structures/cabinet.dm | 214 ++++++++++++++++++ code/game/objects/structures/cabinet_types.dm | 10 + code/game/objects/structures/fireaxe.dm | 179 --------------- .../mining/equipment/kinetic_crusher.dm | 53 ++--- code/modules/projectiles/gun.dm | 6 +- shiptest.dme | 3 +- 29 files changed, 296 insertions(+), 345 deletions(-) create mode 100644 code/game/objects/structures/cabinet.dm create mode 100644 code/game/objects/structures/cabinet_types.dm delete mode 100644 code/game/objects/structures/fireaxe.dm diff --git a/_maps/RandomRuins/JungleRuins/jungle_paradise.dmm b/_maps/RandomRuins/JungleRuins/jungle_paradise.dmm index 0e19890e63c7..47455933ec16 100644 --- a/_maps/RandomRuins/JungleRuins/jungle_paradise.dmm +++ b/_maps/RandomRuins/JungleRuins/jungle_paradise.dmm @@ -5181,7 +5181,7 @@ pixel_x = 7; pixel_y = 6 }, -/obj/structure/fireaxecabinet{ +/obj/structure/cabinet/fireaxe{ pixel_y = 28 }, /turf/open/floor/mineral/titanium, diff --git a/_maps/RandomRuins/SpaceRuins/singularity_lab.dmm b/_maps/RandomRuins/SpaceRuins/singularity_lab.dmm index 99ccda138d00..7dd57c637f35 100644 --- a/_maps/RandomRuins/SpaceRuins/singularity_lab.dmm +++ b/_maps/RandomRuins/SpaceRuins/singularity_lab.dmm @@ -8625,13 +8625,13 @@ /turf/open/floor/plasteel/grimy, /area/ruin/space/has_grav/singularitylab/lab) "HU" = ( -/obj/structure/fireaxecabinet{ - pixel_y = 32 - }, /obj/structure/sign/warning/incident{ pixel_x = -32 }, /obj/effect/decal/cleanable/cobweb, +/obj/structure/cabinet/fireaxe{ + pixel_y = 28 + }, /turf/open/floor/plasteel/dark, /area/ruin/space/has_grav/singularitylab/engineering) "HW" = ( diff --git a/_maps/shuttles/independent/independent_lagoon.dmm b/_maps/shuttles/independent/independent_lagoon.dmm index 3615828fa9d2..1c8c2307a7e8 100644 --- a/_maps/shuttles/independent/independent_lagoon.dmm +++ b/_maps/shuttles/independent/independent_lagoon.dmm @@ -2347,7 +2347,7 @@ }, /obj/item/clothing/suit/hooded/wintercoat/engineering/atmos, /obj/item/clothing/gloves/color/black, -/obj/structure/fireaxecabinet{ +/obj/structure/cabinet/fireaxe{ dir = 8; pixel_x = 28 }, diff --git a/_maps/shuttles/inteq/inteq_talos.dmm b/_maps/shuttles/inteq/inteq_talos.dmm index 195852c9fd5c..6b05aa78caaa 100644 --- a/_maps/shuttles/inteq/inteq_talos.dmm +++ b/_maps/shuttles/inteq/inteq_talos.dmm @@ -2090,7 +2090,7 @@ dir = 1 }, /obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden/layer4, -/obj/structure/fireaxecabinet{ +/obj/structure/cabinet/fireaxe{ dir = 1; pixel_y = -32 }, diff --git a/_maps/shuttles/nanotrasen/nanotrasen_heron.dmm b/_maps/shuttles/nanotrasen/nanotrasen_heron.dmm index 3dda0b36dd63..7d8db3ebb68b 100644 --- a/_maps/shuttles/nanotrasen/nanotrasen_heron.dmm +++ b/_maps/shuttles/nanotrasen/nanotrasen_heron.dmm @@ -13621,7 +13621,7 @@ /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer4{ dir = 6 }, -/obj/structure/fireaxecabinet{ +/obj/structure/cabinet/fireaxe{ pixel_y = 27 }, /obj/structure/closet/secure_closet/engineering_electrical, diff --git a/_maps/shuttles/nanotrasen/nanotrasen_osprey.dmm b/_maps/shuttles/nanotrasen/nanotrasen_osprey.dmm index fb1d6e3c1f12..e99a4cd360a8 100644 --- a/_maps/shuttles/nanotrasen/nanotrasen_osprey.dmm +++ b/_maps/shuttles/nanotrasen/nanotrasen_osprey.dmm @@ -5632,7 +5632,7 @@ /obj/machinery/atmospherics/pipe/manifold/supply/hidden/layer2{ dir = 1 }, -/obj/structure/fireaxecabinet{ +/obj/structure/cabinet/fireaxe{ pixel_y = 32 }, /obj/structure/cable{ diff --git a/_maps/shuttles/nanotrasen/nanotrasen_skipper.dmm b/_maps/shuttles/nanotrasen/nanotrasen_skipper.dmm index d875a024d07f..a8f5bc22c7f4 100644 --- a/_maps/shuttles/nanotrasen/nanotrasen_skipper.dmm +++ b/_maps/shuttles/nanotrasen/nanotrasen_skipper.dmm @@ -472,7 +472,7 @@ /turf/open/floor/plasteel/white, /area/ship/medical) "dZ" = ( -/obj/structure/fireaxecabinet{ +/obj/structure/cabinet/fireaxe{ pixel_y = -29 }, /obj/structure/catwalk/over/plated_catwalk/dark, diff --git a/_maps/shuttles/pirate/pirate_libertatia.dmm b/_maps/shuttles/pirate/pirate_libertatia.dmm index b1bf098571c0..46d00806edd7 100644 --- a/_maps/shuttles/pirate/pirate_libertatia.dmm +++ b/_maps/shuttles/pirate/pirate_libertatia.dmm @@ -299,7 +299,7 @@ /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer4{ dir = 4 }, -/obj/structure/fireaxecabinet{ +/obj/structure/cabinet/fireaxe{ pixel_y = 32 }, /turf/open/floor/pod/light, diff --git a/_maps/shuttles/syndicate/syndicate_gorlex_komodo.dmm b/_maps/shuttles/syndicate/syndicate_gorlex_komodo.dmm index 2b4cfd484e98..c466f5351f9c 100644 --- a/_maps/shuttles/syndicate/syndicate_gorlex_komodo.dmm +++ b/_maps/shuttles/syndicate/syndicate_gorlex_komodo.dmm @@ -2048,7 +2048,7 @@ dir = 4 }, /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer4, -/obj/structure/fireaxecabinet{ +/obj/structure/cabinet/fireaxe{ dir = 8; pixel_x = 27 }, diff --git a/_maps/shuttles/syndicate/syndicate_twinkleshine.dmm b/_maps/shuttles/syndicate/syndicate_twinkleshine.dmm index 6c690286b2ac..29f4bc28922b 100644 --- a/_maps/shuttles/syndicate/syndicate_twinkleshine.dmm +++ b/_maps/shuttles/syndicate/syndicate_twinkleshine.dmm @@ -3500,7 +3500,7 @@ pixel_y = 4 }, /obj/item/storage/toolbox/electrical, -/obj/structure/fireaxecabinet{ +/obj/structure/cabinet/fireaxe{ pixel_y = -32; dir = 1 }, diff --git a/code/__DEFINES/dcs/signals/signals.dm b/code/__DEFINES/dcs/signals/signals.dm index f3295b737904..fd56e61f003b 100644 --- a/code/__DEFINES/dcs/signals/signals.dm +++ b/code/__DEFINES/dcs/signals/signals.dm @@ -671,6 +671,7 @@ #define COMPONENT_TWOHANDED_BLOCK_WIELD 1 #define COMSIG_TWOHANDED_UNWIELD "twohanded_unwield" //from base of datum/component/two_handed/proc/unwield(mob/living/carbon/user): (/mob/user) + // /datum/action signals #define COMSIG_ACTION_TRIGGER "action_trigger" //from base of datum/action/proc/Trigger(): (datum/action) #define COMPONENT_ACTION_BLOCK_TRIGGER 1 diff --git a/code/__DEFINES/traits.dm b/code/__DEFINES/traits.dm index c97fa62ffc5d..4925981b2a91 100644 --- a/code/__DEFINES/traits.dm +++ b/code/__DEFINES/traits.dm @@ -301,6 +301,7 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai #define TRAIT_NO_STORAGE_INSERT "no_storage_insert" //cannot be inserted in a storage. #define TRAIT_T_RAY_VISIBLE "t-ray-visible" // Visible on t-ray scanners if the atom/var/level == 1 #define TRAIT_NO_TELEPORT "no-teleport" //you just can't +#define TRAIT_WIELDED "wielded" //The item is currently being wielded //quirk traits #define TRAIT_ALCOHOL_TOLERANCE "alcohol_tolerance" diff --git a/code/__HELPERS/unsorted.dm b/code/__HELPERS/unsorted.dm index d831296dbb62..7bd6f72771cc 100644 --- a/code/__HELPERS/unsorted.dm +++ b/code/__HELPERS/unsorted.dm @@ -680,7 +680,7 @@ GLOBAL_LIST_INIT(WALLITEMS, typecacheof(list( /obj/machinery/newscaster, /obj/machinery/firealarm, /obj/structure/noticeboard, /obj/machinery/button, /obj/machinery/computer/security/telescreen, /obj/machinery/embedded_controller/radio/simple_vent_controller, /obj/item/storage/secure/safe, /obj/machinery/door_timer, /obj/machinery/flasher, /obj/machinery/keycard_auth, - /obj/structure/mirror, /obj/structure/fireaxecabinet, /obj/machinery/computer/security/telescreen/entertainment, + /obj/structure/mirror, /obj/structure/cabinet, /obj/machinery/computer/security/telescreen/entertainment, /obj/structure/sign/picture_frame, /obj/machinery/bounty_board ))) diff --git a/code/datums/components/twohanded.dm b/code/datums/components/twohanded.dm index 51c9268d13ab..5ba0a368c637 100644 --- a/code/datums/components/twohanded.dm +++ b/code/datums/components/twohanded.dm @@ -4,6 +4,7 @@ * When applied to an item it will make it two handed * */ + /datum/component/two_handed dupe_mode = COMPONENT_DUPE_UNIQUE_PASSARGS // Only one of the component can exist on an item var/wielded = FALSE /// Are we holding the two handed item properly @@ -145,6 +146,7 @@ if(SEND_SIGNAL(parent, COMSIG_TWOHANDED_WIELD, user) & COMPONENT_TWOHANDED_BLOCK_WIELD) return // blocked wield from item wielded = TRUE + ADD_TRAIT(parent, TRAIT_WIELDED, REF(src)) RegisterSignal(user, COMSIG_MOB_SWAP_HANDS, PROC_REF(on_swap_hands)) // update item stats and name @@ -188,6 +190,7 @@ // wield update status wielded = FALSE + REMOVE_TRAIT(parent, TRAIT_WIELDED, REF(src)) UnregisterSignal(user, COMSIG_MOB_SWAP_HANDS) SEND_SIGNAL(parent, COMSIG_TWOHANDED_UNWIELD, user) @@ -303,7 +306,7 @@ sharpened_increase = min(amount, (max_amount - wielded_val)) return COMPONENT_BLOCK_SHARPEN_APPLIED -/** +/* * The offhand dummy item for two handed items * */ diff --git a/code/game/machinery/doors/airlock.dm b/code/game/machinery/doors/airlock.dm index e70edb721788..4c27a08e64a7 100644 --- a/code/game/machinery/doors/airlock.dm +++ b/code/game/machinery/doors/airlock.dm @@ -1238,7 +1238,7 @@ if(!operating) if(istype(I, /obj/item/melee/axe/fire)) //being fireaxe'd var/obj/item/melee/axe/fire/axe = I - if(axe && !axe.wielded) + if(axe && !HAS_TRAIT(axe, TRAIT_WIELDED)) to_chat(user, "You need to be wielding \the [axe] to do that!") return INVOKE_ASYNC(src, (density ? PROC_REF(open) : PROC_REF(close)), 2) diff --git a/code/game/objects/items/defib.dm b/code/game/objects/items/defib.dm index 32a62880d69c..517bc9922786 100644 --- a/code/game/objects/items/defib.dm +++ b/code/game/objects/items/defib.dm @@ -309,17 +309,6 @@ AddElement(/datum/element/update_icon_updates_onmob) AddComponent(/datum/component/two_handed, force_unwielded=8, force_wielded=12) -/// triggered on wield of two handed item -/obj/item/shockpaddles/proc/on_wield(obj/item/source, mob/user) - SIGNAL_HANDLER - - wielded = TRUE - -/// triggered on unwield of two handed item -/obj/item/shockpaddles/proc/on_unwield(obj/item/source, mob/user) - SIGNAL_HANDLER - - wielded = FALSE /obj/item/shockpaddles/Destroy() defib = null @@ -369,8 +358,6 @@ /obj/item/shockpaddles/Initialize() . = ..() ADD_TRAIT(src, TRAIT_NO_STORAGE_INSERT, GENERIC_ITEM_TRAIT) //stops shockpaddles from being inserted in BoH - RegisterSignal(src, COMSIG_TWOHANDED_WIELD, PROC_REF(on_wield)) - RegisterSignal(src, COMSIG_TWOHANDED_UNWIELD, PROC_REF(on_unwield)) if(!req_defib) return //If it doesn't need a defib, just say it exists if (!loc || !istype(loc, /obj/item/defibrillator)) //To avoid weird issues from admin spawns diff --git a/code/game/objects/items/melee/chainsaw.dm b/code/game/objects/items/melee/chainsaw.dm index 494ec65cdb5a..d179237f8559 100644 --- a/code/game/objects/items/melee/chainsaw.dm +++ b/code/game/objects/items/melee/chainsaw.dm @@ -22,30 +22,12 @@ tool_behaviour = TOOL_SAW toolspeed = 0.5 var/on = FALSE - var/wielded = FALSE // track wielded status on item - -/obj/item/chainsaw/Initialize() - . = ..() - RegisterSignal(src, COMSIG_TWOHANDED_WIELD, PROC_REF(on_wield)) - RegisterSignal(src, COMSIG_TWOHANDED_UNWIELD, PROC_REF(on_unwield)) /obj/item/chainsaw/ComponentInitialize() . = ..() AddComponent(/datum/component/butchering, 30, 100, 0, 'sound/weapons/chainsawhit.ogg', TRUE) AddComponent(/datum/component/two_handed, require_twohands=TRUE) -/// triggered on wield of two handed item -/obj/item/chainsaw/proc/on_wield(obj/item/source, mob/user) - SIGNAL_HANDLER - - wielded = TRUE - -/// triggered on unwield of two handed item -/obj/item/chainsaw/proc/on_unwield(obj/item/source, mob/user) - SIGNAL_HANDLER - - wielded = FALSE - /obj/item/chainsaw/attack_self(mob/user) on = !on to_chat(user, "As you pull the starting cord dangling from [src], [on ? "it begins to whirr." : "the chain stops moving."]") @@ -67,7 +49,7 @@ A.UpdateButtonIcon() /obj/item/chainsaw/get_dismemberment_chance() - if(wielded) + if(HAS_TRAIT(src, TRAIT_WIELDED)) . = ..() /obj/item/chainsaw/doomslayer diff --git a/code/game/objects/items/melee/dualsaber.dm b/code/game/objects/items/melee/dualsaber.dm index 965979db215a..28242c1006a1 100644 --- a/code/game/objects/items/melee/dualsaber.dm +++ b/code/game/objects/items/melee/dualsaber.dm @@ -28,7 +28,6 @@ var/two_hand_force = 34 var/hacked = FALSE var/list/possible_colors = list("red", "blue", "green", "purple", "yellow") - var/wielded = FALSE // track wielded status on item /obj/item/dualsaber/ComponentInitialize() . = ..() @@ -43,7 +42,6 @@ if(user.dna.check_mutation(HULK)) to_chat(user, "You lack the grace to wield this!") return COMPONENT_TWOHANDED_BLOCK_WIELD - wielded = TRUE sharpness = IS_SHARP w_class = w_class_on hitsound = 'sound/weapons/blade1.ogg' @@ -56,16 +54,14 @@ /obj/item/dualsaber/proc/on_unwield(obj/item/source, mob/living/carbon/user) SIGNAL_HANDLER - wielded = FALSE sharpness = initial(sharpness) w_class = initial(w_class) hitsound = "swing_hit" STOP_PROCESSING(SSobj, src) set_light_on(FALSE) - /obj/item/dualsaber/update_icon_state() - icon_state = wielded ? "dualsaber[saber_color]" : "dualsaber" + icon_state = HAS_TRAIT(src, TRAIT_WIELDED) ? "dualsaber[saber_color]" : "dualsaber" return ..() /obj/item/dualsaber/Initialize() @@ -94,14 +90,14 @@ if(user.has_dna()) if(user.dna.check_mutation(HULK)) to_chat(user, "You grip the blade too hard and accidentally drop it!") - if(wielded) + if(HAS_TRAIT(src, TRAIT_WIELDED)) user.dropItemToGround(src, force=TRUE) return ..() - if(wielded && HAS_TRAIT(user, TRAIT_CLUMSY) && prob(40)) + if(HAS_TRAIT(src, TRAIT_WIELDED) && HAS_TRAIT(user, TRAIT_CLUMSY) && prob(40)) impale(user) return - if(wielded && prob(50)) + if(HAS_TRAIT(src, TRAIT_WIELDED) && prob(50)) INVOKE_ASYNC(src, PROC_REF(jedi_spin), user) /obj/item/dualsaber/proc/jedi_spin(mob/living/user) @@ -109,18 +105,18 @@ /obj/item/dualsaber/proc/impale(mob/living/user) to_chat(user, "You twirl around a bit before losing your balance and impaling yourself on [src].") - if(wielded) + if(HAS_TRAIT(src, TRAIT_WIELDED)) user.take_bodypart_damage(20,25,check_armor = TRUE) else user.adjustStaminaLoss(25) /obj/item/dualsaber/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK) - if(wielded) + if(HAS_TRAIT(src, TRAIT_WIELDED)) return ..() return 0 /obj/item/dualsaber/process() - if(wielded) + if(HAS_TRAIT(src, TRAIT_WIELDED)) if(hacked) set_light_color(pick(COLOR_SOFT_RED, LIGHT_COLOR_GREEN, LIGHT_COLOR_LIGHT_CYAN, LIGHT_COLOR_LAVENDER)) open_flame() @@ -128,12 +124,12 @@ STOP_PROCESSING(SSobj, src) /obj/item/dualsaber/IsReflect() - if(wielded) + if(HAS_TRAIT(src, TRAIT_WIELDED)) return 1 /obj/item/dualsaber/ignition_effect(atom/A, mob/user) // same as /obj/item/melee/transforming/energy, mostly - if(!wielded) + if(!HAS_TRAIT(src, TRAIT_WIELDED)) return "" var/in_mouth = "" if(iscarbon(user)) diff --git a/code/game/objects/items/melee/energyhalberd.dm b/code/game/objects/items/melee/energyhalberd.dm index 62c6f5de6020..8ae5cdd96f36 100644 --- a/code/game/objects/items/melee/energyhalberd.dm +++ b/code/game/objects/items/melee/energyhalberd.dm @@ -31,13 +31,12 @@ var/two_hand_force = 34 var/hacked = FALSE var/list/possible_colors = list("red", "blue", "green", "purple", "yellow") - var/wielded = FALSE // track wielded status on item /obj/item/energyhalberd/ComponentInitialize() . = ..() AddComponent(/datum/component/two_handed, force_unwielded=force, force_wielded=two_hand_force, wieldsound='sound/weapons/saberon.ogg', unwieldsound='sound/weapons/saberoff.ogg') -/// Triggered on wield of two handed item + /// Specific hulk checks due to reflection chance for balance issues and switches hitsounds. /obj/item/energyhalberd/proc/on_halberdwield(obj/item/source, mob/living/carbon/user) SIGNAL_HANDLER @@ -46,7 +45,6 @@ if(user.dna.check_mutation(HULK)) to_chat(user, "You lack the grace to wield this!") return COMPONENT_TWOHANDED_BLOCK_WIELD - wielded = TRUE sharpness = IS_SHARP w_class = w_class_on hitsound = 'sound/weapons/blade1.ogg' @@ -54,12 +52,9 @@ set_light_on(TRUE) -/// Triggered on unwield of two handed item /// switch hitsounds /obj/item/energyhalberd/proc/on_halberdunwield(obj/item/source, mob/living/carbon/user) SIGNAL_HANDLER - - wielded = FALSE sharpness = initial(sharpness) w_class = initial(w_class) hitsound = "swing_hit" @@ -68,7 +63,7 @@ /obj/item/energyhalberd/update_icon_state() - if(wielded) + if(HAS_TRAIT(src, TRAIT_WIELDED)) icon_state = "halberd[halberd_color]" return ..() else @@ -101,28 +96,28 @@ if(user.has_dna()) if(user.dna.check_mutation(HULK)) to_chat(user, "You grip the blade too hard and accidentally drop it!") - if(wielded) + if(HAS_TRAIT(src, TRAIT_WIELDED)) user.dropItemToGround(src, force=TRUE) return ..() - if(wielded && HAS_TRAIT(user, TRAIT_CLUMSY) && prob(40)) + if(HAS_TRAIT(src, TRAIT_WIELDED) && HAS_TRAIT(user, TRAIT_CLUMSY) && prob(40)) impale(user) return /obj/item/energyhalberd/proc/impale(mob/living/user) to_chat(user, "You swing around a bit before losing your balance and impaling yourself on [src].") - if(wielded) + if(HAS_TRAIT(src, TRAIT_WIELDED)) user.take_bodypart_damage(20,25,check_armor = TRUE) else user.adjustStaminaLoss(25) /obj/item/energyhalberd/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK) - if(wielded) + if(HAS_TRAIT(src, TRAIT_WIELDED)) return ..() return 0 /obj/item/energyhalberd/process() - if(wielded) + if(HAS_TRAIT(src, TRAIT_WIELDED)) if(hacked) set_light_color(pick(COLOR_SOFT_RED, LIGHT_COLOR_GREEN, LIGHT_COLOR_LIGHT_CYAN, LIGHT_COLOR_LAVENDER)) open_flame() @@ -130,12 +125,12 @@ STOP_PROCESSING(SSobj, src) /obj/item/energyhalberd/IsReflect() - if(wielded) + if(HAS_TRAIT(src, TRAIT_WIELDED)) return 1 /obj/item/energyhalberd/ignition_effect(atom/A, mob/user) // same as /obj/item/melee/transforming/energy, mostly - if(!wielded) + if(!HAS_TRAIT(src, TRAIT_WIELDED)) return "" var/in_mouth = "" if(iscarbon(user)) diff --git a/code/game/objects/items/melee/fireaxe.dm b/code/game/objects/items/melee/fireaxe.dm index bfbed0fe361b..b3e04ac1bc3c 100644 --- a/code/game/objects/items/melee/fireaxe.dm +++ b/code/game/objects/items/melee/fireaxe.dm @@ -13,31 +13,13 @@ armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 100, "acid" = 30) resistance_flags = FIRE_PROOF species_exception = list(/datum/species/kepori) - var/wielded = FALSE // track wielded status on item - -/obj/item/melee/axe/Initialize() - . = ..() - RegisterSignal(src, COMSIG_TWOHANDED_WIELD, PROC_REF(on_wield)) - RegisterSignal(src, COMSIG_TWOHANDED_UNWIELD, PROC_REF(on_unwield)) /obj/item/melee/axe/ComponentInitialize() . = ..() AddComponent(/datum/component/butchering, 100, 80, 0 , hitsound) //axes are not known for being precision butchering tools AddComponent(/datum/component/two_handed, force_unwielded=5, force_wielded=24, icon_wielded="[base_icon_state]1") -/// triggered on wield of two handed item -/obj/item/melee/axe/proc/on_wield(obj/item/source, mob/user) - SIGNAL_HANDLER - - wielded = TRUE - -/// triggered on unwield of two handed item -/obj/item/melee/axe/proc/on_unwield(obj/item/source, mob/user) - SIGNAL_HANDLER - - wielded = FALSE - -/obj/item/melee/axe/update_icon_state() +/obj/item/fireaxe/update_icon_state() icon_state = "[base_icon_state]0" return ..() @@ -45,7 +27,7 @@ . = ..() if(!proximity) return - if(wielded) //destroys windows and grilles in one hit + if(HAS_TRAIT(src, TRAIT_WIELDED)) //destroys windows and grilles in one hit if(istype(A, /obj/structure/window) || istype(A, /obj/structure/grille)) var/obj/structure/W = A W.obj_destruction("axe") diff --git a/code/game/objects/items/melee/spear.dm b/code/game/objects/items/melee/spear.dm index 42717117fd8e..218638882bfb 100644 --- a/code/game/objects/items/melee/spear.dm +++ b/code/game/objects/items/melee/spear.dm @@ -66,30 +66,15 @@ icon_prefix = "spearbomb" var/obj/item/grenade/explosive = null var/war_cry = "AAAAARGH!!!" - var/wielded = FALSE // track wielded status on item /obj/item/melee/spear/explosive/Initialize(mapload) . = ..() - RegisterSignal(src, COMSIG_TWOHANDED_WIELD, PROC_REF(on_wield)) - RegisterSignal(src, COMSIG_TWOHANDED_UNWIELD, PROC_REF(on_unwield)) set_explosive(new /obj/item/grenade/iedcasing/spawned()) //For admin-spawned explosive lances /obj/item/melee/spear/explosive/ComponentInitialize() . = ..() AddComponent(/datum/component/two_handed, force_unwielded=10, force_wielded=18, icon_wielded="[icon_prefix]1") -/// triggered on wield of two handed item -/obj/item/melee/spear/explosive/proc/on_wield(obj/item/source, mob/user) - SIGNAL_HANDLER - - wielded = TRUE - -/// triggered on unwield of two handed item -/obj/item/melee/spear/explosive/proc/on_unwield(obj/item/source, mob/user) - SIGNAL_HANDLER - - wielded = FALSE - /obj/item/melee/spear/explosive/proc/set_explosive(obj/item/grenade/G) if(explosive) QDEL_NULL(explosive) @@ -130,7 +115,7 @@ . = ..() if(!proximity) return - if(wielded) + if(HAS_TRAIT(src, TRAIT_WIELDED)) user.say("[war_cry]", forced="spear warcry") explosive.forceMove(AM) explosive.prime() diff --git a/code/game/objects/items/melee/sword.dm b/code/game/objects/items/melee/sword.dm index 21bde05c0dd3..ff384770a318 100644 --- a/code/game/objects/items/melee/sword.dm +++ b/code/game/objects/items/melee/sword.dm @@ -332,38 +332,20 @@ attack_verb = list("cut", "sliced", "diced") slot_flags = ITEM_SLOT_BACK hitsound = 'sound/weapons/bladeslice.ogg' - var/wielded = FALSE // track wielded status on item - -/obj/item/melee/sword/vibro/Initialize() - . = ..() - RegisterSignal(src, COMSIG_TWOHANDED_WIELD, PROC_REF(on_wield)) - RegisterSignal(src, COMSIG_TWOHANDED_UNWIELD, PROC_REF(on_unwield)) /obj/item/melee/sword/vibro/ComponentInitialize() . = ..() AddComponent(/datum/component/butchering, 20, 105) AddComponent(/datum/component/two_handed, force_multiplier=2, icon_wielded="[base_icon_state]1") -/// triggered on wield of two handed item -/obj/item/melee/sword/vibro/proc/on_wield(obj/item/source, mob/user) - SIGNAL_HANDLER - - wielded = TRUE - -/// triggered on unwield of two handed item -/obj/item/melee/sword/vibro/proc/on_unwield(obj/item/source, mob/user) - SIGNAL_HANDLER - - wielded = FALSE - /obj/item/melee/sword/vibro/update_icon_state() icon_state = "[base_icon_state]0" return ..() /obj/item/melee/sword/vibro/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK) - if(wielded) + if(HAS_TRAIT(src, TRAIT_WIELDED)) final_block_chance *= 2 - if(wielded || attack_type != PROJECTILE_ATTACK) + if(HAS_TRAIT(src, TRAIT_WIELDED) || attack_type != PROJECTILE_ATTACK) if(prob(final_block_chance)) if(attack_type == PROJECTILE_ATTACK) owner.visible_message("[owner] deflects [attack_text] with [src]!") diff --git a/code/game/objects/items/storage/secure.dm b/code/game/objects/items/storage/secure.dm index 422ff52b15b0..f918a3b883fb 100644 --- a/code/game/objects/items/storage/secure.dm +++ b/code/game/objects/items/storage/secure.dm @@ -173,7 +173,7 @@ . = ..() var/datum/component/storage/STR = GetComponent(/datum/component/storage) STR.set_holdable(null, list(/obj/item/storage/secure/briefcase)) - STR.max_w_class = 8 //?? + STR.max_w_class = 8 /obj/item/storage/secure/safe/PopulateContents() new /obj/item/paper(src) diff --git a/code/game/objects/structures/cabinet.dm b/code/game/objects/structures/cabinet.dm new file mode 100644 index 000000000000..bc89cf1d0bbe --- /dev/null +++ b/code/game/objects/structures/cabinet.dm @@ -0,0 +1,214 @@ +/obj/structure/cabinet + name = "\improper cabinet" + desc = "There is a small label that reads \"For Emergency use only\". Yeah right." + icon = 'icons/obj/wallmounts.dmi' + icon_state = "fireaxe" + anchored = TRUE + density = FALSE + armor = list("melee" = 50, "bullet" = 20, "laser" = 0, "energy" = 100, "bomb" = 10, "bio" = 100, "rad" = 100, "fire" = 90, "acid" = 50) + max_integrity = 150 + integrity_failure = 0.33 + req_one_access_txt = "0" + var/locked = TRUE + var/open = FALSE + var/start_empty = FALSE + var/obj/item/stored + var/allowed_type + var/stored_sprite = "axe" + +/obj/structure/cabinet/Initialize() + . = ..() + if(allowed_type && !start_empty) + stored = new allowed_type(src) + update_appearance() + +/obj/structure/cabinet/Destroy() + if(istype(stored)) + qdel(stored) + stored = null + return ..() + +/obj/structure/cabinet/examine(mob/user) + . = ..() + if(!open) + . += span_notice("Alt-click to [locked ? "unlock" : "lock"] [src]") + if(stored) + . += span_notice("[stored] is sitting inside, ripe for the taking.") + +/obj/structure/cabinet/attackby(obj/item/I, mob/user, params) + if(iscyborg(user) || I.tool_behaviour == TOOL_MULTITOOL) + hack_lock(user) + else if(I.tool_behaviour == TOOL_WELDER && user.a_intent == INTENT_HELP && !broken) + if(obj_integrity < max_integrity) + if(!I.tool_start_check(user, amount=2)) + return + to_chat(user, span_notice("You begin repairing [src]")) + if(I.use_tool(src, user, 40, volume=50, amount=2)) + obj_integrity = max_integrity + update_appearance() + to_chat(user, span_notice("You repair [src]")) + else + to_chat(user, span_warning("[src] is already in good condition!")) + return + else if(istype(I, /obj/item/stack/sheet/glass) && broken) + var/obj/item/stack/sheet/glass/G = I + if(G.get_amount() < 2) + to_chat(user, span_warning("You need two [G.singular_name] to fix [src]!")) + return + to_chat(user, span_notice("You start fixing [src]...")) + if(do_after(user, 20, target = src) && G.use(2)) + broken = 0 + obj_integrity = max_integrity + update_appearance() + else if(open || broken) + if(istype(I, allowed_type) && !stored) + var/obj/item/storee = I + SIGNAL_HANDLER + if(storee && HAS_TRAIT(storee, TRAIT_WIELDED)) + to_chat(user, span_warning("Unwield the [storee.name] first.")) + return + if(!user.transferItemToLoc(I, src)) + return + stored = storee + to_chat(user, span_notice("You place the [storee.name] back in the [name].")) + update_appearance() + return + else if(!broken) + toggle_open() + else + return ..() + +/obj/structure/cabinet/play_attack_sound(damage_amount, damage_type = BRUTE, damage_flag = 0) + switch(damage_type) + if(BRUTE) + if(broken) + playsound(loc, 'sound/effects/hit_on_shattered_glass.ogg', 90, TRUE) + else + playsound(loc, 'sound/effects/glasshit.ogg', 90, TRUE) + if(BURN) + playsound(src.loc, 'sound/items/welder.ogg', 100, TRUE) + +/obj/structure/cabinet/take_damage(damage_amount, damage_type = BRUTE, damage_flag = 0, sound_effect = 1, attack_dir) + if(open) + return + . = ..() + if(.) + update_appearance() + +/obj/structure/cabinet/obj_break(damage_flag) + if(!broken && !(flags_1 & NODECONSTRUCT_1)) + update_appearance() + broken = TRUE + playsound(src, 'sound/effects/glassbr3.ogg', 100, TRUE) + new /obj/item/shard(loc) + new /obj/item/shard(loc) + +/obj/structure/cabinet/deconstruct(disassembled = TRUE) + if(!(flags_1 & NODECONSTRUCT_1)) + if(stored && loc) + stored.forceMove(loc) + stored = null + new /obj/item/stack/sheet/metal(loc, 2) + qdel(src) + +/obj/structure/cabinet/attack_hand(mob/user) + . = ..() + if(.) + return + if(open || broken) + if(stored) + to_chat(user, span_notice("You take [stored] from [name].")) + user.put_in_hands(stored) + stored = null + src.add_fingerprint(user) + update_appearance() + return + if(locked) + to_chat(user, span_warning("[name] won't budge!")) + return + else + open = !open + update_appearance() + return + +/obj/structure/cabinet/attack_paw(mob/living/user) + return attack_hand(user) + +/obj/structure/cabinet/attack_ai(mob/user) + toggle_lock(user) + return + +/obj/structure/cabinet/attack_tk(mob/user) + if(locked) + to_chat(user, span_warning("[name] won't budge!")) + return + else + open = !open + update_appearance() + return + +/obj/structure/cabinet/update_overlays() + . = ..() + if(stored) + . += "[stored_sprite]" + if(open) + . += "glass_raised" + return + var/hp_percent = obj_integrity/max_integrity * 100 + if(broken) + . += "glass4" + else + switch(hp_percent) + if(-INFINITY to 40) + . += "glass3" + if(40 to 60) + . += "glass2" + if(60 to 80) + . += "glass1" + if(80 to INFINITY) + . += "glass" + + . += locked ? "locked" : "unlocked" + +/obj/structure/cabinet/proc/toggle_lock(mob/user) + if(!broken) + if(allowed(user)) + if(iscarbon(user)) + add_fingerprint(user) + locked = !locked + user.visible_message( + span_notice("[user] [locked ? "locks" : "unlocks"][src]."), + span_notice("You [locked ? "lock" : "unlock"] [src].")) + update_appearance() + else + to_chat(user, span_warning("Access denied!")) + else if(broken) + to_chat(user, span_warning("\The [src] is broken!")) + +/obj/structure/cabinet/AltClick(mob/user) + ..() + if(!user.canUseTopic(src, BE_CLOSE) || !isturf(loc) || open) + return + else + toggle_lock(user) + +/obj/structure/cabinet/proc/hack_lock(mob/user) + to_chat(user, span_notice("Resetting circuitry...")) + playsound(src, 'sound/machines/locktoggle.ogg', 50, TRUE) + if(do_after(user, 20, target = src)) + to_chat(user, span_notice("You [locked ? "disable" : "re-enable"] the locking modules.")) + locked = !locked + update_appearance() + +/obj/structure/cabinet/verb/toggle_open() + set name = "Open/Close" + set category = "Object" + set src in oview(1) + + if(locked) + visible_message(span_warning("[name] won't budge!")) + return + else + open = !open + update_appearance() + return diff --git a/code/game/objects/structures/cabinet_types.dm b/code/game/objects/structures/cabinet_types.dm new file mode 100644 index 000000000000..347e1954ded4 --- /dev/null +++ b/code/game/objects/structures/cabinet_types.dm @@ -0,0 +1,10 @@ +/obj/structure/cabinet/fireaxe + name = "\improper fire axe cabinet" + desc = "There is a small label that reads \"For Emergency use only\" along with details for safe use of the axe. As if." + icon = 'icons/obj/wallmounts.dmi' + icon_state = "fireaxe" + anchored = TRUE + density = FALSE + stored_sprite = "axe" + allowed_type = /obj/item/melee/axe/fire + req_one_access_txt = "24" diff --git a/code/game/objects/structures/fireaxe.dm b/code/game/objects/structures/fireaxe.dm deleted file mode 100644 index a164248a2bdd..000000000000 --- a/code/game/objects/structures/fireaxe.dm +++ /dev/null @@ -1,179 +0,0 @@ -/obj/structure/fireaxecabinet - name = "fire axe cabinet" - desc = "There is a small label that reads \"For Emergency use only\" along with details for safe use of the axe. As if." - icon = 'icons/obj/wallmounts.dmi' - icon_state = "fireaxe" - anchored = TRUE - density = FALSE - armor = list("melee" = 50, "bullet" = 20, "laser" = 0, "energy" = 100, "bomb" = 10, "bio" = 100, "rad" = 100, "fire" = 90, "acid" = 50) - max_integrity = 150 - integrity_failure = 0.33 - var/locked = TRUE - var/open = FALSE - var/obj/item/melee/axe/fire/fireaxe - -/obj/structure/fireaxecabinet/Initialize() - . = ..() - fireaxe = new - update_appearance() - -/obj/structure/fireaxecabinet/Destroy() - if(fireaxe) - QDEL_NULL(fireaxe) - return ..() - -/obj/structure/fireaxecabinet/attackby(obj/item/I, mob/user, params) - if(iscyborg(user) || I.tool_behaviour == TOOL_MULTITOOL) - toggle_lock(user) - else if(I.tool_behaviour == TOOL_WELDER && user.a_intent == INTENT_HELP && !broken) - if(obj_integrity < max_integrity) - if(!I.tool_start_check(user, amount=2)) - return - - to_chat(user, "You begin repairing [src].") - if(I.use_tool(src, user, 40, volume=50, amount=2)) - obj_integrity = max_integrity - update_appearance() - to_chat(user, "You repair [src].") - else - to_chat(user, "[src] is already in good condition!") - return - else if(istype(I, /obj/item/stack/sheet/glass) && broken) - var/obj/item/stack/sheet/glass/G = I - if(G.get_amount() < 2) - to_chat(user, "You need two glass sheets to fix [src]!") - return - to_chat(user, "You start fixing [src]...") - if(do_after(user, 20, target = src) && G.use(2)) - broken = 0 - obj_integrity = max_integrity - update_appearance() - else if(open || broken) - if(istype(I, /obj/item/melee/axe/fire) && !fireaxe) - var/obj/item/melee/axe/fire/F = I - if(F && F.wielded) - to_chat(user, "Unwield the [F.name] first.") - return - if(!user.transferItemToLoc(F, src)) - return - fireaxe = F - to_chat(user, "You place the [F.name] back in the [name].") - update_appearance() - return - else if(!broken) - toggle_open() - else - return ..() - -/obj/structure/fireaxecabinet/play_attack_sound(damage_amount, damage_type = BRUTE, damage_flag = 0) - switch(damage_type) - if(BRUTE) - if(broken) - playsound(loc, 'sound/effects/hit_on_shattered_glass.ogg', 90, TRUE) - else - playsound(loc, 'sound/effects/glasshit.ogg', 90, TRUE) - if(BURN) - playsound(src.loc, 'sound/items/welder.ogg', 100, TRUE) - -/obj/structure/fireaxecabinet/take_damage(damage_amount, damage_type = BRUTE, damage_flag = 0, sound_effect = 1, attack_dir) - if(open) - return - . = ..() - if(.) - update_appearance() - -/obj/structure/fireaxecabinet/obj_break(damage_flag) - if(!broken && !(flags_1 & NODECONSTRUCT_1)) - update_appearance() - broken = TRUE - playsound(src, 'sound/effects/glassbr3.ogg', 100, TRUE) - new /obj/item/shard(loc) - new /obj/item/shard(loc) - -/obj/structure/fireaxecabinet/deconstruct(disassembled = TRUE) - if(!(flags_1 & NODECONSTRUCT_1)) - if(fireaxe && loc) - fireaxe.forceMove(loc) - fireaxe = null - new /obj/item/stack/sheet/metal(loc, 2) - qdel(src) - -/obj/structure/fireaxecabinet/attack_hand(mob/user) - . = ..() - if(.) - return - if(open || broken) - if(fireaxe) - user.put_in_hands(fireaxe) - fireaxe = null - to_chat(user, "You take the fire axe from the [name].") - src.add_fingerprint(user) - update_appearance() - return - if(locked) - to_chat(user, "The [name] won't budge!") - return - else - open = !open - update_appearance() - return - -/obj/structure/fireaxecabinet/attack_paw(mob/living/user) - return attack_hand(user) - -/obj/structure/fireaxecabinet/attack_ai(mob/user) - toggle_lock(user) - return - -/obj/structure/fireaxecabinet/attack_tk(mob/user) - if(locked) - to_chat(user, "The [name] won't budge!") - return - else - open = !open - update_appearance() - return - -/obj/structure/fireaxecabinet/update_overlays() - . = ..() - if(fireaxe) - . += "axe" - if(open) - . += "glass_raised" - return - var/hp_percent = obj_integrity/max_integrity * 100 - if(broken) - . += "glass4" - else - switch(hp_percent) - if(-INFINITY to 40) - . += "glass3" - if(40 to 60) - . += "glass2" - if(60 to 80) - . += "glass1" - if(80 to INFINITY) - . += "glass" - - . += locked ? "locked" : "unlocked" - -/obj/structure/fireaxecabinet/proc/toggle_lock(mob/user) - to_chat(user, "Resetting circuitry...") - playsound(src, 'sound/machines/locktoggle.ogg', 50, TRUE) - if(do_after(user, 20, target = src)) - to_chat(user, "You [locked ? "disable" : "re-enable"] the locking modules.") - locked = !locked - update_appearance() - -/obj/structure/fireaxecabinet/verb/toggle_open() - set name = "Open/Close" - set category = "Object" - set src in oview(1) - - if(locked) - to_chat(usr, "The [name] won't budge!") - return - else - open = !open - update_appearance() - return diff --git a/code/modules/mining/equipment/kinetic_crusher.dm b/code/modules/mining/equipment/kinetic_crusher.dm index 3e0bed238bec..05e81421ac4f 100644 --- a/code/modules/mining/equipment/kinetic_crusher.dm +++ b/code/modules/mining/equipment/kinetic_crusher.dm @@ -8,7 +8,7 @@ name = "proto-magnetic crusher" desc = "A multipurpose disembarkation and self-defense tool designed by EXOCOM using an incomplete Nanotrasen prototype. \ Found in the grime-stained hands of wannabee explorers across the frontier, it cuts rock and hews flora using magnetic osscilation and a heavy cleaving edge." - force = 0 //You can't hit stuff unless wielded + force = 0 //You can't hit stuff unless it's wielded w_class = WEIGHT_CLASS_BULKY slot_flags = ITEM_SLOT_BACK throwforce = 5 @@ -28,33 +28,19 @@ var/charge_time = 15 var/detonation_damage = 20 var/backstab_bonus = 10 - var/wielded = FALSE // track wielded status on item - -/obj/item/kinetic_crusher/Initialize() - . = ..() - RegisterSignal(src, COMSIG_TWOHANDED_WIELD, PROC_REF(on_wield)) - RegisterSignal(src, COMSIG_TWOHANDED_UNWIELD, PROC_REF(on_unwield)) /obj/item/kinetic_crusher/ComponentInitialize() . = ..() AddComponent(/datum/component/butchering, 60, 110) //technically it's huge and bulky, but this provides an incentive to use it AddComponent(/datum/component/two_handed, force_unwielded=0, force_wielded=15) -/// triggered on wield of two handed item -/obj/item/kinetic_crusher/proc/on_wield(obj/item/source, mob/user) - wielded = TRUE - -/// triggered on unwield of two handed item -/obj/item/kinetic_crusher/proc/on_unwield(obj/item/source, mob/user) - wielded = FALSE - /obj/item/kinetic_crusher/examine(mob/living/user) . = ..() . += "Induce magnetism in an enemy by striking them with a magnetospheric wave, then hit them in melee to force a waveform collapse for [force + detonation_damage] damage." . += "Does [force + detonation_damage + backstab_bonus] damage if the target is backstabbed, instead of [force + detonation_damage]." /obj/item/kinetic_crusher/attack(mob/living/target, mob/living/carbon/user) - if(!wielded) + if(!HAS_TRAIT(src, TRAIT_WIELDED)) to_chat(user, "[src] is too heavy to use with one hand! You fumble and drop everything.") user.drop_all_held_items() return @@ -66,7 +52,7 @@ /obj/item/kinetic_crusher/afterattack(atom/target, mob/living/user, proximity_flag, clickparams) . = ..() - if(!wielded) + if(!HAS_TRAIT(src, TRAIT_WIELDED)) return if(!proximity_flag && charged)//Mark a target, or mine a tile. var/turf/proj_turf = user.loc @@ -118,7 +104,7 @@ /obj/item/kinetic_crusher/update_icon_state() - item_state = "crusher[wielded]" // this is not icon_state and not supported by 2hcomponent + item_state = "crusher[HAS_TRAIT(src, TRAIT_WIELDED)]" // this is not icon_state and not supported by 2hcomponent return ..() /obj/item/kinetic_crusher/update_overlays() @@ -182,7 +168,7 @@ user.changeNext_move(CLICK_CD_MELEE * 2.0)//...slow swinga. /obj/item/kinetic_crusher/old/update_icon_state() - item_state = "crusherold[wielded]" // still not supported by 2hcomponent + item_state = "crusherold[HAS_TRAIT(src, TRAIT_WIELDED)]" // still not supported by 2hcomponent return ..() //100% original syndicate oc, plz do not steal. More effective against human targets then the typical crusher, with a bit of block chance. @@ -195,7 +181,7 @@ name = "magnetic cleaver" desc = "Designed by Syndicate Research and Development for their resource-gathering operations on hostile worlds. Syndicate Legal Ops would like to stress that you've never seen anything like this before. Ever." armour_penetration = 69//nice cut - force = 0 //You can't hit stuff unless wielded + force = 0 //You can't hit stuff unless HAS_TRAIT(src, TRAIT_WIELDED) w_class = WEIGHT_CLASS_BULKY slot_flags = ITEM_SLOT_BACK throwforce = 5 @@ -216,35 +202,40 @@ charge_time = 15 detonation_damage = 35 backstab_bonus = 15 - wielded = FALSE // track wielded status on item actions_types = list() + +/obj/item/kinetic_crusher/syndie_crusher/Initialize() + . = ..() + RegisterSignal(src, COMSIG_TWOHANDED_WIELD, PROC_REF(on_wield)) + RegisterSignal(src, COMSIG_TWOHANDED_UNWIELD, PROC_REF(on_unwield)) + /obj/item/kinetic_crusher/syndie_crusher/ComponentInitialize() . = ..() AddComponent(/datum/component/butchering, 60, 150) AddComponent(/datum/component/two_handed, force_unwielded=0, force_wielded=10) /// triggered on wield of two handed item -/obj/item/kinetic_crusher/syndie_crusher/on_wield(obj/item/source, mob/user) - . = ..() - wielded = TRUE +/obj/item/kinetic_crusher/syndie_crusher/proc/on_wield(obj/item/source, mob/user) + SIGNAL_HANDLER + icon_state = "crushersyndie1" playsound(user, 'sound/weapons/saberon.ogg', 35, TRUE) - set_light_on(wielded) + set_light_on(HAS_TRAIT(src, TRAIT_WIELDED)) /// triggered on unwield of two handed item -/obj/item/kinetic_crusher/syndie_crusher/on_unwield(obj/item/source, mob/user) - . = ..() - wielded = FALSE +/obj/item/kinetic_crusher/syndie_crusher/proc/on_unwield(obj/item/source, mob/user) + SIGNAL_HANDLER + icon_state = "crushersyndie" playsound(user, 'sound/weapons/saberoff.ogg', 35, TRUE) - set_light_on(wielded) + set_light_on(HAS_TRAIT(src, TRAIT_WIELDED)) /obj/item/kinetic_crusher/syndie_crusher/update_icon_state() - item_state = "crushersyndie[wielded]" // this is not icon_state and not supported by 2hcomponent + item_state = "crushersyndie[HAS_TRAIT(src, TRAIT_WIELDED)]" // this is not icon_state and not supported by 2hcomponent return ..() /obj/item/kinetic_crusher/syndie_crusher/update_overlays() . = ..() - if(wielded) + if(HAS_TRAIT(src, TRAIT_WIELDED)) . += "[icon_state]_lit" diff --git a/code/modules/projectiles/gun.dm b/code/modules/projectiles/gun.dm index 94cc4f6f1e38..7fe0a5b07c3a 100644 --- a/code/modules/projectiles/gun.dm +++ b/code/modules/projectiles/gun.dm @@ -364,9 +364,6 @@ wielded_fully = TRUE return TRUE -/obj/item/gun/proc/is_wielded() - return wielded - /// triggered on unwield of two handed item /obj/item/gun/proc/on_unwield(obj/item/source, mob/user) wielded = FALSE @@ -374,6 +371,9 @@ zoom(user, forced_zoom = FALSE) user.remove_movespeed_modifier(/datum/movespeed_modifier/gun) +/obj/item/gun/proc/is_wielded() + return wielded + /obj/item/gun/Destroy() if(chambered) //Not all guns are chambered (EMP'ed energy guns etc) QDEL_NULL(chambered) diff --git a/shiptest.dme b/shiptest.dme index 0bff452a9161..53b8c061b5fa 100644 --- a/shiptest.dme +++ b/shiptest.dme @@ -1387,6 +1387,8 @@ #include "code\game\objects\structures\artstuff.dm" #include "code\game\objects\structures\barsigns.dm" #include "code\game\objects\structures\bedsheet_bin.dm" +#include "code\game\objects\structures\cabinet.dm" +#include "code\game\objects\structures\cabinet_types.dm" #include "code\game\objects\structures\catwalk.dm" #include "code\game\objects\structures\crateshelf.dm" #include "code\game\objects\structures\curtains.dm" @@ -1400,7 +1402,6 @@ #include "code\game\objects\structures\extinguisher.dm" #include "code\game\objects\structures\false_walls.dm" #include "code\game\objects\structures\fence.dm" -#include "code\game\objects\structures\fireaxe.dm" #include "code\game\objects\structures\fireplace.dm" #include "code\game\objects\structures\flora.dm" #include "code\game\objects\structures\fluff.dm" From d71acf3f8e02f93b260c2f47b0435215378d5ac2 Mon Sep 17 00:00:00 2001 From: Changelogs Date: Mon, 30 Sep 2024 11:55:56 -0500 Subject: [PATCH 07/12] Automatic changelog generation for PR #3378 [ci skip] --- html/changelogs/AutoChangeLog-pr-3378.yml | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 html/changelogs/AutoChangeLog-pr-3378.yml diff --git a/html/changelogs/AutoChangeLog-pr-3378.yml b/html/changelogs/AutoChangeLog-pr-3378.yml new file mode 100644 index 000000000000..7ed5af71b205 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-3378.yml @@ -0,0 +1,5 @@ +author: Erika Fox +changes: + - {code_imp: 'Fireaxe cabinets have been repathed, and now function as a more general + cabinet object. please report any inconsistencies with behavior'} +delete-after: true From 53714787d3eebbd41f903bcc37c5817cee334dc6 Mon Sep 17 00:00:00 2001 From: Theos Date: Mon, 30 Sep 2024 12:19:01 -0400 Subject: [PATCH 08/12] Should fix hallucinations being permanent (#3445) ## About The Pull Request Fixes #3435 Caps hallucination natural decay at 0 so it can't reach negative numbers off dumb stuff and never actually stop doing stuff ## Changelog :cl: fix: hallucinations can no longer be permanent unless treated /:cl: Signed-off-by: Theos --- code/modules/flufftext/Hallucination.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/modules/flufftext/Hallucination.dm b/code/modules/flufftext/Hallucination.dm index 69c15b1e3494..8f8e532577c0 100644 --- a/code/modules/flufftext/Hallucination.dm +++ b/code/modules/flufftext/Hallucination.dm @@ -29,7 +29,7 @@ GLOBAL_LIST_INIT(hallucination_list, list( if(!hallucination) return - hallucination-- + hallucination = max(hallucination - 1, 0) if(world.time < next_hallucination) return From 7530971650a1339771c5cafb0da773bc1e427ecb Mon Sep 17 00:00:00 2001 From: Changelogs Date: Mon, 30 Sep 2024 12:09:16 -0500 Subject: [PATCH 09/12] Automatic changelog generation for PR #3445 [ci skip] --- html/changelogs/AutoChangeLog-pr-3445.yml | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 html/changelogs/AutoChangeLog-pr-3445.yml diff --git a/html/changelogs/AutoChangeLog-pr-3445.yml b/html/changelogs/AutoChangeLog-pr-3445.yml new file mode 100644 index 000000000000..3199030bea7f --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-3445.yml @@ -0,0 +1,4 @@ +author: SomeguyManperson +changes: + - {bugfix: hallucinations can no longer be permanent unless treated} +delete-after: true From 96b8045defa3771caa4bb6efe3cc5bec75b295a9 Mon Sep 17 00:00:00 2001 From: Changelogs Date: Tue, 1 Oct 2024 01:08:21 +0000 Subject: [PATCH 10/12] Automatic changelog compile [ci skip] --- html/changelogs/AutoChangeLog-pr-3366.yml | 4 ---- html/changelogs/AutoChangeLog-pr-3378.yml | 5 ----- html/changelogs/AutoChangeLog-pr-3445.yml | 4 ---- html/changelogs/AutoChangeLog-pr-3455.yml | 5 ----- html/changelogs/archive/2024-10.yml | 10 ++++++++++ 5 files changed, 10 insertions(+), 18 deletions(-) delete mode 100644 html/changelogs/AutoChangeLog-pr-3366.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-3378.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-3445.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-3455.yml create mode 100644 html/changelogs/archive/2024-10.yml diff --git a/html/changelogs/AutoChangeLog-pr-3366.yml b/html/changelogs/AutoChangeLog-pr-3366.yml deleted file mode 100644 index f1b353bf3387..000000000000 --- a/html/changelogs/AutoChangeLog-pr-3366.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: Erika Fox -changes: - - {rscadd: Anti-Radiation Foam is now available at the outpost} -delete-after: true diff --git a/html/changelogs/AutoChangeLog-pr-3378.yml b/html/changelogs/AutoChangeLog-pr-3378.yml deleted file mode 100644 index 7ed5af71b205..000000000000 --- a/html/changelogs/AutoChangeLog-pr-3378.yml +++ /dev/null @@ -1,5 +0,0 @@ -author: Erika Fox -changes: - - {code_imp: 'Fireaxe cabinets have been repathed, and now function as a more general - cabinet object. please report any inconsistencies with behavior'} -delete-after: true diff --git a/html/changelogs/AutoChangeLog-pr-3445.yml b/html/changelogs/AutoChangeLog-pr-3445.yml deleted file mode 100644 index 3199030bea7f..000000000000 --- a/html/changelogs/AutoChangeLog-pr-3445.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: SomeguyManperson -changes: - - {bugfix: hallucinations can no longer be permanent unless treated} -delete-after: true diff --git a/html/changelogs/AutoChangeLog-pr-3455.yml b/html/changelogs/AutoChangeLog-pr-3455.yml deleted file mode 100644 index 0351ddf280b1..000000000000 --- a/html/changelogs/AutoChangeLog-pr-3455.yml +++ /dev/null @@ -1,5 +0,0 @@ -author: Sadhorizon -changes: - - {tweak: You can now put knives in secbelts and the subtypes of secbelts.} - - {bugfix: You can now fit all knives in mining webbings.} -delete-after: true diff --git a/html/changelogs/archive/2024-10.yml b/html/changelogs/archive/2024-10.yml new file mode 100644 index 000000000000..546d4d7ab402 --- /dev/null +++ b/html/changelogs/archive/2024-10.yml @@ -0,0 +1,10 @@ +2024-10-01: + Erika Fox: + - rscadd: Anti-Radiation Foam is now available at the outpost + - code_imp: Fireaxe cabinets have been repathed, and now function as a more general + cabinet object. please report any inconsistencies with behavior + Sadhorizon: + - tweak: You can now put knives in secbelts and the subtypes of secbelts. + - bugfix: You can now fit all knives in mining webbings. + SomeguyManperson: + - bugfix: hallucinations can no longer be permanent unless treated From 180c9b216ab142495afd77f7e9b17390602fd33b Mon Sep 17 00:00:00 2001 From: tmtmtl30 <53132901+tmtmtl30@users.noreply.github.com> Date: Tue, 1 Oct 2024 01:10:36 -0700 Subject: [PATCH 11/12] a bedtime update for beddy-bye boys (Bunk beds!) (#3345) ## About The Pull Request Adds bunk beds, in the form of two objects, a "bottom bunk" structure and a "top bunk" structure, each with appropriate layering and sprite-shifting, including for bedsheets. Sprites are courtesy of @thgvr . They can be crafted with metal or placed by mappers as a single object using a spawner effect. Additionally, beds, double beds, and bunk beds have had their alternate-direction behavior fixed. These beds have a flipped set of sprites on the NORTH and EAST directions, but neither bedsheets nor buckled players correctly respected the alternate sprites. This has been fixed. oh also i fixed a random rendering error with tank storage units that imaginos notified me of. they weren't showing the final 5-tank overlay state correctly. they do now ![image](https://github.com/user-attachments/assets/bbebeb5e-27db-4703-a7db-c639b8ec1502) ## Why It's Good For The Game 1. bunkbeds give mappers another tool to make ships and ruins feel appropriately-decorated 2. mappers being effectively locked to a single bed rotation is dumb currently, there's one bug: when crafting a bunk bed, you need to make the bottom one first. if you make the top one first, you won't be able to place the bottom bunk there without just deconstructing the top bunk. i know exactly what causes this, it's mostly just annoying and i've got a few ideas for (slightly hacky) fixes. but i'm also lazy ## Changelog :cl: tmtmtl30, Thgvr add: Added bunkbeds, which can now be crafted with metal or placed by mappers. fix: Beds facing alternate directions now correctly support people buckling to them and bedsheets being placed on top of them. /:cl: --- code/datums/elements/bed_tucking.dm | 23 +++- code/game/objects/items/plushes.dm | 2 +- .../stacks/sheets/recipes/recipes_metal.dm | 8 +- code/game/objects/items/stacks/stack.dm | 2 +- .../structures/beds_chairs/alien_nest.dm | 1 + .../objects/structures/beds_chairs/bed.dm | 130 +++++++++++++++++- code/game/objects/structures/bedsheet_bin.dm | 2 +- .../game/objects/structures/tank_dispenser.dm | 6 +- .../abductor/equipment/abduction_gear.dm | 1 + .../nukeop/equipment/nuclearbomb.dm | 2 +- code/modules/mob/living/carbon/carbon.dm | 2 +- icons/effects/effects.dmi | Bin 901728 -> 903017 bytes icons/obj/objects.dmi | Bin 102051 -> 103649 bytes 13 files changed, 163 insertions(+), 16 deletions(-) diff --git a/code/datums/elements/bed_tucking.dm b/code/datums/elements/bed_tucking.dm index c094e5a5b108..e505e6efdb5a 100644 --- a/code/datums/elements/bed_tucking.dm +++ b/code/datums/elements/bed_tucking.dm @@ -8,8 +8,13 @@ var/y_offset = 0 /// our rotation degree - how much the item turns when in bed (+degrees turns it more parallel) var/rotation_degree = 0 + /// Whether the item changes its dir to match the desired lying direction of the bed that it's tucked into. + var/change_dir = FALSE + /// Whether the item changes its layer to the layer suggested by the bed for tucked-in item. + /// When the item is untucked, it is returned to its initial() layer. + var/change_layer = FALSE -/datum/element/bed_tuckable/Attach(obj/target, x = 0, y = 0, rotation = 0) +/datum/element/bed_tuckable/Attach(obj/target, x = 0, y = 0, rotation = 0, _change_dir = FALSE, _change_layer = FALSE) . = ..() if(!isitem(target)) return ELEMENT_INCOMPATIBLE @@ -17,6 +22,8 @@ x_offset = x y_offset = y rotation_degree = rotation + change_dir = _change_dir + change_layer = _change_layer RegisterSignal(target, COMSIG_ITEM_ATTACK_OBJ, PROC_REF(tuck_into_bed)) /datum/element/bed_tuckable/Detach(obj/target) @@ -40,11 +47,20 @@ return to_chat(tucker, "You lay [tucked] out on [target_bed].") - tucked.pixel_x = x_offset - tucked.pixel_y = y_offset + tucked.pixel_x = x_offset + target_bed.tucked_x_shift + tucked.pixel_y = y_offset + target_bed.tucked_y_shift if(rotation_degree) tucked.transform = turn(tucked.transform, rotation_degree) RegisterSignal(tucked, COMSIG_ITEM_PICKUP, PROC_REF(untuck)) + // the buckle_lying value on the bed controls the direction that mobs lay down in when they're buckled into bed. + // some items (bedsheets) have different states to reflect those directions. + if(change_dir) + if(target_bed.buckle_lying == 270) + tucked.setDir(NORTH) + else + tucked.setDir(SOUTH) + if(target_bed.suggested_tuck_layer != null) + tucked.layer = target_bed.suggested_tuck_layer return COMPONENT_NO_AFTERATTACK @@ -57,4 +73,5 @@ SIGNAL_HANDLER tucked.transform = turn(tucked.transform, -rotation_degree) + tucked.layer = initial(tucked.layer) UnregisterSignal(tucked, COMSIG_ITEM_PICKUP) diff --git a/code/game/objects/items/plushes.dm b/code/game/objects/items/plushes.dm index 63e4ffc5e6c3..4b16ee60942d 100644 --- a/code/game/objects/items/plushes.dm +++ b/code/game/objects/items/plushes.dm @@ -38,7 +38,7 @@ . = ..() if(should_squeak) AddComponent(/datum/component/squeak, squeak_override) - AddElement(/datum/element/bed_tuckable, 6, -5, 90) + AddElement(/datum/element/bed_tuckable, 6, -5, 90, FALSE, FALSE) //have we decided if Pinocchio goes in the blue or pink aisle yet? if(gender == NEUTER) diff --git a/code/game/objects/items/stacks/sheets/recipes/recipes_metal.dm b/code/game/objects/items/stacks/sheets/recipes/recipes_metal.dm index 6860f34be5c7..9819a941e5f8 100644 --- a/code/game/objects/items/stacks/sheets/recipes/recipes_metal.dm +++ b/code/game/objects/items/stacks/sheets/recipes/recipes_metal.dm @@ -1,9 +1,13 @@ GLOBAL_LIST_INIT(metal_recipes, list ( \ new/datum/stack_recipe("stool", /obj/structure/chair/stool, one_per_turf = TRUE, on_floor = TRUE), \ new/datum/stack_recipe("bar stool", /obj/structure/chair/stool/bar, one_per_turf = TRUE, on_floor = TRUE), \ - new/datum/stack_recipe("bed", /obj/structure/bed, 2, one_per_turf = TRUE, on_floor = TRUE), \ - new/datum/stack_recipe("double bed", /obj/structure/bed/double, 4, one_per_turf = TRUE, on_floor = TRUE), \ null, \ + new/datum/stack_recipe_list("beds", list( \ + new/datum/stack_recipe("bed", /obj/structure/bed, 2, one_per_turf = TRUE, on_floor = TRUE), \ + new/datum/stack_recipe("double bed", /obj/structure/bed/double, 4, one_per_turf = TRUE, on_floor = TRUE), \ + new/datum/stack_recipe("bottom bunk", /obj/structure/bed/bunk, 2, one_per_turf = TRUE, on_floor = TRUE), \ + new/datum/stack_recipe("top bunk", /obj/structure/bed/bunk/top, 2, one_per_turf = TRUE, on_floor = TRUE), \ + )), \ new/datum/stack_recipe_list("office chairs", list( \ new/datum/stack_recipe("gray office chair", /obj/structure/chair/office, 5, one_per_turf = TRUE, on_floor = TRUE), \ new/datum/stack_recipe("light office chair", /obj/structure/chair/office/light, 5, one_per_turf = TRUE, on_floor = TRUE), \ diff --git a/code/game/objects/items/stacks/stack.dm b/code/game/objects/items/stacks/stack.dm index 5653b641c99d..f34836de156f 100644 --- a/code/game/objects/items/stacks/stack.dm +++ b/code/game/objects/items/stacks/stack.dm @@ -305,7 +305,7 @@ if(!window_structure.fulltile) continue if(object.density) - to_chat(usr, "There is \a [object.name] here. You cant make \a [recipe.title] here!") + to_chat(usr, "There is \a [object.name] here. You can't make \a [recipe.title] here!") return FALSE if(recipe.placement_checks) switch(recipe.placement_checks) diff --git a/code/game/objects/structures/beds_chairs/alien_nest.dm b/code/game/objects/structures/beds_chairs/alien_nest.dm index 4f132b11af99..ecc050aa8f77 100644 --- a/code/game/objects/structures/beds_chairs/alien_nest.dm +++ b/code/game/objects/structures/beds_chairs/alien_nest.dm @@ -14,6 +14,7 @@ buildstacktype = null flags_1 = NODECONSTRUCT_1 bolts = FALSE + swap_lying_with_dir = FALSE var/static/mutable_appearance/nest_overlay = mutable_appearance('icons/mob/alien.dmi', "nestoverlay", LYING_MOB_LAYER) /obj/structure/bed/nest/user_unbuckle_mob(mob/living/buckled_mob, mob/living/user) diff --git a/code/game/objects/structures/beds_chairs/bed.dm b/code/game/objects/structures/beds_chairs/bed.dm index 6c5f46e94a3b..ec7132a67cdd 100644 --- a/code/game/objects/structures/beds_chairs/bed.dm +++ b/code/game/objects/structures/beds_chairs/bed.dm @@ -18,10 +18,44 @@ resistance_flags = FLAMMABLE max_integrity = 100 integrity_failure = 0.35 + var/buildstacktype = /obj/item/stack/sheet/metal var/buildstackamount = 2 var/bolts = TRUE + /// Whether the bed changes its buckle_lying direction + /// (and accordingly the direction in which mobs lie down) based on its current direction. + var/swap_lying_with_dir = TRUE + /// If non-null, some items (bedsheets) which can be tucked into beds + /// will set their layer to this value when they are tucked in, until they are picked up again. + var/suggested_tuck_layer = null + /// The amount added to the pixel_x value of a tucked-in item. + var/tucked_x_shift = 0 + /// The amount added to the pixel_y value of a tucked-in item. + var/tucked_y_shift = 0 + +/obj/structure/bed/Initialize(...) + . = ..() + if(swap_lying_with_dir) + buckle_lying = get_buckle_angle_from_dir(dir) + +/obj/structure/bed/setDir(newdir) + . = ..() + if(swap_lying_with_dir) + buckle_lying = get_buckle_angle_from_dir(newdir) + // shuttle rotation etc... ugh. + if(has_buckled_mobs()) + for(var/mob/living/M as anything in buckled_mobs) + // this proc already checks to see if the new angle is different from the old one, + // so this shouldn't cause any duplicate work or unnecessary animations. + M.set_lying_angle(buckle_lying) + +/obj/structure/bed/proc/get_buckle_angle_from_dir(some_dir) + if(some_dir & (SOUTH|WEST)) + return 90 + else + return 270 + /obj/structure/bed/examine(mob/user) . = ..() if(bolts) @@ -52,6 +86,9 @@ icon_state = "down" anchored = FALSE resistance_flags = NONE + + // no dir states + swap_lying_with_dir = FALSE var/foldabletype = /obj/item/roller /obj/structure/bed/roller/attackby(obj/item/W, mob/user, params) @@ -161,8 +198,9 @@ else to_chat(user, "The dock is empty!") -//Dog bed - +/* + * "Dog" beds + */ /obj/structure/bed/dogbed name = "dog bed" icon_state = "dogbed" @@ -170,6 +208,9 @@ anchored = TRUE buildstacktype = /obj/item/stack/sheet/mineral/wood buildstackamount = 10 + + // no dir states + swap_lying_with_dir = FALSE var/mob/living/owner = null /obj/structure/bed/dogbed/ian @@ -206,7 +247,9 @@ . = ..() update_owner(M) -//Double Beds, for luxurious sleeping, i.e. the captain and maybe heads - no quirky refrence here. Move along +/* + * Double beds, for luxurious sleeping, i.e. the captain and maybe heads - no quirky refrence here. Move along + */ /obj/structure/bed/double name = "double bed" desc = "A luxurious double bed, for those too important for small dreams." @@ -232,3 +275,84 @@ name = "double dirty mattress" desc = "An old grubby king sized mattress. You really try to not think about what could be the cause of those stains." icon_state = "dirty_mattress_double" + +/* + * Bunk beds. Comes with an /obj/effect spawner that lets mappers place them down easily. + * The base type is the bottom bunk, with the top bunk as a derived type. + * Like other beds, the pillow may be on the left or right depending on the direction. + */ +/obj/structure/bed/bunk + name = "bottom bunk" + desc = "The oft-maligned bottom bunk of a compact bunk bed. Heavy sleepers only." + icon_state = "bottom_bunk" + // just below the top bunk's main layer + suggested_tuck_layer = LYING_MOB_LAYER + 0.005 + /// The amount added to the pixel_y value of mobs lying down, relative to the default shift for that position. + var/mob_y_shift = -1 + // i think it looks best without shifting the bedsheet down, even though the mob gets shifted down some + +// alter their pixel offset when they lie down... +/obj/structure/bed/bunk/post_buckle_mob(mob/living/M) + // we shift the lying mob a little so that they line up better with the pillow, but the shift direction changes + // depending on the direction they lie down in, controlled by buckle_lying + // (which is in turn based on our direction, but we don't need to worry about that directly) + var/horz_offset + if(buckle_lying == 90) + horz_offset = 2 + else + horz_offset = -2 + + M.pixel_x = M.get_standard_pixel_x_offset(M.body_position == LYING_DOWN) + horz_offset + M.pixel_y = M.get_standard_pixel_y_offset(M.body_position == LYING_DOWN) + mob_y_shift + +// ...and reset it when they get off +/obj/structure/bed/bunk/post_unbuckle_mob(mob/living/M) + M.pixel_x = M.get_standard_pixel_x_offset(M.body_position == LYING_DOWN) + M.pixel_y = M.get_standard_pixel_y_offset(M.body_position == LYING_DOWN) + + +/obj/structure/bed/bunk/top + name = "top bunk" + desc = "The top bunk of a compact bunk bed. Few other sleeping accommodations can match its luxury." + icon_state = "top_bunk" + + // higher layer, so that it renders on top of people on the bottom bunk + layer = LYING_MOB_LAYER + 0.01 + mob_y_shift = 13 + + // above the lying mob, but below the ladder + suggested_tuck_layer = LYING_MOB_LAYER + 0.025 + tucked_y_shift = 14 + +/obj/structure/bed/bunk/top/Initialize(...) + . = ..() + // the ladder needs to render above the mob + overlays += image(icon = 'icons/obj/objects.dmi', icon_state = "top_bunk_ladder", layer = LYING_MOB_LAYER + 0.03) + // and the posts need to render below the bottom bunk + overlays += image(icon = 'icons/obj/objects.dmi', icon_state = "top_bunk_posts", layer = TABLE_LAYER) + +/obj/structure/bed/bunk/top/post_buckle_mob(mob/living/M) + . = ..() + M.layer = LYING_MOB_LAYER + 0.02 + +/obj/structure/bed/bunk/top/post_unbuckle_mob(mob/living/M) + . = ..() + // honestly not really confident in this, but since standing up takes a do_after + // (and thus happens afterwards, resetting the layer), it should be fine... + // i'm more worried about altering layers via + and -, since if you figured out ways + // of stacking those you could layer yourself under, like, the floor. + M.layer = LYING_MOB_LAYER + + +// the spawner +/obj/effect/spawner/bunk_bed + name = "bunk bed spawner" + icon_state = "bunk_bed_spawner" + +/obj/effect/spawner/bunk_bed/Initialize(...) + . = ..() + var/obj/structure/bed/bunk/bottom_bunk = new(loc) + var/obj/structure/bed/bunk/top/top_bunk = new(loc) + + bottom_bunk.setDir(dir) + top_bunk.setDir(dir) diff --git a/code/game/objects/structures/bedsheet_bin.dm b/code/game/objects/structures/bedsheet_bin.dm index 1a89195c646a..31e9d9a0b8fc 100644 --- a/code/game/objects/structures/bedsheet_bin.dm +++ b/code/game/objects/structures/bedsheet_bin.dm @@ -28,7 +28,7 @@ LINEN BINS /obj/item/bedsheet/Initialize(mapload) . = ..() - AddElement(/datum/element/bed_tuckable, 0, 0, 0) + AddElement(/datum/element/bed_tuckable, 0, 0, 0, TRUE, TRUE) /obj/item/bedsheet/attack_self(mob/user) if(!user.CanReach(src)) //No telekenetic grabbing. diff --git a/code/game/objects/structures/tank_dispenser.dm b/code/game/objects/structures/tank_dispenser.dm index 1be5f857e155..c0604dd5e09b 100644 --- a/code/game/objects/structures/tank_dispenser.dm +++ b/code/game/objects/structures/tank_dispenser.dm @@ -28,10 +28,10 @@ /obj/structure/tank_dispenser/update_overlays() . = ..() switch(oxygentanks) - if(1 to 3) + if(1 to 4) . += "oxygen-[oxygentanks]" - if(4 to TANK_DISPENSER_CAPACITY) - . += "oxygen-4" + if(5 to TANK_DISPENSER_CAPACITY) + . += "oxygen-5" switch(plasmatanks) if(1 to 4) . += "plasma-[plasmatanks]" diff --git a/code/modules/antagonists/abductor/equipment/abduction_gear.dm b/code/modules/antagonists/abductor/equipment/abduction_gear.dm index 5bce8014babe..abc69300c9c6 100644 --- a/code/modules/antagonists/abductor/equipment/abduction_gear.dm +++ b/code/modules/antagonists/abductor/equipment/abduction_gear.dm @@ -761,6 +761,7 @@ Congratulations! You are now trained for invasive xenobiology research!"} icon = 'icons/obj/abductor.dmi' buildstacktype = /obj/item/stack/sheet/mineral/abductor icon_state = "bed" + swap_lying_with_dir = FALSE /obj/structure/table_frame/abductor name = "alien table frame" diff --git a/code/modules/antagonists/nukeop/equipment/nuclearbomb.dm b/code/modules/antagonists/nukeop/equipment/nuclearbomb.dm index 9c65e50130cf..c073a7c3521c 100644 --- a/code/modules/antagonists/nukeop/equipment/nuclearbomb.dm +++ b/code/modules/antagonists/nukeop/equipment/nuclearbomb.dm @@ -608,7 +608,7 @@ This is here to make the tiles around the station mininuke change when it's arme /obj/item/disk/nuclear/Initialize() . = ..() - AddElement(/datum/element/bed_tuckable, 6, -6, 0) + AddElement(/datum/element/bed_tuckable, 6, -6, 0, FALSE, FALSE) if(!fake) SSpoints_of_interest.make_point_of_interest(src) diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm index 3ed2b86816ac..9a19e198a555 100644 --- a/code/modules/mob/living/carbon/carbon.dm +++ b/code/modules/mob/living/carbon/carbon.dm @@ -386,7 +386,7 @@ /mob/living/carbon/get_standard_pixel_y_offset(lying = 0) if(lying) - return -6 + return PIXEL_Y_OFFSET_LYING else return initial(pixel_y) diff --git a/icons/effects/effects.dmi b/icons/effects/effects.dmi index 0aa256c631e428148e97de7cb47668ff901b7abc..bb63eb2b7f0ed5f486bf924e7fc009cfb034276b 100644 GIT binary patch delta 15274 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 F{a^HXrM>_F delta 13975 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 A*8l(j diff --git a/icons/obj/objects.dmi b/icons/obj/objects.dmi index 1b156b9294f9f7f3339ceff03486df17204f65c5..8479c100f1b0a25f9ca2e2cb61b391e86f03899e 100644 GIT binary patch delta 11309 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 PzzD0 From ea15b40ba8a113123dacb8f8e582aa928c43d587 Mon Sep 17 00:00:00 2001 From: Changelogs Date: Tue, 1 Oct 2024 03:20:54 -0500 Subject: [PATCH 12/12] Automatic changelog generation for PR #3345 [ci skip] --- html/changelogs/AutoChangeLog-pr-3345.yml | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 html/changelogs/AutoChangeLog-pr-3345.yml diff --git a/html/changelogs/AutoChangeLog-pr-3345.yml b/html/changelogs/AutoChangeLog-pr-3345.yml new file mode 100644 index 000000000000..3da650007188 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-3345.yml @@ -0,0 +1,6 @@ +author: tmtmtl30, Thgvr +changes: + - {rscadd: 'Added bunkbeds, which can now be crafted with metal or placed by mappers.'} + - {bugfix: Beds facing alternate directions now correctly support people buckling + to them and bedsheets being placed on top of them.} +delete-after: true