diff --git a/_maps/RandomRuins/IceRuins/icemoon_underground_abandoned_plasma_facility.dmm b/_maps/RandomRuins/IceRuins/icemoon_underground_abandoned_plasma_facility.dmm index 865695e5b3327..356bed29f9fe1 100644 --- a/_maps/RandomRuins/IceRuins/icemoon_underground_abandoned_plasma_facility.dmm +++ b/_maps/RandomRuins/IceRuins/icemoon_underground_abandoned_plasma_facility.dmm @@ -1016,7 +1016,7 @@ /area/ruin/plasma_facility/commons) "pE" = ( /obj/structure/bed/maint, -/obj/item/bedsheet/dorms, +/obj/effect/spawner/random/bedsheet, /obj/item/flashlight/flare/candle{ pixel_x = 12; pixel_y = 9 diff --git a/_maps/RandomRuins/IceRuins/icemoon_underground_abandoned_village.dmm b/_maps/RandomRuins/IceRuins/icemoon_underground_abandoned_village.dmm index c2b11194dfb4c..97b4e3d53c99f 100644 --- a/_maps/RandomRuins/IceRuins/icemoon_underground_abandoned_village.dmm +++ b/_maps/RandomRuins/IceRuins/icemoon_underground_abandoned_village.dmm @@ -40,7 +40,7 @@ "fD" = ( /obj/structure/bed, /obj/effect/decal/cleanable/blood/bubblegum, -/obj/item/bedsheet/random, +/obj/effect/spawner/random/bedsheet/any, /turf/open/floor/wood, /area/ruin/powered) "gG" = ( @@ -416,7 +416,7 @@ /obj/structure/bed{ dir = 4 }, -/obj/item/bedsheet/random{ +/obj/effect/spawner/random/bedsheet/any{ dir = 4 }, /turf/open/floor/wood, diff --git a/_maps/RandomRuins/IceRuins/icemoon_underground_frozen_comms.dmm b/_maps/RandomRuins/IceRuins/icemoon_underground_frozen_comms.dmm index 25f29890f45db..eb537cd26f6c6 100644 --- a/_maps/RandomRuins/IceRuins/icemoon_underground_frozen_comms.dmm +++ b/_maps/RandomRuins/IceRuins/icemoon_underground_frozen_comms.dmm @@ -63,7 +63,7 @@ "oj" = ( /obj/effect/decal/cleanable/dirt, /obj/structure/bed, -/obj/item/bedsheet/dorms, +/obj/effect/spawner/random/bedsheet, /turf/open/floor/iron/grimy{ initial_gas_mix = "ICEMOON_ATMOS" }, diff --git a/_maps/RandomRuins/LavaRuins/lavaland_biodome_beach.dmm b/_maps/RandomRuins/LavaRuins/lavaland_biodome_beach.dmm index c97bd25796016..7de6e7d990082 100644 --- a/_maps/RandomRuins/LavaRuins/lavaland_biodome_beach.dmm +++ b/_maps/RandomRuins/LavaRuins/lavaland_biodome_beach.dmm @@ -286,7 +286,7 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer4{ dir = 4 }, -/obj/item/bedsheet/dorms{ +/obj/effect/spawner/random/bedsheet{ dir = 4 }, /obj/structure/bed{ diff --git a/_maps/RandomRuins/SpaceRuins/DJstation/quarters_1.dmm b/_maps/RandomRuins/SpaceRuins/DJstation/quarters_1.dmm index c389af77150b2..dc6cea464f7ef 100644 --- a/_maps/RandomRuins/SpaceRuins/DJstation/quarters_1.dmm +++ b/_maps/RandomRuins/SpaceRuins/DJstation/quarters_1.dmm @@ -16,7 +16,7 @@ /area/ruin/space/djstation) "k" = ( /obj/structure/bed, -/obj/item/bedsheet/random, +/obj/effect/spawner/random/bedsheet/any, /turf/open/floor/iron/grimy, /area/ruin/space/djstation) "p" = ( @@ -41,7 +41,7 @@ /obj/structure/bed{ dir = 4 }, -/obj/item/bedsheet/random{ +/obj/effect/spawner/random/bedsheet/any{ dir = 4 }, /turf/open/floor/iron/grimy, diff --git a/_maps/RandomRuins/SpaceRuins/DJstation/quarters_4.dmm b/_maps/RandomRuins/SpaceRuins/DJstation/quarters_4.dmm index 8e632403b3669..52ec466ae8623 100644 --- a/_maps/RandomRuins/SpaceRuins/DJstation/quarters_4.dmm +++ b/_maps/RandomRuins/SpaceRuins/DJstation/quarters_4.dmm @@ -39,7 +39,7 @@ /turf/open/floor/iron/freezer/airless, /area/ruin/space/djstation) "x" = ( -/obj/item/bedsheet/random, +/obj/effect/spawner/random/bedsheet/any, /turf/open/floor/plating/airless, /area/ruin/space/djstation) "A" = ( diff --git a/_maps/RandomRuins/SpaceRuins/deepstorage.dmm b/_maps/RandomRuins/SpaceRuins/deepstorage.dmm index 5645ac3ef152c..2c23219b7d382 100644 --- a/_maps/RandomRuins/SpaceRuins/deepstorage.dmm +++ b/_maps/RandomRuins/SpaceRuins/deepstorage.dmm @@ -1958,7 +1958,7 @@ /area/ruin/space/has_grav/deepstorage/hydroponics) "zl" = ( /obj/structure/bed/double, -/obj/item/bedsheet/dorms_double, +/obj/effect/spawner/random/bedsheet/double, /obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2, /turf/open/floor/wood, /area/ruin/space/has_grav/deepstorage/dorm) @@ -2128,7 +2128,7 @@ "Ev" = ( /obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2, /obj/structure/bed/double, -/obj/item/bedsheet/dorms_double, +/obj/effect/spawner/random/bedsheet/double, /turf/open/floor/wood, /area/ruin/space/has_grav/deepstorage/dorm) "EA" = ( diff --git a/_maps/RandomRuins/SpaceRuins/hellfactory.dmm b/_maps/RandomRuins/SpaceRuins/hellfactory.dmm index 9660b317c66f1..524e81ebb69cc 100644 --- a/_maps/RandomRuins/SpaceRuins/hellfactory.dmm +++ b/_maps/RandomRuins/SpaceRuins/hellfactory.dmm @@ -570,7 +570,7 @@ /area/ruin/space/has_grav/hellfactory) "cc" = ( /obj/structure/bed, -/obj/item/bedsheet/dorms, +/obj/effect/spawner/random/bedsheet, /turf/open/floor/holofloor/wood, /area/ruin/space/has_grav/hellfactory) "cd" = ( @@ -899,7 +899,7 @@ /area/ruin/space/has_grav/hellfactoryoffice) "xK" = ( /obj/structure/bed, -/obj/item/bedsheet/dorms, +/obj/effect/spawner/random/bedsheet, /obj/effect/decal/cleanable/cobweb/cobweb2, /turf/open/floor/holofloor/wood, /area/ruin/space/has_grav/hellfactory) diff --git a/_maps/RandomRuins/SpaceRuins/hilbertresearchfacility.dmm b/_maps/RandomRuins/SpaceRuins/hilbertresearchfacility.dmm index f829696000951..b964addf1f6e6 100644 --- a/_maps/RandomRuins/SpaceRuins/hilbertresearchfacility.dmm +++ b/_maps/RandomRuins/SpaceRuins/hilbertresearchfacility.dmm @@ -349,7 +349,7 @@ /area/ruin/space/has_grav/powered/hilbertresearchfacility) "jt" = ( /obj/structure/bed, -/obj/item/bedsheet/dorms, +/obj/effect/spawner/random/bedsheet, /turf/open/floor/carpet/black, /area/ruin/space/has_grav/powered/hilbertresearchfacility) "jC" = ( diff --git a/_maps/RandomRuins/SpaceRuins/waystation.dmm b/_maps/RandomRuins/SpaceRuins/waystation.dmm index 9399ee029474d..def97102238e5 100644 --- a/_maps/RandomRuins/SpaceRuins/waystation.dmm +++ b/_maps/RandomRuins/SpaceRuins/waystation.dmm @@ -1143,7 +1143,7 @@ /area/ruin/space/has_grav/waystation/dorms) "rQ" = ( /obj/structure/bed, -/obj/item/bedsheet/random, +/obj/effect/spawner/random/bedsheet/any, /turf/open/floor/wood, /area/ruin/space/has_grav/waystation/dorms) "rV" = ( @@ -1889,7 +1889,7 @@ /area/ruin/space/has_grav/waystation/cargobay) "IS" = ( /obj/structure/bed, -/obj/item/bedsheet/random, +/obj/effect/spawner/random/bedsheet/any, /obj/effect/decal/cleanable/dirt, /turf/open/floor/wood, /area/ruin/space/has_grav/waystation/dorms) diff --git a/_maps/RandomZLevels/SnowCabin.dmm b/_maps/RandomZLevels/SnowCabin.dmm index c6366d62e541d..7ad0b42218f51 100644 --- a/_maps/RandomZLevels/SnowCabin.dmm +++ b/_maps/RandomZLevels/SnowCabin.dmm @@ -2142,7 +2142,7 @@ /area/awaymission/cabin/caves) "km" = ( /obj/structure/bed, -/obj/item/bedsheet/dorms, +/obj/effect/spawner/random/bedsheet, /turf/open/floor/wood, /area/awaymission/cabin/caves) "ko" = ( diff --git a/_maps/map_files/Basketball/beach_bums.dmm b/_maps/map_files/Basketball/beach_bums.dmm index aa5948a34e6d2..517e70f2b630a 100644 --- a/_maps/map_files/Basketball/beach_bums.dmm +++ b/_maps/map_files/Basketball/beach_bums.dmm @@ -1,6 +1,6 @@ //MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE "af" = ( -/obj/item/bedsheet/dorms{ +/obj/effect/spawner/random/bedsheet{ pixel_x = 6; pixel_y = 11 }, @@ -344,7 +344,7 @@ /turf/open/misc/beach/sand, /area/centcom/basketball) "Jb" = ( -/obj/item/bedsheet/dorms{ +/obj/effect/spawner/random/bedsheet{ pixel_x = 6; pixel_y = 11 }, @@ -360,7 +360,7 @@ /turf/open/misc/beach/sand, /area/centcom/basketball) "Lu" = ( -/obj/item/bedsheet/dorms{ +/obj/effect/spawner/random/bedsheet{ pixel_x = 6; pixel_y = 11 }, diff --git a/_maps/map_files/Birdshot/birdshot.dmm b/_maps/map_files/Birdshot/birdshot.dmm index 72516d9c396fa..09cd9472764a6 100644 --- a/_maps/map_files/Birdshot/birdshot.dmm +++ b/_maps/map_files/Birdshot/birdshot.dmm @@ -9299,7 +9299,7 @@ /area/station/maintenance/department/medical/central) "dBA" = ( /obj/structure/bed, -/obj/item/bedsheet/dorms, +/obj/effect/spawner/random/bedsheet, /obj/machinery/light/small/directional/east, /turf/open/floor/carpet/royalblack, /area/station/commons/dorms) @@ -11067,7 +11067,7 @@ /obj/structure/bed{ dir = 4 }, -/obj/item/bedsheet/dorms{ +/obj/effect/spawner/random/bedsheet{ dir = 4 }, /obj/machinery/light/small/directional/west, @@ -39807,7 +39807,7 @@ /area/station/security/checkpoint/customs) "ohO" = ( /obj/structure/bed, -/obj/item/bedsheet/dorms, +/obj/effect/spawner/random/bedsheet, /obj/machinery/light/small/directional/east, /turf/open/floor/carpet/red, /area/station/commons/dorms) @@ -70063,7 +70063,7 @@ /obj/structure/bed{ dir = 4 }, -/obj/item/bedsheet/dorms{ +/obj/effect/spawner/random/bedsheet{ dir = 4 }, /obj/machinery/light/small/directional/west, diff --git a/_maps/map_files/Deltastation/DeltaStation2.dmm b/_maps/map_files/Deltastation/DeltaStation2.dmm index bd942b1bd8787..28143ce53ea8b 100644 --- a/_maps/map_files/Deltastation/DeltaStation2.dmm +++ b/_maps/map_files/Deltastation/DeltaStation2.dmm @@ -1408,7 +1408,7 @@ /obj/structure/bed{ dir = 4 }, -/obj/item/bedsheet/dorms{ +/obj/effect/spawner/random/bedsheet{ dir = 1 }, /obj/item/pillow/random, @@ -55689,7 +55689,7 @@ /area/station/maintenance/department/science) "nTU" = ( /obj/structure/bed, -/obj/item/bedsheet/dorms, +/obj/effect/spawner/random/bedsheet, /obj/effect/decal/cleanable/dirt, /obj/effect/landmark/start/hangover, /obj/item/pillow/random, @@ -58792,7 +58792,7 @@ /area/station/maintenance/department/science) "oLO" = ( /obj/structure/bed, -/obj/item/bedsheet/dorms, +/obj/effect/spawner/random/bedsheet, /obj/machinery/status_display/evac/directional/east, /obj/item/pillow/random, /turf/open/floor/wood, @@ -63735,7 +63735,7 @@ /obj/structure/bed{ dir = 4 }, -/obj/item/bedsheet/dorms{ +/obj/effect/spawner/random/bedsheet{ dir = 1 }, /obj/machinery/status_display/evac/directional/north, @@ -82687,7 +82687,7 @@ /area/station/tcommsat/server) "uEo" = ( /obj/structure/bed/double, -/obj/item/bedsheet/dorms_double, +/obj/effect/spawner/random/bedsheet/double, /obj/machinery/status_display/evac/directional/east, /obj/effect/landmark/start/hangover, /obj/item/pillow/random, @@ -93649,7 +93649,7 @@ /area/station/science/genetics) "xso" = ( /obj/structure/bed/double, -/obj/item/bedsheet/random/double, +/obj/effect/spawner/random/bedsheet/any/double, /turf/open/floor/wood, /area/station/maintenance/port/aft) "xsp" = ( diff --git a/_maps/map_files/IceBoxStation/IceBoxStation.dmm b/_maps/map_files/IceBoxStation/IceBoxStation.dmm index efeb6bc25c74e..3b78dacec0643 100644 --- a/_maps/map_files/IceBoxStation/IceBoxStation.dmm +++ b/_maps/map_files/IceBoxStation/IceBoxStation.dmm @@ -6937,7 +6937,7 @@ /area/station/engineering/atmos/project) "ccp" = ( /obj/structure/bed, -/obj/item/bedsheet/dorms, +/obj/effect/spawner/random/bedsheet, /obj/effect/landmark/start/hangover, /obj/machinery/button/door/directional/south{ id = "Dorm5"; @@ -10057,7 +10057,7 @@ /area/station/cargo/office) "cXp" = ( /obj/structure/bed/pod, -/obj/item/bedsheet/random, +/obj/effect/spawner/random/bedsheet/any, /obj/effect/mapping_helpers/broken_floor, /turf/open/floor/wood, /area/station/maintenance/port/fore) @@ -10420,7 +10420,7 @@ "dcq" = ( /obj/structure/bed, /obj/machinery/airalarm/directional/north, -/obj/item/bedsheet/dorms, +/obj/effect/spawner/random/bedsheet, /obj/machinery/button/door/directional/east{ id = "Dorm3"; name = "Dorm Bolt Control"; @@ -34264,7 +34264,7 @@ /area/station/hallway/secondary/service) "kzv" = ( /obj/structure/bed, -/obj/item/bedsheet/random, +/obj/effect/spawner/random/bedsheet/any, /turf/open/floor/plating, /area/station/maintenance/department/medical/morgue) "kzw" = ( @@ -41367,7 +41367,7 @@ "mJO" = ( /obj/structure/bed, /obj/machinery/airalarm/directional/north, -/obj/item/bedsheet/dorms, +/obj/effect/spawner/random/bedsheet, /obj/machinery/button/door/directional/east{ id = "Dorm2"; name = "Dorm Bolt Control"; @@ -45232,7 +45232,7 @@ "nOl" = ( /obj/structure/bed, /obj/machinery/airalarm/directional/north, -/obj/item/bedsheet/dorms, +/obj/effect/spawner/random/bedsheet, /obj/effect/landmark/start/hangover, /obj/machinery/button/door/directional/east{ id = "Dorm4"; @@ -49799,7 +49799,7 @@ /area/station/hallway/primary/central) "piC" = ( /obj/structure/bed, -/obj/item/bedsheet/dorms, +/obj/effect/spawner/random/bedsheet, /obj/machinery/button/door/directional/south{ id = "Dorm6"; name = "Cabin Bolt Control"; @@ -63483,7 +63483,7 @@ /obj/structure/bed{ dir = 1 }, -/obj/item/bedsheet/dorms{ +/obj/effect/spawner/random/bedsheet{ dir = 1 }, /obj/effect/spawner/random/contraband/permabrig_gear, @@ -66635,7 +66635,7 @@ /obj/structure/bed{ dir = 1 }, -/obj/item/bedsheet/dorms{ +/obj/effect/spawner/random/bedsheet{ dir = 1 }, /obj/effect/turf_decal/trimline/red/filled/line{ diff --git a/_maps/map_files/MetaStation/MetaStation.dmm b/_maps/map_files/MetaStation/MetaStation.dmm index b2a9971f12f91..03dfa234b14be 100644 --- a/_maps/map_files/MetaStation/MetaStation.dmm +++ b/_maps/map_files/MetaStation/MetaStation.dmm @@ -1124,7 +1124,7 @@ /area/station/maintenance/fore/lesser) "avU" = ( /obj/structure/bed, -/obj/item/bedsheet/dorms, +/obj/effect/spawner/random/bedsheet, /obj/machinery/atmospherics/components/unary/vent_pump/on/layer4, /obj/machinery/button/door/directional/east{ id = "Cabin2"; @@ -31986,7 +31986,7 @@ /area/station/medical/virology) "lxf" = ( /obj/structure/bed, -/obj/item/bedsheet/dorms, +/obj/effect/spawner/random/bedsheet, /obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2, /obj/machinery/button/door/directional/west{ id = "Cabin5"; @@ -41784,7 +41784,7 @@ "oYv" = ( /obj/effect/decal/cleanable/cobweb, /obj/structure/bed, -/obj/item/bedsheet/dorms, +/obj/effect/spawner/random/bedsheet, /obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2, /obj/machinery/button/door/directional/west{ id = "Cabin4"; @@ -50133,7 +50133,7 @@ /area/station/commons/locker) "rUo" = ( /obj/structure/bed, -/obj/item/bedsheet/dorms, +/obj/effect/spawner/random/bedsheet, /obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2{ dir = 1 }, @@ -51804,7 +51804,7 @@ "sBa" = ( /obj/structure/bed, /obj/effect/decal/cleanable/cobweb/cobweb2, -/obj/item/bedsheet/dorms, +/obj/effect/spawner/random/bedsheet, /obj/machinery/atmospherics/components/unary/vent_pump/on/layer4, /obj/machinery/button/door/directional/east{ id = "Cabin3"; @@ -64199,7 +64199,7 @@ "wNp" = ( /obj/structure/bed, /obj/effect/decal/cleanable/cobweb, -/obj/item/bedsheet/dorms, +/obj/effect/spawner/random/bedsheet, /obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2, /obj/effect/landmark/start/hangover, /obj/machinery/button/door/directional/west{ diff --git a/_maps/map_files/NorthStar/north_star.dmm b/_maps/map_files/NorthStar/north_star.dmm index e01fb546e4c3a..9a1372065a6d9 100644 --- a/_maps/map_files/NorthStar/north_star.dmm +++ b/_maps/map_files/NorthStar/north_star.dmm @@ -26977,7 +26977,7 @@ /area/station/medical/pharmacy) "heS" = ( /obj/structure/bed/double, -/obj/item/bedsheet/dorms_double, +/obj/effect/spawner/random/bedsheet/double, /obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ dir = 8 }, @@ -27019,7 +27019,7 @@ /area/station/maintenance/floor1/starboard/aft) "hfy" = ( /obj/structure/bed/double, -/obj/item/bedsheet/dorms_double, +/obj/effect/spawner/random/bedsheet/double, /obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ dir = 8 }, @@ -33741,7 +33741,7 @@ /area/station/maintenance/floor1/starboard/fore) "iTn" = ( /obj/structure/bed, -/obj/item/bedsheet/dorms, +/obj/effect/spawner/random/bedsheet, /turf/open/floor/carpet/black, /area/station/hallway/secondary/service) "iTu" = ( @@ -63497,7 +63497,7 @@ /area/station/science/genetics) "qBh" = ( /obj/structure/bed/double, -/obj/item/bedsheet/dorms_double, +/obj/effect/spawner/random/bedsheet/double, /obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ dir = 8 }, @@ -63553,7 +63553,7 @@ /area/station/commons/fitness) "qCn" = ( /obj/structure/bed, -/obj/item/bedsheet/random, +/obj/effect/spawner/random/bedsheet/any, /turf/open/floor/wood, /area/station/medical/psychology) "qCo" = ( diff --git a/_maps/map_files/tramstation/tramstation.dmm b/_maps/map_files/tramstation/tramstation.dmm index bd915e60abb13..57379c2353eed 100644 --- a/_maps/map_files/tramstation/tramstation.dmm +++ b/_maps/map_files/tramstation/tramstation.dmm @@ -7420,7 +7420,7 @@ /obj/structure/bed{ dir = 4 }, -/obj/item/bedsheet/dorms{ +/obj/effect/spawner/random/bedsheet{ dir = 4 }, /obj/structure/sign/clock/directional/west, @@ -10176,7 +10176,7 @@ /area/station/command/heads_quarters/captain) "cvg" = ( /obj/structure/bed/double, -/obj/item/bedsheet/dorms_double, +/obj/effect/spawner/random/bedsheet/double, /obj/effect/landmark/start/assistant, /obj/structure/sign/clock/directional/north, /obj/item/pillow/random, @@ -11408,7 +11408,7 @@ /obj/structure/bed{ dir = 4 }, -/obj/item/bedsheet/dorms{ +/obj/effect/spawner/random/bedsheet{ dir = 4 }, /obj/effect/landmark/start/assistant, @@ -14385,7 +14385,7 @@ /obj/structure/bed{ dir = 4 }, -/obj/item/bedsheet/dorms{ +/obj/effect/spawner/random/bedsheet{ dir = 4 }, /obj/structure/sign/clock/directional/south, @@ -22999,7 +22999,7 @@ /obj/structure/bed{ dir = 8 }, -/obj/item/bedsheet/dorms, +/obj/effect/spawner/random/bedsheet, /obj/structure/sign/clock/directional/east, /obj/item/pillow/random, /turf/open/floor/wood, @@ -24884,7 +24884,7 @@ /area/station/security/brig) "hRK" = ( /obj/structure/bed, -/obj/item/bedsheet/dorms, +/obj/effect/spawner/random/bedsheet, /obj/effect/landmark/start/hangover, /obj/structure/sign/clock/directional/south, /obj/item/pillow/random, @@ -26311,7 +26311,7 @@ /area/station/hallway/secondary/entry) "iuJ" = ( /obj/structure/bed/double, -/obj/item/bedsheet/dorms_double, +/obj/effect/spawner/random/bedsheet/double, /obj/structure/sign/clock/directional/north, /obj/item/pillow/random, /turf/open/floor/carpet, @@ -28841,7 +28841,7 @@ /obj/structure/bed{ dir = 8 }, -/obj/item/bedsheet/dorms, +/obj/effect/spawner/random/bedsheet, /obj/effect/landmark/start/assistant, /obj/structure/sign/clock/directional/east, /obj/item/pillow/random, @@ -36227,7 +36227,7 @@ /obj/structure/bed{ dir = 8 }, -/obj/item/bedsheet/dorms, +/obj/effect/spawner/random/bedsheet, /obj/effect/landmark/start/assistant, /obj/structure/sign/clock/directional/east, /obj/item/pillow/random, @@ -45402,7 +45402,7 @@ /turf/open/floor/iron/showroomfloor, /area/station/security/warden) "pfm" = ( -/obj/item/bedsheet/dorms_double{ +/obj/effect/spawner/random/bedsheet/double{ dir = 4 }, /obj/structure/bed/double{ @@ -59280,7 +59280,7 @@ /obj/structure/bed{ dir = 4 }, -/obj/item/bedsheet/dorms{ +/obj/effect/spawner/random/bedsheet{ dir = 4 }, /obj/structure/sign/clock/directional/west, @@ -59892,7 +59892,7 @@ /obj/structure/bed{ dir = 8 }, -/obj/item/bedsheet/dorms, +/obj/effect/spawner/random/bedsheet, /obj/structure/sign/clock/directional/east, /obj/item/pillow/random, /turf/open/floor/carpet, @@ -60494,7 +60494,7 @@ /area/station/hallway/secondary/command) "upb" = ( /obj/structure/bed/double, -/obj/item/bedsheet/dorms_double, +/obj/effect/spawner/random/bedsheet/double, /obj/effect/landmark/start/hangover, /obj/structure/sign/clock/directional/north, /obj/item/pillow/random, @@ -67525,7 +67525,7 @@ /obj/structure/bed/double{ dir = 4 }, -/obj/item/bedsheet/dorms_double{ +/obj/effect/spawner/random/bedsheet/double{ dir = 4 }, /obj/structure/sign/clock/directional/north, diff --git a/_maps/shuttles/emergency_clown.dmm b/_maps/shuttles/emergency_clown.dmm index f5c0ca4ea61eb..fc943e5287bb8 100644 --- a/_maps/shuttles/emergency_clown.dmm +++ b/_maps/shuttles/emergency_clown.dmm @@ -158,7 +158,7 @@ /area/shuttle/escape) "aM" = ( /obj/structure/bed, -/obj/item/bedsheet/random, +/obj/effect/spawner/random/bedsheet/any, /turf/open/floor/mineral/bananium, /area/shuttle/escape) "aQ" = ( @@ -246,7 +246,7 @@ /area/shuttle/escape) "iU" = ( /obj/structure/bed, -/obj/item/bedsheet/random, +/obj/effect/spawner/random/bedsheet/any, /obj/machinery/light/small/directional/east, /turf/open/floor/mineral/bananium, /area/shuttle/escape) @@ -254,7 +254,7 @@ /obj/structure/bed{ dir = 4 }, -/obj/item/bedsheet/random{ +/obj/effect/spawner/random/bedsheet/any{ dir = 4 }, /turf/open/floor/mineral/bananium, @@ -289,7 +289,7 @@ /obj/structure/bed{ dir = 4 }, -/obj/item/bedsheet/random{ +/obj/effect/spawner/random/bedsheet/any{ dir = 4 }, /obj/machinery/light/small/directional/west, @@ -300,7 +300,7 @@ /obj/structure/bed{ dir = 4 }, -/obj/item/bedsheet/random{ +/obj/effect/spawner/random/bedsheet/any{ dir = 4 }, /turf/open/floor/mineral/bananium, @@ -315,7 +315,7 @@ "XT" = ( /obj/structure/window/reinforced/spawner/directional/east, /obj/structure/bed, -/obj/item/bedsheet/random, +/obj/effect/spawner/random/bedsheet/any, /turf/open/floor/mineral/bananium, /area/shuttle/escape) "YC" = ( diff --git a/_maps/shuttles/emergency_hugcage.dmm b/_maps/shuttles/emergency_hugcage.dmm index 6e68506c4332e..4b500f7bdbd45 100644 --- a/_maps/shuttles/emergency_hugcage.dmm +++ b/_maps/shuttles/emergency_hugcage.dmm @@ -3,7 +3,7 @@ /turf/closed/wall/mineral/titanium/nodiagonal, /area/shuttle/escape/brig) "aR" = ( -/obj/item/bedsheet/random{ +/obj/effect/spawner/random/bedsheet/any{ dir = 8 }, /obj/structure/bed, @@ -83,7 +83,7 @@ /turf/closed/wall/mineral/titanium, /area/shuttle/escape) "gg" = ( -/obj/item/bedsheet/random{ +/obj/effect/spawner/random/bedsheet/any{ dir = 4 }, /obj/structure/bed{ @@ -116,7 +116,7 @@ /area/shuttle/escape) "iI" = ( /obj/structure/bed, -/obj/item/bedsheet/random, +/obj/effect/spawner/random/bedsheet/any, /obj/item/pillow/random, /obj/effect/spawner/random/entertainment/plushie_delux, /turf/open/floor/mineral/titanium/yellow, @@ -148,7 +148,7 @@ /obj/structure/bed{ dir = 1 }, -/obj/item/bedsheet/random{ +/obj/effect/spawner/random/bedsheet/any{ dir = 4 }, /obj/item/pillow/random, @@ -211,7 +211,7 @@ /turf/open/floor/mineral/titanium/blue, /area/shuttle/escape) "ys" = ( -/obj/item/bedsheet/random{ +/obj/effect/spawner/random/bedsheet/any{ dir = 4 }, /obj/structure/bed{ @@ -327,7 +327,7 @@ /turf/open/floor/mineral/plastitanium/red, /area/shuttle/escape/brig) "KW" = ( -/obj/item/bedsheet/random{ +/obj/effect/spawner/random/bedsheet/any{ dir = 8 }, /obj/structure/bed, diff --git a/_maps/shuttles/pirate_grey.dmm b/_maps/shuttles/pirate_grey.dmm index 0726d8d1ea196..7ba8fdd5a5ced 100644 --- a/_maps/shuttles/pirate_grey.dmm +++ b/_maps/shuttles/pirate_grey.dmm @@ -955,7 +955,7 @@ /area/shuttle/pirate) "DP" = ( /obj/structure/bed, -/obj/item/bedsheet/random, +/obj/effect/spawner/random/bedsheet/any, /turf/open/floor/plating, /area/shuttle/pirate) "DX" = ( diff --git a/_maps/shuttles/pirate_silverscale.dmm b/_maps/shuttles/pirate_silverscale.dmm index e4838e040e472..d4bd9d0c16b3e 100644 --- a/_maps/shuttles/pirate_silverscale.dmm +++ b/_maps/shuttles/pirate_silverscale.dmm @@ -91,7 +91,7 @@ /obj/structure/bed/pod{ dir = 4 }, -/obj/item/bedsheet/black{ +/obj/item/bedsheet/pirate{ dir = 4 }, /turf/open/floor/carpet/royalblack, @@ -288,7 +288,7 @@ /area/shuttle/pirate) "uP" = ( /obj/structure/bed/pod, -/obj/item/bedsheet/black, +/obj/item/bedsheet/pirate, /turf/open/floor/carpet/royalblack, /area/shuttle/pirate) "vw" = ( @@ -381,7 +381,7 @@ /obj/machinery/airalarm/directional/east, /obj/effect/mapping_helpers/airalarm/all_access, /obj/structure/bed/pod, -/obj/item/bedsheet/black, +/obj/item/bedsheet/pirate, /turf/open/floor/carpet/royalblack, /area/shuttle/pirate) "zB" = ( diff --git a/_maps/shuttles/ruin_pirate_cutter.dmm b/_maps/shuttles/ruin_pirate_cutter.dmm index 9fa1943c5f8f1..e99c5097664a6 100644 --- a/_maps/shuttles/ruin_pirate_cutter.dmm +++ b/_maps/shuttles/ruin_pirate_cutter.dmm @@ -344,7 +344,7 @@ "wV" = ( /obj/machinery/light/small/directional/north, /obj/structure/bed, -/obj/item/bedsheet/brown, +/obj/item/bedsheet/pirate, /turf/open/floor/iron/dark, /area/shuttle/ruin/caravan/pirate) "xb" = ( @@ -501,7 +501,7 @@ /obj/structure/bed{ dir = 4 }, -/obj/item/bedsheet/brown{ +/obj/item/bedsheet/pirate{ dir = 4 }, /obj/machinery/airalarm/directional/west, @@ -514,7 +514,7 @@ "Ha" = ( /obj/machinery/light/small/directional/south, /obj/structure/bed, -/obj/item/bedsheet/brown, +/obj/item/bedsheet/pirate, /turf/open/floor/iron/dark, /area/shuttle/ruin/caravan/pirate) "Hb" = ( @@ -838,7 +838,7 @@ /obj/structure/bed{ dir = 4 }, -/obj/item/bedsheet/brown{ +/obj/item/bedsheet/pirate{ dir = 4 }, /obj/machinery/firealarm/directional/west, diff --git a/_maps/shuttles/whiteship_cere.dmm b/_maps/shuttles/whiteship_cere.dmm index e6a677d57c3a5..1f0308690e77d 100644 --- a/_maps/shuttles/whiteship_cere.dmm +++ b/_maps/shuttles/whiteship_cere.dmm @@ -388,7 +388,7 @@ /area/shuttle/abandoned/cargo) "oB" = ( /obj/structure/bed, -/obj/item/bedsheet/random, +/obj/effect/spawner/random/bedsheet/any, /obj/machinery/light/small/directional/east, /obj/effect/decal/cleanable/dirt, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden, diff --git a/_maps/shuttles/whiteship_kilo.dmm b/_maps/shuttles/whiteship_kilo.dmm index 2dc2e1c54d5bc..cbc214f21d828 100644 --- a/_maps/shuttles/whiteship_kilo.dmm +++ b/_maps/shuttles/whiteship_kilo.dmm @@ -1176,7 +1176,7 @@ /obj/structure/bed/pod{ dir = 1 }, -/obj/item/bedsheet/dorms{ +/obj/effect/spawner/random/bedsheet{ dir = 4 }, /obj/effect/decal/cleanable/dirt, diff --git a/_maps/shuttles/whiteship_personalshuttle.dmm b/_maps/shuttles/whiteship_personalshuttle.dmm index e3f432f350b57..8e041082bc6d9 100644 --- a/_maps/shuttles/whiteship_personalshuttle.dmm +++ b/_maps/shuttles/whiteship_personalshuttle.dmm @@ -273,7 +273,7 @@ /area/shuttle/abandoned/bridge) "pS" = ( /obj/machinery/light/small/directional/south, -/obj/item/bedsheet/dorms{ +/obj/effect/spawner/random/bedsheet{ dir = 4 }, /obj/structure/bed/pod{ diff --git a/_maps/templates/hilbertshotel.dmm b/_maps/templates/hilbertshotel.dmm index 2895d10406907..8c425aa9c13db 100644 --- a/_maps/templates/hilbertshotel.dmm +++ b/_maps/templates/hilbertshotel.dmm @@ -76,7 +76,7 @@ /area/misc/hilbertshotel) "q" = ( /obj/structure/bed, -/obj/item/bedsheet/random, +/obj/effect/spawner/random/bedsheet/any, /turf/open/indestructible/hotelwood, /area/misc/hilbertshotel) "r" = ( diff --git a/_maps/templates/hilbertshotellore.dmm b/_maps/templates/hilbertshotellore.dmm index 4774f6788e373..fe77ef9cc3d54 100644 --- a/_maps/templates/hilbertshotellore.dmm +++ b/_maps/templates/hilbertshotellore.dmm @@ -177,7 +177,7 @@ /area/misc/hilbertshotel) "aU" = ( /obj/structure/bed, -/obj/item/bedsheet/random, +/obj/effect/spawner/random/bedsheet/any, /obj/effect/decal/cleanable/dirt, /turf/open/indestructible/hotelwood, /area/misc/hilbertshotel) diff --git a/_maps/virtual_domains/beach_bar.dmm b/_maps/virtual_domains/beach_bar.dmm index 7da71e943d172..6368168416193 100644 --- a/_maps/virtual_domains/beach_bar.dmm +++ b/_maps/virtual_domains/beach_bar.dmm @@ -859,7 +859,7 @@ /turf/open/misc/beach/sand, /area/virtual_domain/fullbright) "Nw" = ( -/obj/item/bedsheet/dorms{ +/obj/effect/spawner/random/bedsheet{ dir = 4 }, /obj/structure/bed{ diff --git a/code/__DEFINES/dcs/signals/signals_camera.dm b/code/__DEFINES/dcs/signals/signals_camera.dm index 6ec142f54fabe..92e9b94f35bba 100644 --- a/code/__DEFINES/dcs/signals/signals_camera.dm +++ b/code/__DEFINES/dcs/signals/signals_camera.dm @@ -1,2 +1,4 @@ -///Signal sent when a /datum/trackable found a target: (datum/trackable/source, mob/living/target) +///Signal sent when a /datum/trackable found a target: (mob/living/target) #define COMSIG_TRACKABLE_TRACKING_TARGET "comsig_trackable_tracking_target" +///Signal sent when the mob a /datum/trackable is actively following changes glide size: mob/living/target, new_glide_size) +#define COMSIG_TRACKABLE_GLIDE_CHANGED "comsig_trackable_glide_changed" diff --git a/code/__DEFINES/random_spawner.dm b/code/__DEFINES/random_spawner.dm new file mode 100644 index 0000000000000..2a012e7904860 --- /dev/null +++ b/code/__DEFINES/random_spawner.dm @@ -0,0 +1,3 @@ +///Used by bedsheets spawners to tell if it's a single or double bedsheet. +#define BEDSHEET_SINGLE "single" +#define BEDSHEET_DOUBLE "double" diff --git a/code/__DEFINES/traits/declarations.dm b/code/__DEFINES/traits/declarations.dm index 9e901b0665faa..5946f76b7a109 100644 --- a/code/__DEFINES/traits/declarations.dm +++ b/code/__DEFINES/traits/declarations.dm @@ -425,6 +425,8 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai #define TRAIT_FOV_APPLIED "fov_applied" /// Mob is using the scope component #define TRAIT_USER_SCOPED "user_scoped" +/// Mob is unable to feel pain +#define TRAIT_ANALGESIA "analgesia" /// Trait added when a revenant is visible. #define TRAIT_REVENANT_REVEALED "revenant_revealed" diff --git a/code/__HELPERS/global_lists.dm b/code/__HELPERS/global_lists.dm index d4a4192614e6c..f7889f0b5af80 100644 --- a/code/__HELPERS/global_lists.dm +++ b/code/__HELPERS/global_lists.dm @@ -25,7 +25,6 @@ init_sprite_accessory_subtypes(/datum/sprite_accessory/wings_open, GLOB.wings_open_list) init_sprite_accessory_subtypes(/datum/sprite_accessory/frills, GLOB.frills_list) init_sprite_accessory_subtypes(/datum/sprite_accessory/spines, GLOB.spines_list) - init_sprite_accessory_subtypes(/datum/sprite_accessory/spines_animated, GLOB.animated_spines_list) init_sprite_accessory_subtypes(/datum/sprite_accessory/tail_spines, GLOB.tail_spines_list) init_sprite_accessory_subtypes(/datum/sprite_accessory/legs, GLOB.legs_list) init_sprite_accessory_subtypes(/datum/sprite_accessory/caps, GLOB.caps_list) diff --git a/code/_globalvars/lists/flavor_misc.dm b/code/_globalvars/lists/flavor_misc.dm index 38072aaec01e7..ce4d847928988 100644 --- a/code/_globalvars/lists/flavor_misc.dm +++ b/code/_globalvars/lists/flavor_misc.dm @@ -26,7 +26,6 @@ GLOBAL_LIST_EMPTY(frills_list) GLOBAL_LIST_EMPTY(spines_list) GLOBAL_LIST_EMPTY(tail_spines_list) GLOBAL_LIST_EMPTY(legs_list) -GLOBAL_LIST_EMPTY(animated_spines_list) //Mutant Human bits GLOBAL_LIST_EMPTY(tails_list_human) diff --git a/code/_globalvars/traits/_traits.dm b/code/_globalvars/traits/_traits.dm index dd074b8d0649b..4bc72354a8625 100644 --- a/code/_globalvars/traits/_traits.dm +++ b/code/_globalvars/traits/_traits.dm @@ -118,6 +118,7 @@ GLOBAL_LIST_INIT(traits_by_type, list( "TRAIT_ALLOW_HERETIC_CASTING" = TRAIT_ALLOW_HERETIC_CASTING, "TRAIT_ALWAYS_NO_ACCESS" = TRAIT_ALWAYS_NO_ACCESS, "TRAIT_ALWAYS_WANTED" = TRAIT_ALWAYS_WANTED, + "TRAIT_ANALGESIA" = TRAIT_ANALGESIA, "TRAIT_ANGELIC" = TRAIT_ANGELIC, "TRAIT_ANTENNAE" = TRAIT_ANTENNAE, "TRAIT_ANTICONVULSANT" = TRAIT_ANTICONVULSANT, @@ -270,13 +271,11 @@ GLOBAL_LIST_INIT(traits_by_type, list( "TRAIT_LIMBATTACHMENT" = TRAIT_LIMBATTACHMENT, "TRAIT_LITERATE" = TRAIT_LITERATE, "TRAIT_LIVERLESS_METABOLISM" = TRAIT_LIVERLESS_METABOLISM, - "TRAIT_LIVERLESS_METABOLISM" = TRAIT_LIVERLESS_METABOLISM, "TRAIT_MADNESS_IMMUNE" = TRAIT_MADNESS_IMMUNE, "TRAIT_MAGICALLY_GIFTED" = TRAIT_MAGICALLY_GIFTED, "TRAIT_MAGICALLY_PHASED" = TRAIT_MAGICALLY_PHASED, "TRAIT_MARTIAL_ARTS_IMMUNE" = TRAIT_MARTIAL_ARTS_IMMUNE, "TRAIT_MEDIBOTCOMINGTHROUGH" = TRAIT_MEDIBOTCOMINGTHROUGH, - "TRAIT_MEDIBOTCOMINGTHROUGH" = TRAIT_MEDIBOTCOMINGTHROUGH, "TRAIT_MEDICAL_HUD" = TRAIT_MEDICAL_HUD, "TRAIT_MESON_VISION" = TRAIT_MESON_VISION, "TRAIT_MIME_FAN" = TRAIT_MIME_FAN, diff --git a/code/_globalvars/traits/admin_tooling.dm b/code/_globalvars/traits/admin_tooling.dm index 01269087d3660..b81719bc808c3 100644 --- a/code/_globalvars/traits/admin_tooling.dm +++ b/code/_globalvars/traits/admin_tooling.dm @@ -113,7 +113,7 @@ GLOBAL_LIST_INIT(admin_visible_traits, list( "TRAIT_LIMBATTACHMENT" = TRAIT_LIMBATTACHMENT, "TRAIT_LITERATE" = TRAIT_LITERATE, "TRAIT_LIVERLESS_METABOLISM" = TRAIT_LIVERLESS_METABOLISM, - "TRAIT_LIVERLESS_METABOLISM" = TRAIT_LIVERLESS_METABOLISM, + "TRAIT_MAGICALLY_GIFTED" = TRAIT_MAGICALLY_GIFTED, "TRAIT_MEDICAL_HUD" = TRAIT_MEDICAL_HUD, "TRAIT_MIME_FAN" = TRAIT_MIME_FAN, "TRAIT_MIMING" = TRAIT_MIMING, diff --git a/code/_onclick/ai.dm b/code/_onclick/ai.dm index 614258388cc1b..8f95bdadda934 100644 --- a/code/_onclick/ai.dm +++ b/code/_onclick/ai.dm @@ -11,7 +11,7 @@ return if(ismob(A)) - ai_tracking_tool.set_tracked_mob(src, A.name) + ai_tracking_tool.track_mob(src, A) else A.move_camera_by_click() diff --git a/code/controllers/master.dm b/code/controllers/master.dm index 6e4c21fba208b..ac12add1ae2d5 100644 --- a/code/controllers/master.dm +++ b/code/controllers/master.dm @@ -684,10 +684,16 @@ GLOBAL_REAL(Master, /datum/controller/master) queue_node.state = SS_RUNNING + if(queue_node.profiler_focused) + world.Profile(PROFILE_START) + tick_usage = TICK_USAGE var/state = queue_node.ignite(queue_node_paused) tick_usage = TICK_USAGE - tick_usage + if(queue_node.profiler_focused) + world.Profile(PROFILE_STOP) + if (state == SS_RUNNING) state = SS_IDLE current_tick_budget -= queue_node_priority diff --git a/code/controllers/subsystem.dm b/code/controllers/subsystem.dm index ddeb9368f500b..b01f4b17b9de4 100644 --- a/code/controllers/subsystem.dm +++ b/code/controllers/subsystem.dm @@ -38,6 +38,12 @@ ///Bitmap of what game states can this subsystem fire at. See [RUNLEVELS_DEFAULT] for more details. var/runlevels = RUNLEVELS_DEFAULT //points of the game at which the SS can fire + /** + * boolean set by admins. if TRUE then this subsystem will stop the world profiler after ignite() returns and start it again when called. + * used so that you can audit a specific subsystem or group of subsystems' synchronous call chain. + */ + var/profiler_focused = FALSE + /* * The following variables are managed by the MC and should not be modified directly. */ @@ -65,7 +71,7 @@ /// Tracks the current execution state of the subsystem. Used to handle subsystems that sleep in fire so the mc doesn't run them again while they are sleeping var/state = SS_IDLE - + /// Tracks how many times a subsystem has ever slept in fire(). var/slept_count = 0 diff --git a/code/controllers/subsystem/polling.dm b/code/controllers/subsystem/polling.dm index 7787d36b2bf4b..8a041eb36b96c 100644 --- a/code/controllers/subsystem/polling.dm +++ b/code/controllers/subsystem/polling.dm @@ -49,7 +49,6 @@ SUBSYSTEM_DEF(polling) if(role && !is_eligible(candidate_mob, role, check_jobban, ignore_category)) continue - SEND_SOUND(candidate_mob, 'sound/misc/notice2.ogg') if(flash_window) window_flash(candidate_mob.client) @@ -116,7 +115,10 @@ SUBSYSTEM_DEF(polling) var/act_never = "" if(ignore_category) act_never = "\[Never For This Round]" - to_chat(candidate_mob, span_boldnotice(examine_block("Now looking for candidates [role_name_text ? "to play as \an [role_name_text]." : "\"[question]\""] [act_jump] [act_signup] [act_never]"))) + + if(!duplicate_message_check(alert_poll)) //Only notify people once. They'll notice if there are multiple and we don't want to spam people. + SEND_SOUND(candidate_mob, 'sound/misc/notice2.ogg') + to_chat(candidate_mob, span_boldnotice(examine_block("Now looking for candidates [role_name_text ? "to play as \an [role_name_text]." : "\"[question]\""] [act_jump] [act_signup] [act_never]"))) // Start processing it so it updates visually the timer START_PROCESSING(SSprocessing, poll_alert_button) @@ -192,13 +194,8 @@ SUBSYSTEM_DEF(polling) // Take care of updating the remaining screen alerts if a similar poll is found, or deleting them. if(length(finishing_poll.alert_buttons)) - var/polls_of_same_type_left = FALSE - for(var/datum/candidate_poll/running_poll as anything in currently_polling) - if(running_poll.poll_key == finishing_poll.poll_key && running_poll.time_left() > 0) - polls_of_same_type_left = TRUE - break for(var/atom/movable/screen/alert/poll_alert/alert as anything in finishing_poll.alert_buttons) - if(polls_of_same_type_left) + if(duplicate_message_check(finishing_poll)) alert.update_stacks_overlay() else alert.owner.clear_alert("[finishing_poll.poll_key]_poll_alert") @@ -213,6 +210,13 @@ SUBSYSTEM_DEF(polling) msg += " | Next: [DisplayTimeText(soonest_to_complete.time_left())] ([length(soonest_to_complete.signed_up)] candidates)" return ..() +///Is there a multiple of the given event type running right now? +/datum/controller/subsystem/polling/proc/duplicate_message_check(datum/candidate_poll/poll_to_check) + for(var/datum/candidate_poll/running_poll as anything in currently_polling) + if((running_poll.poll_key == poll_to_check.poll_key && running_poll != poll_to_check) && running_poll.time_left() > 0) + return TRUE + return FALSE + /datum/controller/subsystem/polling/proc/get_next_poll_to_finish() var/lowest_time_left = INFINITY var/next_poll_to_finish diff --git a/code/datums/achievements/_achievement_data.dm b/code/datums/achievements/_achievement_data.dm index 295770b89b5b7..8b78cf7c8f387 100644 --- a/code/datums/achievements/_achievement_data.dm +++ b/code/datums/achievements/_achievement_data.dm @@ -113,7 +113,7 @@ "name" = award.name, "desc" = award.desc, "category" = award.category, - "icon_class" = assets.icon_class_name(award.icon), + "icon_class" = assets.icon_class_name("achievement-[award.icon_state]"), "value" = data[achievement_type], ) award_data += award.get_ui_data(user.ckey) diff --git a/code/datums/achievements/_awards.dm b/code/datums/achievements/_awards.dm index 23ab5e81001c9..d99659ea780f9 100644 --- a/code/datums/achievements/_awards.dm +++ b/code/datums/achievements/_awards.dm @@ -2,8 +2,10 @@ ///Name of the achievement, If null it won't show up in the achievement browser. (Handy for inheritance trees) var/name var/desc = "You did it." - ///The icon state for this award. The icon file is found in ui_icons/achievements. - var/icon = "default" + ///The dmi icon file that holds the award's icon state. + var/icon = ACHIEVEMENTS_SET + ///The icon state for this award. + var/icon_state = "default" var/category = "Normal" @@ -80,7 +82,7 @@ ///Achievements are one-off awards for usually doing cool things. /datum/award/achievement desc = "Achievement for epic people" - icon = "" // This should warn contributors that do not declare an icon when contributing new achievements. + icon_state = "" // This should warn contributors that do not declare an icon when contributing new achievements. ///How many players have earned this achievement var/times_achieved = 0 @@ -171,7 +173,7 @@ /datum/award/score/achievements_score name = "Achievements Unlocked" desc = "Don't worry, metagaming is all that matters." - icon = "elephant" //Obey the reference + icon_state = "elephant" //Obey the reference database_id = ACHIEVEMENTS_SCORE /datum/award/score/achievements_score/get_ui_data(key) diff --git a/code/datums/achievements/boss_achievements.dm b/code/datums/achievements/boss_achievements.dm index a378b703e46ed..c02286b8f7a58 100644 --- a/code/datums/achievements/boss_achievements.dm +++ b/code/datums/achievements/boss_achievements.dm @@ -5,119 +5,119 @@ name = "Tendril Exterminator" desc = "Watch your step" database_id = BOSS_MEDAL_TENDRIL - icon = "tendril" + icon_state = "tendril" /datum/award/achievement/boss/boss_killer name = "Boss Killer" desc = "You've come a long ways from asking how to switch hands." database_id = "Boss Killer" - icon = "firstboss" + icon_state = "firstboss" /datum/award/achievement/boss/blood_miner_kill name = "Blood-Drunk Miner Killer" desc = "I guess he couldn't handle his drink that well." database_id = BOSS_MEDAL_MINER - icon = "miner" + icon_state = "miner" /datum/award/achievement/boss/demonic_miner_kill name = "Demonic-Frost Miner Killer" desc = "Definitely harder than the Blood-Drunk Miner." database_id = BOSS_MEDAL_FROSTMINER - icon = "frostminer" + icon_state = "frostminer" /datum/award/achievement/boss/bubblegum_kill name = "Bubblegum Killer" desc = "I guess he wasn't made of candy after all" database_id = BOSS_MEDAL_BUBBLEGUM - icon = "bbgum" + icon_state = "bbgum" /datum/award/achievement/boss/colossus_kill name = "Colossus Killer" desc = "The bigger they are... the better the loot" database_id = BOSS_MEDAL_COLOSSUS - icon = "colossus" + icon_state = "colossus" /datum/award/achievement/boss/drake_kill name = "Drake Killer" desc = "Now I can wear Rune Platebodies!" database_id = BOSS_MEDAL_DRAKE - icon = "drake" + icon_state = "drake" /datum/award/achievement/boss/hierophant_kill name = "Hierophant Killer" desc = "Hierophant, but not triumphant." database_id = BOSS_MEDAL_HIEROPHANT - icon = "hierophant" + icon_state = "hierophant" /datum/award/achievement/boss/legion_kill name = "Legion Killer" desc = "We were many..now we are none." database_id = BOSS_MEDAL_LEGION - icon = "legion" + icon_state = "legion" /datum/award/achievement/boss/wendigo_kill name = "Wendigo Killer" desc = "You've now ruined years of mythical storytelling." database_id = BOSS_MEDAL_WENDIGO - icon = "wendigo" + icon_state = "wendigo" /datum/award/achievement/boss/blood_miner_crusher name = "Blood-Drunk Miner Crusher" desc = "I guess he couldn't handle his drink that well." database_id = BOSS_MEDAL_MINER_CRUSHER - icon = "miner" + icon_state = "miner" /datum/award/achievement/boss/demonic_miner_crusher name = "Demonic-Frost Miner Crusher" desc = "Definitely harder than the Blood-Drunk Miner." database_id = BOSS_MEDAL_FROSTMINER_CRUSHER - icon = "frostminer" + icon_state = "frostminer" /datum/award/achievement/boss/bubblegum_crusher name = "Bubblegum Crusher" desc = "I guess he wasn't made of candy after all" database_id = BOSS_MEDAL_BUBBLEGUM_CRUSHER - icon = "bbgum" + icon_state = "bbgum" /datum/award/achievement/boss/colossus_crusher name = "Colossus Crusher" desc = "The bigger they are... the better the loot" database_id = BOSS_MEDAL_COLOSSUS_CRUSHER - icon = "colossus" + icon_state = "colossus" /datum/award/achievement/boss/drake_crusher name = "Drake Crusher" desc = "Now I can wear Rune Platebodies!" database_id = BOSS_MEDAL_DRAKE_CRUSHER - icon = "drake" + icon_state = "drake" /datum/award/achievement/boss/hierophant_crusher name = "Hierophant Crusher" desc = "Hierophant, but not triumphant." database_id = BOSS_MEDAL_HIEROPHANT_CRUSHER - icon = "hierophant" + icon_state = "hierophant" /datum/award/achievement/boss/legion_crusher name = "Legion Crusher" desc = "We were many... now we are none." database_id = BOSS_MEDAL_LEGION_CRUSHER - icon = "legion" + icon_state = "legion" /datum/award/achievement/boss/wendigo_crusher name = "Wendigo Crusher" desc = "You've now ruined years of mythical storytelling." database_id = BOSS_MEDAL_WENDIGO_CRUSHER - icon = "wendigo" + icon_state = "wendigo" //should be removed soon /datum/award/achievement/boss/king_goat_kill name = "King Goat Killer" desc = "The king is dead, long live the king!" database_id = BOSS_MEDAL_KINGGOAT - icon = "goatboss" + icon_state = "goatboss" /datum/award/achievement/boss/king_goat_crusher name = "King Goat Crusher" desc = "The king is dead, long live the king!" database_id = BOSS_MEDAL_KINGGOAT_CRUSHER - icon = "goatboss" + icon_state = "goatboss" diff --git a/code/datums/achievements/job_achievements.dm b/code/datums/achievements/job_achievements.dm index 6aafbee8e68d1..bd37de7c0e112 100644 --- a/code/datums/achievements/job_achievements.dm +++ b/code/datums/achievements/job_achievements.dm @@ -8,7 +8,7 @@ name = "All Within Theoretical Limits" desc = "I never thought I'd see a resonance cascade, let alone prevent one..." database_id = MEDAL_THEORETICAL_LIMITS - icon = "theoreticallimits" + icon_state = "theoreticallimits" //medical @@ -16,13 +16,13 @@ name = "Mister Sandman" desc = "Mechanically speaking, there's no real benefit to being unconscious during surgery. Weird how insistent this doctor is about using the N2O anyway though, huh?" database_id = MEDAL_SANDMAN - icon = "basemisc" + icon_state = "basemisc" /datum/award/achievement/jobs/helbitaljanken name = "Helbitaljanken" desc = "You janked hard" database_id = MEDAL_HELBITALJANKEN - icon = "helbital" + icon_state = "helbital" //mining @@ -30,7 +30,7 @@ name = "Frenching" desc = "Just a taste, for science!" database_id = MEDAL_FRENCHING - icon = "frenchingthebubble" + icon_state = "frenchingthebubble" //science @@ -38,13 +38,13 @@ name = "Feat of Strength" desc = "If the rod is immovable, is it passing you or are you passing it?" database_id = MEDAL_RODSUPLEX - icon = "featofstrength" + icon_state = "featofstrength" /datum/award/achievement/jobs/snail name = "KKKiiilll mmmeee" desc = "You were a little too ambitious, but hey, I guess you're still alive?" database_id = MEDAL_SNAIL - icon = "snail" + icon_state = "snail" //all of service! hip hip! @@ -52,18 +52,18 @@ name = "Centcom Grade: Shitty Service" desc = "Well, you at least tried. How about trying harder?" database_id = MEDAL_BAD_SERVICE - icon = "service_bad" + icon_state = "service_bad" /datum/award/achievement/jobs/service_okay name = "Centcom Grade: Acceptable Service" desc = "Well, it'll do! You and your department did just fine." database_id = MEDAL_OKAY_SERVICE - icon = "service_okay" + icon_state = "service_okay" /datum/award/achievement/jobs/service_good name = "Centcom Grade: Exemplary Service" desc = "Centcom is very impressed with your department!" database_id = MEDAL_GOOD_SERVICE - icon = "service_good" + icon_state = "service_good" //civilian achievies! while not recognized by the code, it is recognized by our hearts diff --git a/code/datums/achievements/mafia_achievements.dm b/code/datums/achievements/mafia_achievements.dm index da70fb11e871f..31462f7a0ce2f 100644 --- a/code/datums/achievements/mafia_achievements.dm +++ b/code/datums/achievements/mafia_achievements.dm @@ -7,103 +7,103 @@ name = "Assistant Victory" desc = "If you got killed instead of someone more important, you just flexed the true strength of your \"\"\"\"role\"\"\"\"." database_id = MAFIA_MEDAL_ASSISTANT - icon = "town" + icon_state = "town" /datum/award/achievement/mafia/detective name = "Detective Victory" desc = "If you did this with a Medical Doctor in the game, i'm not really that impressed." database_id = MAFIA_MEDAL_DETECTIVE - icon = "town" + icon_state = "town" /datum/award/achievement/mafia/psychologist name = "Psychologist Victory" desc = "You learned how to not reveal someone random night one! Or... maybe you're just a lucky bastard." database_id = MAFIA_MEDAL_PSYCHOLOGIST - icon = "town" + icon_state = "town" /datum/award/achievement/mafia/chaplain name = "Chaplain Victory" desc = "Useless... until the one night the thoughtfeeder confidently claims themselves as detective. Mafia's true bullshit detector." database_id = MAFIA_MEDAL_CHAPLAIN - icon = "town" + icon_state = "town" /datum/award/achievement/mafia/md name = "Medical Doctor Victory" desc = "Congratulations on learning how to not talk!" database_id = MAFIA_MEDAL_MD - icon = "town" + icon_state = "town" /datum/award/achievement/mafia/officer name = "Security Officer Victory" desc = "Don't worry, you can win this if you're dead! You... did use your ability to become dead, right?" database_id = MAFIA_MEDAL_OFFICER - icon = "town" + icon_state = "town" /datum/award/achievement/mafia/lawyer name = "Lawyer Victory" desc = "Oh don't mind me, i'm just the worst rol- Oops, I just instantly ended the game." database_id = MAFIA_MEDAL_LAWYER - icon = "town" + icon_state = "town" /datum/award/achievement/mafia/hop name = "Head of Personnel Victory" desc = "King of Assistants, waster of a single mafia's night, thrower of games." database_id = MAFIA_MEDAL_HOP - icon = "town" + icon_state = "town" /datum/award/achievement/mafia/warden name = "Warden Victory" desc = "Make changelings think you're detective, go on lockdown, actual detective investigates you and dies. Cha cha real smooth!" database_id = MAFIA_MEDAL_WARDEN - icon = "town" + icon_state = "town" /datum/award/achievement/mafia/hos name = "Head of Security Victory" desc = "Certified not shitcurity." database_id = MAFIA_MEDAL_HOS - icon = "town" + icon_state = "town" /datum/award/achievement/mafia/changeling name = "Changeling Victory" desc = "I think the changelings are metacomming." database_id = MAFIA_MEDAL_CHANGELING - icon = "mafia" + icon_state = "mafia" /datum/award/achievement/mafia/thoughtfeeder name = "Thoughtfeeder Victory" desc = "Clown's best friend. And Obsessed. And fugitive? Whose side are you on?!" database_id = MAFIA_MEDAL_THOUGHTFEEDER - icon = "mafia" + icon_state = "mafia" /datum/award/achievement/mafia/traitor name = "Traitor Victory" desc = "Guys, we still have two more changelings to ki-!! TRAITOR VICTORY !!" database_id = MAFIA_MEDAL_TRAITOR - icon = "neutral" + icon_state = "neutral" /datum/award/achievement/mafia/nightmare name = "Nightmare Victory" desc = "DID YOUR LIGHT FLICKER?!" database_id = MAFIA_MEDAL_NIGHTMARE - icon = "neutral" + icon_state = "neutral" /datum/award/achievement/mafia/fugitive name = "Fugitive Victory" desc = "I'm just the description on an achievement, but if you end up having to choose between town and changelings, go changelings." database_id = MAFIA_MEDAL_FUGITIVE - icon = "neutral" + icon_state = "neutral" /datum/award/achievement/mafia/obsessed name = "Obsessed Victory" desc = "You got your target lynched, so instead of being spiteful and annoying, you're just smug and annoying." database_id = MAFIA_MEDAL_OBSESSED - icon = "neutral" + icon_state = "neutral" /datum/award/achievement/mafia/clown name = "Clown Victory" desc = "Did you know this works on traitors, despite their immunity? If you hit the jackpot and manage to kill one, they'll salt into the next dimension. Clown tips!" database_id = MAFIA_MEDAL_CLOWN - icon = "neutral" + icon_state = "neutral" ///ALL THE ACHIEVEMENTS FOR MISC MAFIA ODDITIES/// @@ -111,4 +111,4 @@ name = "Universally Hated" desc = "Managed to get more than 12 votes when put up on trial, jesus christ." database_id = MAFIA_MEDAL_HATED - icon = "hated" + icon_state = "hated" diff --git a/code/datums/achievements/misc_achievements.dm b/code/datums/achievements/misc_achievements.dm index e452b860f0072..e92fc3bc56b91 100644 --- a/code/datums/achievements/misc_achievements.dm +++ b/code/datums/achievements/misc_achievements.dm @@ -1,54 +1,54 @@ /datum/award/achievement/misc category = "Misc" - icon = "basemisc" //for those achievements that still need an actual icon, later. + icon_state = "basemisc" //for those achievements that still need an actual icon, later. /datum/award/achievement/misc/meteor_examine name = "Your Life Before Your Eyes" desc = "Take a close look at hurtling space debris" database_id = MEDAL_METEOR - icon = "meteors" + icon_state = "meteors" /datum/award/achievement/misc/pulse name = "Jackpot" desc = "Win a pulse rifle from an arcade machine" database_id = MEDAL_PULSE - icon = "jackpot" + icon_state = "jackpot" /datum/award/achievement/misc/time_waste name = "Time waster" desc = "Speak no evil, hear no evil, see just errors" database_id = MEDAL_TIMEWASTE - icon = "timewaste" + icon_state = "timewaste" /datum/award/achievement/misc/round_and_full name = "Round and Full" desc = "Well at least you aren't down the river, I hear they eat people there." database_id = MEDAL_CLOWNCARKING - icon = "clownking" + icon_state = "clownking" /datum/award/achievement/misc/the_best_driver name = "The Best Driver" desc = "100 honks later" database_id = MEDAL_THANKSALOT - icon = "clownthanks" + icon_state = "clownthanks" /datum/award/achievement/misc/getting_an_upgrade name = "Getting an upgrade" desc = "Make your first unique material item!" database_id = MEDAL_MATERIALCRAFT - icon = "upgrade" + icon_state = "upgrade" /datum/award/achievement/misc/rocket_holdup name = "Disk, Please!" desc = "Is the man currently pointing a loaded rocket launcher at your head point blank really dumb enough to pull the trigger? Do you really want to find out?" database_id = MEDAL_DISKPLEASE - icon = "rocket_holdup" + icon_state = "rocket_holdup" /datum/award/achievement/misc/gamer name = "My Watchlist Status is Not Important" desc = "You may be under the impression that violent video games are a harmless pastime, but the security and medical personnel swarming your location with batons and knockout gas look like they disagree." database_id = MEDAL_GAMER - icon = "live_sec_reaction" + icon_state = "live_sec_reaction" /datum/award/achievement/misc/vendor_squish name = "I Was a Teenage Anarchist" @@ -69,161 +69,161 @@ name = "One Lean, Mean, Cleaning Machine" desc = "How does it feel to know that your workplace values a mop bucket on wheels more than you?" // i can do better than this give me time database_id = MEDAL_CLEANBOSS - icon = "cleanboss" + icon_state = "cleanboss" /datum/award/achievement/misc/rule8 name = "Rule 8" desc = "Call an admin this is ILLEGAL!!" database_id = MEDAL_RULE8 - icon = "rule8" + icon_state = "rule8" /datum/award/achievement/misc/speed_round name = "Long shift" desc = "Well, that didn't take long." database_id = MEDAL_LONGSHIFT - icon = "longshift" + icon_state = "longshift" /datum/award/achievement/misc/lookoutsir name = "Look Out, Sir!" desc = "Either awarded for making the ultimate sacrifice for your comrades, or a really dumb attempt at grenade jumping." database_id = MEDAL_LOOKOUTSIR - icon = "martyr" // purple heart on an explosive danger warning sign (well, sort of) + icon_state = "martyr" // purple heart on an explosive danger warning sign (well, sort of) /datum/award/achievement/misc/gottem name = "HA, GOTTEM" desc = "Made you look!" database_id = MEDAL_GOTTEM - icon = "gottem" + icon_state = "gottem" /datum/award/achievement/misc/ascension name = "Ascension" desc = "Caedite eos. Novit enim Dominus qui sunt eius." database_id = MEDAL_ASCENSION - icon = "ascension" + icon_state = "ascension" /datum/award/achievement/misc/ash_ascension name = "Nightwatcher's Eyes" desc = "You've risen above the flames, became one with the ashes. You've been reborn as one with the Nightwatcher." database_id = MEDAL_ASH_ASCENSION - icon = "ashascend" + icon_state = "ashascend" /datum/award/achievement/misc/flesh_ascension name = "Vortex of Arms" desc = "You've became something more, something greater. A piece of the emperor resides within you, and you within him." database_id = MEDAL_FLESH_ASCENSION - icon = "fleshascend" + icon_state = "fleshascend" /datum/award/achievement/misc/rust_ascension name = "Hills of Rust" desc = "You've summoned a piece of the Hill of rust, and so the Hills welcome you." database_id = MEDAL_RUST_ASCENSION - icon = "rustascend" + icon_state = "rustascend" /datum/award/achievement/misc/void_ascension name = "All that perish" desc = "Place of a different being, different time. Everything ends there... but maybe it is just the beginning?" database_id = MEDAL_VOID_ASCENSION - icon = "voidascend" + icon_state = "voidascend" /datum/award/achievement/misc/blade_ascension name = "Silver and Steel" desc = "You've become the master of all duellists - the paragon of blades." database_id = MEDAL_BLADE_ASCENSION - icon = "bladeascend" + icon_state = "bladeascend" /datum/award/achievement/misc/cosmic_ascension name = "It arrived" desc = "You managed to teleport an entity on the station that really shouldn't be there." database_id = MEDAL_COSMOS_ASCENSION - icon = "cosmicascend" + icon_state = "cosmicascend" /datum/award/achievement/misc/lock_ascension name = "Secrets of the Locked Labyrinth" desc = "You managed to open a gate into the mansus." database_id = MEDAL_LOCK_ASCENSION - icon = "lockascend" + icon_state = "lockascend" /datum/award/achievement/misc/moon_ascension name = "The Last Act" desc = "You managed to become the ringleader and slay the lie." database_id = MEDAL_MOON_ASCENSION - icon = "moonascend" + icon_state = "moonascend" /datum/award/achievement/misc/grand_ritual_finale name = "Archmage" desc = "Made a big impression on the station with your phenomenal cosmic power." database_id = MEDAL_ARCHMAGE - icon = "archmage" + icon_state = "archmage" /datum/award/achievement/misc/toolbox_soul name = "SOUL'd Out" desc = "My eternal soul was destroyed to make a toolbox look funny and all I got was this achievement..." database_id = MEDAL_TOOLBOX_SOUL - icon = "toolbox_soul" + icon_state = "toolbox_soul" /datum/award/achievement/misc/hot_damn name = "Hot Damn!" desc = "Sometimes you need to make some noise to make a point." database_id = MEDAL_HOT_DAMN - icon = "hotdamn" + icon_state = "hotdamn" /datum/award/achievement/misc/cayenne_disk name = "Very Important Piscis" desc = "You can rest well now." database_id = MEDAL_CAYENNE_DISK - icon = "cayenne_disk" + icon_state = "cayenne_disk" /datum/award/achievement/misc/tram_surfer name = "Tram Surfer" desc = "Lights out, guerilla radio!" database_id = MEDAL_TRAM_SURFER - icon = "tram_surfer" + icon_state = "tram_surfer" /datum/award/achievement/misc/cult_shuttle_omfg name = "WHAT JUST HAPPENED" desc = "As a blood cultist, be part of a team that summons 3 shuttle curses within 10 seconds. Imagine cleaning up after them, g r o s s!" database_id = MEDAL_CULT_SHUTTLE_OMFG - icon = "cult_shuttle_omfg" + icon_state = "cult_shuttle_omfg" /datum/award/achievement/misc/clickbait name = "Clickbait" desc = "Where's my free smartphone?!?" database_id = MEDAL_CLICKBAIT - icon = "bait" + icon_state = "bait" /datum/award/achievement/misc/narsupreme name = "If Nar'Sie is so good, why isn't there a..." desc = "Even interdimensional space deitys need a friend." database_id = MEDAL_NARSUPREME - icon = "narsupreme" + icon_state = "narsupreme" /datum/award/achievement/misc/springlock name = "The Man Inside the MODsuit" desc = "Ignore the warning label on a springlock MODsuit." database_id = MEDAL_SPRINGLOCK - icon = "springlock" + icon_state = "springlock" /datum/award/achievement/misc/healthy name = "The Picture of Health" desc = "Don't be such a baby, it's just a heart attack. You've bounced back from worse!" database_id = MEDAL_HEALTHY - icon = "picofhealth" + icon_state = "picofhealth" /datum/award/achievement/misc/gods_wrath name = "God's Wrath" desc = "Did you think you could get away with defiling the word of God?" database_id = MEDAL_GODS_WRATH - icon = "godswrath" + icon_state = "godswrath" /datum/award/achievement/misc/earthquake_victim name = "A Nasty Fall" desc = "...And the earth opened its mouth and swallowed them and their station- all the HOP's men and all their possessions." database_id = MEDAL_EARTHQUAKE_VICTIM - icon = "earthquake" + icon_state = "earthquake" /datum/award/achievement/misc/debt_extinguished name = "Outdebted" desc = "I've paid my dues, shift after shift... I've done my sentence but commited no griff..." database_id = MEDAL_DEBT_EXTINGUISHED - icon = "outdebted" + icon_state = "outdebted" diff --git a/code/datums/achievements/skill_achievements.dm b/code/datums/achievements/skill_achievements.dm index 6384b1b3db4ad..7e2f3f1a24742 100644 --- a/code/datums/achievements/skill_achievements.dm +++ b/code/datums/achievements/skill_achievements.dm @@ -5,10 +5,10 @@ name = "Legendary miner" desc = "No mere rock can stop me!" database_id = MEDAL_LEGENDARY_MINER - icon = "mining" + icon_state = "mining" /datum/award/achievement/skill/legendary_fisher name = "Legendary fisher" desc = "Give a spaceman a fish and you feed him for a while; teach a spaceman to fish and you feed him until the shuttle arrives." database_id = MEDAL_LEGENDARY_FISHER - icon = "fishing_hat" + icon_state = "fishing_hat" diff --git a/code/datums/brain_damage/special.dm b/code/datums/brain_damage/special.dm index 651881292e9c7..e24ecd99c6177 100644 --- a/code/datums/brain_damage/special.dm +++ b/code/datums/brain_damage/special.dm @@ -267,11 +267,11 @@ lose_text = span_warning("You realize you can feel pain again.") /datum/brain_trauma/special/tenacity/on_gain() - owner.add_traits(list(TRAIT_NOSOFTCRIT, TRAIT_NOHARDCRIT), TRAUMA_TRAIT) + owner.add_traits(list(TRAIT_NOSOFTCRIT, TRAIT_NOHARDCRIT, TRAIT_ANALGESIA), TRAUMA_TRAIT) ..() /datum/brain_trauma/special/tenacity/on_lose() - owner.remove_traits(list(TRAIT_NOSOFTCRIT, TRAIT_NOHARDCRIT), TRAUMA_TRAIT) + owner.remove_traits(list(TRAIT_NOSOFTCRIT, TRAIT_NOHARDCRIT, TRAIT_ANALGESIA), TRAUMA_TRAIT) ..() /datum/brain_trauma/special/death_whispers diff --git a/code/datums/components/jetpack.dm b/code/datums/components/jetpack.dm index 3e0fd28ed8013..437660abc82e0 100644 --- a/code/datums/components/jetpack.dm +++ b/code/datums/components/jetpack.dm @@ -116,7 +116,7 @@ return if(user.throwing)//You don't must use jet if you thrown return - if(length(user.client.keys_held & user.client.movement_keys))//You use jet when press keys. yes. + if(user.client.intended_direction)//You use jet when press keys. yes. thrust() /datum/component/jetpack/proc/pre_move_react(mob/user) diff --git a/code/datums/components/material/material_container.dm b/code/datums/components/material/material_container.dm index b69ae91825ea8..69f67d46df3a8 100644 --- a/code/datums/components/material/material_container.dm +++ b/code/datums/components/material/material_container.dm @@ -275,10 +275,9 @@ var/inserted = 0 //All messages to be displayed to chat var/list/chat_msgs = list() - //differs from held_item when using TK var/active_held = user.get_active_held_item() - + //storage items to retrive items from var/static/list/storage_items if(isnull(storage_items)) storage_items = list( @@ -288,7 +287,7 @@ ) //1st iteration consumes all items that do not have contents inside - //2nd iteration consumes items who do have contents inside(but they were consumed in the 1st iteration si its empty now) + //2nd iteration consumes items who do have contents inside(but they were consumed in the 1st iteration so its empty now) for(var/i in 1 to 2) //no point inserting more items if(inserted == MATERIAL_INSERT_ITEM_NO_SPACE) @@ -311,15 +310,11 @@ //can't allow abstract, hologram items if((target_item.item_flags & ABSTRACT) || (target_item.flags_1 & HOLOGRAM_1)) continue - //untouchable, move it out the way, code copied from recycler - if(target_item.resistance_flags & INDESTRUCTIBLE) - target_item.forceMove(get_turf(parent)) - continue //user defined conditions if(SEND_SIGNAL(src, COMSIG_MATCONTAINER_PRE_USER_INSERT, target_item, user) & MATCONTAINER_BLOCK_INSERT) continue - //item is either not allowed for redemption, not in the allowed types - if((target_item.item_flags & NO_MAT_REDEMPTION) || (allowed_item_typecache && !is_type_in_typecache(target_item, allowed_item_typecache))) + //item is either indestructible, not allowed for redemption or not in the allowed types + if((target_item.resistance_flags & INDESTRUCTIBLE) || (target_item.item_flags & NO_MAT_REDEMPTION) || (allowed_item_typecache && !is_type_in_typecache(target_item, allowed_item_typecache))) if(!(mat_container_flags & MATCONTAINER_SILENT) && i == 1) //count only child items the 1st time around var/list/status_data = chat_msgs["[MATERIAL_INSERT_ITEM_FAILURE]"] || list() var/list/item_data = status_data[target_item.name] || list() @@ -327,6 +322,10 @@ status_data[target_item.name] = item_data chat_msgs["[MATERIAL_INSERT_ITEM_FAILURE]"] = status_data + if(target_item.resistance_flags & INDESTRUCTIBLE) + if(i == 1 && target_item != active_held) //move it out of any storage medium its in so it doesn't get consumed with its parent, but only if that storage medium is not our hand + target_item.forceMove(get_turf(context)) + continue //storage items usually come here but we make the exception only on the 1st iteration //this is so players can insert items from their bags into machines for convinience if(!is_type_in_list(target_item, storage_items)) diff --git a/code/datums/components/scope.dm b/code/datums/components/scope.dm index b413b6f8e51ac..531ff9e9962df 100644 --- a/code/datums/components/scope.dm +++ b/code/datums/components/scope.dm @@ -60,7 +60,7 @@ stop_zooming(user_mob) return tracker.calculate_params() - if(!length(user_client.keys_held & user_client.movement_keys)) + if(!user_client.intended_direction) user_mob.face_atom(tracker.given_turf) animate(user_client, world.tick_lag, pixel_x = tracker.given_x, pixel_y = tracker.given_y) diff --git a/code/datums/helper_datums/teleport.dm b/code/datums/helper_datums/teleport.dm index bee48a2bb4936..b979c9cda0f5c 100644 --- a/code/datums/helper_datums/teleport.dm +++ b/code/datums/helper_datums/teleport.dm @@ -70,6 +70,9 @@ teleatom.balloon_alert(teleatom, "something holds you back!") return FALSE + SEND_SIGNAL(teleatom, COMSIG_MOVABLE_TELEPORTED, destination, channel) + SEND_SIGNAL(destturf, COMSIG_ATOM_INTERCEPT_TELEPORTED, channel, curturf, destturf) + if(isobserver(teleatom)) teleatom.abstract_move(destturf) return TRUE @@ -85,7 +88,7 @@ teleatom.log_message("teleported from [loc_name(curturf)] to [loc_name(destturf)].", LOG_GAME, log_globally = FALSE) M.cancel_camera() - SEND_SIGNAL(teleatom, COMSIG_MOVABLE_POST_TELEPORT) + SEND_SIGNAL(teleatom, COMSIG_MOVABLE_POST_TELEPORT, destination, channel) return TRUE @@ -209,7 +212,4 @@ if(SEND_SIGNAL(destination_turf, COMSIG_ATOM_INTERCEPT_TELEPORTING, channel, origin_turf, destination_turf) & COMPONENT_BLOCK_TELEPORT) return FALSE - SEND_SIGNAL(teleported_atom, COMSIG_MOVABLE_TELEPORTED, destination, channel) - SEND_SIGNAL(destination_turf, COMSIG_ATOM_INTERCEPT_TELEPORTED, channel, origin_turf, destination_turf) - return TRUE diff --git a/code/datums/martial/krav_maga.dm b/code/datums/martial/krav_maga.dm index cda53bbe6475e..1710009de3c6e 100644 --- a/code/datums/martial/krav_maga.dm +++ b/code/datums/martial/krav_maga.dm @@ -102,6 +102,8 @@ /datum/martial_art/krav_maga/proc/leg_sweep(mob/living/attacker, mob/living/defender) if(defender.stat != CONSCIOUS || defender.IsParalyzed()) return MARTIAL_ATTACK_INVALID + if(HAS_TRAIT(attacker, TRAIT_PACIFISM)) + return MARTIAL_ATTACK_INVALID // Does 5 damage, so we can't let pacifists leg sweep. defender.visible_message( span_warning("[attacker] leg sweeps [defender]!"), span_userdanger("Your legs are sweeped by [attacker]!"), @@ -134,6 +136,8 @@ return MARTIAL_ATTACK_SUCCESS /datum/martial_art/krav_maga/proc/neck_chop(mob/living/attacker, mob/living/defender) + if(HAS_TRAIT(attacker, TRAIT_PACIFISM)) + return MARTIAL_ATTACK_INVALID // Does 10 damage, so we can't let pacifists neck chop. attacker.do_attack_animation(defender) defender.visible_message( span_warning("[attacker] karate chops [defender]'s neck!"), diff --git a/code/datums/mood_events/generic_negative_events.dm b/code/datums/mood_events/generic_negative_events.dm index afcb5d688ed60..32b9772dc0709 100644 --- a/code/datums/mood_events/generic_negative_events.dm +++ b/code/datums/mood_events/generic_negative_events.dm @@ -92,6 +92,12 @@ mood_change = -3 timeout = 2 MINUTES +/datum/mood_event/reattachment/New(mob/M, ...) + if(HAS_TRAIT(M, TRAIT_ANALGESIA)) + qdel(src) + return + return ..() + /datum/mood_event/reattachment/add_effects(obj/item/bodypart/limb) if(limb) description = "Ouch! My [limb.plaintext_zone] feels like I fell asleep on it." @@ -122,6 +128,12 @@ mood_change = -3 timeout = 3 MINUTES +/datum/mood_event/table_limbsmash/New(mob/M, ...) + if(HAS_TRAIT(M, TRAIT_ANALGESIA)) + qdel(src) + return + return ..() + /datum/mood_event/table_limbsmash/add_effects(obj/item/bodypart/banged_limb) if(banged_limb) description = "My fucking [banged_limb.plaintext_zone], man that hurts..." @@ -194,6 +206,12 @@ mood_change = -5 timeout = 60 SECONDS +/datum/mood_event/painful_medicine/New(mob/M, ...) + if(HAS_TRAIT(M, TRAIT_ANALGESIA)) + qdel(src) + return + return ..() + /datum/mood_event/spooked description = "The rattling of those bones... It still haunts me." mood_change = -4 @@ -231,6 +249,12 @@ description = "Bags never sit right on my back, this hurts like hell!" mood_change = -15 +/datum/mood_event/back_pain/New(mob/M, ...) + if(HAS_TRAIT(M, TRAIT_ANALGESIA)) + qdel(src) + return + return ..() + /datum/mood_event/sad_empath description = "Someone seems upset..." mood_change = -1 diff --git a/code/datums/quirks/negative_quirks/all_nighter.dm b/code/datums/quirks/negative_quirks/all_nighter.dm index 798add0539f24..253ce12b41f32 100644 --- a/code/datums/quirks/negative_quirks/all_nighter.dm +++ b/code/datums/quirks/negative_quirks/all_nighter.dm @@ -14,7 +14,7 @@ mail_goodies = list( /obj/item/clothing/glasses/blindfold, - /obj/item/bedsheet/random, + /obj/effect/spawner/random/bedsheet/any, /obj/item/clothing/under/misc/pj/red, /obj/item/clothing/head/costume/nightcap/red, /obj/item/clothing/under/misc/pj/blue, diff --git a/code/datums/sprite_accessories.dm b/code/datums/sprite_accessories.dm index bf4da0d98ea8f..2f433b8e340fb 100644 --- a/code/datums/sprite_accessories.dm +++ b/code/datums/sprite_accessories.dm @@ -2076,10 +2076,6 @@ icon = 'icons/mob/human/species/lizard/lizard_spines.dmi' em_block = TRUE -/datum/sprite_accessory/spines_animated - icon = 'icons/mob/human/species/lizard/lizard_spines.dmi' - em_block = TRUE - /datum/sprite_accessory/tail_spines icon = 'icons/mob/human/species/lizard/lizard_spines.dmi' em_block = TRUE @@ -2088,10 +2084,6 @@ name = "None" icon_state = "none" -/datum/sprite_accessory/spines_animated/none - name = "None" - icon_state = "none" - /datum/sprite_accessory/tail_spines/none name = "None" icon_state = "none" @@ -2100,10 +2092,6 @@ name = "Short" icon_state = "short" -/datum/sprite_accessory/spines_animated/short - name = "Short" - icon_state = "short" - /datum/sprite_accessory/tail_spines/short name = "Short" icon_state = "short" @@ -2112,10 +2100,6 @@ name = "Short + Membrane" icon_state = "shortmeme" -/datum/sprite_accessory/spines_animated/shortmeme - name = "Short + Membrane" - icon_state = "shortmeme" - /datum/sprite_accessory/tail_spines/shortmeme name = "Short + Membrane" icon_state = "shortmeme" @@ -2124,10 +2108,6 @@ name = "Long" icon_state = "long" -/datum/sprite_accessory/spines_animated/long - name = "Long" - icon_state = "long" - /datum/sprite_accessory/tail_spines/long name = "Long" icon_state = "long" @@ -2136,10 +2116,6 @@ name = "Long + Membrane" icon_state = "longmeme" -/datum/sprite_accessory/spines_animated/longmeme - name = "Long + Membrane" - icon_state = "longmeme" - /datum/sprite_accessory/tail_spines/longmeme name = "Long + Membrane" icon_state = "longmeme" @@ -2148,10 +2124,6 @@ name = "Aquatic" icon_state = "aqua" -/datum/sprite_accessory/spines_animated/aquatic - name = "Aquatic" - icon_state = "aqua" - /datum/sprite_accessory/tail_spines/aquatic name = "Aquatic" icon_state = "aqua" diff --git a/code/datums/wounds/bones.dm b/code/datums/wounds/bones.dm index 80c1c0a755713..9911a7cdd5de0 100644 --- a/code/datums/wounds/bones.dm +++ b/code/datums/wounds/bones.dm @@ -413,22 +413,11 @@ user.visible_message(span_notice("[user] finishes applying [I] to [victim]'s [limb.plaintext_zone], emitting a fizzing noise!"), span_notice("You finish applying [I] to [victim]'s [limb.plaintext_zone]!"), ignored_mobs=victim) to_chat(victim, span_userdanger("[user] finishes applying [I] to your [limb.plaintext_zone], and you can feel the bones exploding with pain as they begin melting and reforming!")) else - var/painkiller_bonus = 0 - if(victim.get_drunk_amount() > 10) - painkiller_bonus += 10 - if(victim.reagents.has_reagent(/datum/reagent/medicine/morphine)) - painkiller_bonus += 20 - if(victim.reagents.has_reagent(/datum/reagent/determination)) - painkiller_bonus += 10 - if(victim.reagents.has_reagent(/datum/reagent/consumable/ethanol/painkiller)) - painkiller_bonus += 15 - if(victim.reagents.has_reagent(/datum/reagent/medicine/mine_salve)) - painkiller_bonus += 20 - - if(prob(25 + (20 * (severity - 2)) - painkiller_bonus)) // 25%/45% chance to fail self-applying with severe and critical wounds, modded by painkillers - victim.visible_message(span_danger("[victim] fails to finish applying [I] to [victim.p_their()] [limb.plaintext_zone], passing out from the pain!"), span_notice("You pass out from the pain of applying [I] to your [limb.plaintext_zone] before you can finish!")) - victim.AdjustUnconscious(5 SECONDS) - return TRUE + if(!HAS_TRAIT(victim, TRAIT_ANALGESIA)) + if(prob(25 + (20 * (severity - 2)) - min(victim.get_drunk_amount(), 10))) // 25%/45% chance to fail self-applying with severe and critical wounds, modded by drunkenness + victim.visible_message(span_danger("[victim] fails to finish applying [I] to [victim.p_their()] [limb.plaintext_zone], passing out from the pain!"), span_notice("You pass out from the pain of applying [I] to your [limb.plaintext_zone] before you can finish!")) + victim.AdjustUnconscious(5 SECONDS) + return TRUE victim.visible_message(span_notice("[victim] finishes applying [I] to [victim.p_their()] [limb.plaintext_zone], grimacing from the pain!"), span_notice("You finish applying [I] to your [limb.plaintext_zone], and your bones explode in pain!")) limb.receive_damage(25, wound_bonus=CANT_WOUND) diff --git a/code/game/atom/alternate_appearance.dm b/code/game/atom/alternate_appearance.dm index e22e5c8951995..228462f7936a4 100644 --- a/code/game/atom/alternate_appearance.dm +++ b/code/game/atom/alternate_appearance.dm @@ -166,7 +166,7 @@ GLOBAL_LIST_EMPTY(active_alternate_appearances) return TRUE return FALSE -/datum/atom_hud/alternate_appearance/basic/one_person/New(key, image/I, options, mob/living/seer) +/datum/atom_hud/alternate_appearance/basic/one_person/New(key, image/I, options = NONE, mob/living/seer) src.seer = seer return ..() diff --git a/code/game/machinery/camera/trackable.dm b/code/game/machinery/camera/trackable.dm index 884f38f750bc5..b1c4b46da4b19 100644 --- a/code/game/machinery/camera/trackable.dm +++ b/code/game/machinery/camera/trackable.dm @@ -2,13 +2,13 @@ #define CAMERA_TICK_LIMIT 10 /datum/trackable - ///Boolean on whether or not we are currently trying to track something. - var/tracking = FALSE ///Reference to the atom that owns us, used for tracking. var/atom/tracking_holder - ///If there is a mob currently being tracked, this will be the weakref to it. - var/datum/weakref/tracked_mob + ///What mob are we currently tracking, if any + var/mob/living/tracked_mob + ///If we're currently rechecking our target's trackability in hopes of something changing + var/rechecking = FALSE ///How many times we've failed to locate our target. var/cameraticks = 0 @@ -24,7 +24,7 @@ /datum/trackable/New(atom/source) . = ..() tracking_holder = source - RegisterSignal(tracking_holder, COMSIG_MOB_RESET_PERSPECTIVE, PROC_REF(cancel_target_tracking)) + RegisterSignal(tracking_holder, COMSIG_MOB_RESET_PERSPECTIVE, PROC_REF(perspective_reset)) /datum/trackable/Destroy(force) tracking_holder = null @@ -32,27 +32,6 @@ STOP_PROCESSING(SSprocessing, src) return ..() -/datum/trackable/process() - var/mob/living/tracked_target = tracked_mob?.resolve() - if(!tracked_target || !tracking) - set_tracking(FALSE) - return - - if(tracked_target.can_track(tracking_holder)) - cameraticks = initial(cameraticks) - SEND_SIGNAL(tracking_holder, COMSIG_TRACKABLE_TRACKING_TARGET, tracked_target) - return - - if(cameraticks < CAMERA_TICK_LIMIT) - if(!cameraticks) - to_chat(tracking_holder, span_warning("Target is not near any active cameras. Attempting to reacquire...")) - cameraticks++ - return - - to_chat(tracking_holder, span_warning("Unable to reacquire, cancelling track...")) - cameraticks = initial(cameraticks) - set_tracking(FALSE) - ///Generates a list of trackable people by name, returning a list of Humans + Non-Humans that can be tracked. /datum/trackable/proc/find_trackable_mobs() RETURN_TYPE(/list) @@ -82,47 +61,140 @@ var/list/targets = sort_list(humans) + sort_list(others) return targets -///Toggles whether or not we're tracking something. Arg is whether it's on or off. -/datum/trackable/proc/set_tracking(on = FALSE) - if(on) +/// Takes a mob to track, resets our state and begins trying to follow it +/// Best we can at least +/datum/trackable/proc/set_tracked_mob(mob/living/track) + set_rechecking(FALSE) + if(tracked_mob) + UnregisterSignal(tracked_mob, list(COMSIG_QDELETING, COMSIG_MOVABLE_MOVED, COMSIG_MOVABLE_UPDATE_GLIDE_SIZE)) + if(track && !isliving(track)) + tracked_mob = null + return + tracked_mob = track + if(tracked_mob) + RegisterSignal(tracked_mob, COMSIG_QDELETING, PROC_REF(target_deleted)) + RegisterSignal(tracked_mob, COMSIG_MOVABLE_MOVED, PROC_REF(target_moved)) + RegisterSignal(tracked_mob, COMSIG_MOVABLE_UPDATE_GLIDE_SIZE, PROC_REF(glide_size_changed)) + attempt_track() + +/datum/trackable/proc/target_deleted(datum/source) + SIGNAL_HANDLER + reset_tracking() + +/datum/trackable/proc/perspective_reset(atom/source) + SIGNAL_HANDLER + reset_tracking() + +/datum/trackable/proc/target_moved(datum/source) + SIGNAL_HANDLER + if(attempt_track()) + return + set_rechecking(TRUE) + +/// Controls if we're processing to recheck the conditions that prevent tracking or not +/datum/trackable/proc/set_rechecking(should_check) + if(should_check) START_PROCESSING(SSprocessing, src) - tracking = TRUE + cameraticks = initial(cameraticks) + rechecking = TRUE else STOP_PROCESSING(SSprocessing, src) - tracking = FALSE - tracked_mob = null + rechecking = FALSE + +/datum/trackable/process() + if(!rechecking) + return PROCESS_KILL + + if(attempt_track()) + set_rechecking(FALSE) + return + + if(cameraticks < CAMERA_TICK_LIMIT) + if(!cameraticks) + to_chat(tracking_holder, span_warning("Target is not near any active cameras. Attempting to reacquire...")) + cameraticks++ + return -///Called by Signals, used to cancel tracking of a target. -/datum/trackable/proc/cancel_target_tracking(atom/source) + to_chat(tracking_holder, span_warning("Unable to reacquire, cancelling track...")) + reset_tracking() + +/// Tries to track onto our target mob. Returns true if it succeeds, false otherwise +/datum/trackable/proc/attempt_track() + if(!tracked_mob) + reset_tracking() + return FALSE + + if(!tracked_mob.can_track(tracking_holder)) + return FALSE + // In case we've been checking + set_rechecking(FALSE) + SEND_SIGNAL(src, COMSIG_TRACKABLE_TRACKING_TARGET, tracked_mob) + return TRUE + +/datum/trackable/proc/glide_size_changed(datum/source, new_glide_size) SIGNAL_HANDLER - set_tracking(FALSE) + SEND_SIGNAL(src, COMSIG_TRACKABLE_GLIDE_CHANGED, tracked_mob, new_glide_size) /** - * set_tracked_mob + * reset_tracking * - * Sets a mob as being tracked, if a target is already provided then it will track that directly, - * otherwise it will give a tgui input list to find targets to track. + * Resets our tracking + */ +/datum/trackable/proc/reset_tracking() + set_tracked_mob(null) + +/** + * track_input + * + * Sets a mob as being tracked, will give a tgui input list to find targets to track. * Args: * tracker - The person trying to track, used for feedback messages. This is not the same as tracking_holder - * tracked_mob_name - (Optional) The person being tracked, to skip the input list. */ -/datum/trackable/proc/set_tracked_mob(mob/living/tracker, tracked_mob_name) +/datum/trackable/proc/track_input(mob/living/tracker) if(!tracker || tracker.stat == DEAD) return - if(tracked_mob_name) - find_trackable_mobs() //this is in case the tracked mob is newly/no-longer in camera field of view. - tracked_mob = isnull(humans[tracked_mob_name]) ? others[tracked_mob_name] : humans[tracked_mob_name] - if(isnull(tracked_mob)) - to_chat(tracker, span_notice("Target is not on or near any active cameras. Tracking failed.")) - return - to_chat(tracker, span_notice("Now tracking [tracked_mob_name] on camera.")) - else - var/target_name = tgui_input_list(tracker, "Select a target", "Tracking", find_trackable_mobs()) - if(!target_name || isnull(target_name)) - return - tracked_mob = isnull(humans[target_name]) ? others[target_name] : humans[target_name] + var/target_name = tgui_input_list(tracker, "Select a target", "Tracking", find_trackable_mobs()) + if(!target_name || isnull(target_name)) + return + var/datum/weakref/mob_ref = isnull(humans[target_name]) ? others[target_name] : humans[target_name] + if(isnull(mob_ref)) + to_chat(tracker, span_notice("Target is not on or near any active cameras. Tracking failed.")) + return + set_tracked_mob(mob_ref.resolve()) + +/** + * track_name + * + * Sets a mob as being tracked, will track the passed in target name's target + * Args: + * tracker - The person trying to track, used for feedback messages. This is not the same as tracking_holder + * tracked_mob_name - The person being tracked. + */ +/datum/trackable/proc/track_name(mob/living/tracker, tracked_mob_name) + if(!tracker || tracker.stat == DEAD) + return + + find_trackable_mobs() //this is in case the tracked mob is newly/no-longer in camera field of view. + var/datum/weakref/mob_ref = isnull(humans[tracked_mob_name]) ? others[tracked_mob_name] : humans[tracked_mob_name] + if(isnull(mob_ref)) + to_chat(tracker, span_notice("Target is not on or near any active cameras. Tracking failed.")) + return + to_chat(tracker, span_notice("Now tracking [tracked_mob_name] on camera.")) + set_tracked_mob(mob_ref.resolve()) - set_tracking(TRUE) +/** + * track_mob + * + * Sets a mob as being tracked, will track the passed in target + * Args: + * tracker - The person trying to track, used for feedback messages. This is not the same as tracking_holder + * tracked - The person being tracked. + */ +/datum/trackable/proc/track_mob(mob/living/tracker, mob/living/tracked) + if(!tracker || tracker.stat == DEAD) + return + // Need to make sure the tracked mob is in our list + track_name(tracked.name) #undef CAMERA_TICK_LIMIT diff --git a/code/game/machinery/computer/crew.dm b/code/game/machinery/computer/crew.dm index a00ed045be7af..d286f8ee6043d 100644 --- a/code/game/machinery/computer/crew.dm +++ b/code/game/machinery/computer/crew.dm @@ -282,7 +282,7 @@ GLOBAL_DATUM_INIT(crewmonitor, /datum/crewmonitor, new) var/mob/living/silicon/ai/AI = usr if(!istype(AI)) return - AI.ai_tracking_tool.set_tracked_mob(AI, params["name"]) + AI.ai_tracking_tool.track_name(AI, params["name"]) #undef SENSORS_UPDATE_PERIOD #undef UNKNOWN_JOB_ID diff --git a/code/game/objects/effects/spawners/random/bedsheet.dm b/code/game/objects/effects/spawners/random/bedsheet.dm new file mode 100644 index 0000000000000..3fb39c5de4a71 --- /dev/null +++ b/code/game/objects/effects/spawners/random/bedsheet.dm @@ -0,0 +1,64 @@ +/obj/effect/spawner/random/bedsheet + name = "random dorm bedsheet" + icon_state = "random_bedsheet" + loot = list(/obj/item/bedsheet = 8, + /obj/item/bedsheet/blue = 8, + /obj/item/bedsheet/green = 8, + /obj/item/bedsheet/grey = 8, + /obj/item/bedsheet/orange = 8, + /obj/item/bedsheet/purple = 8, + /obj/item/bedsheet/red = 8, + /obj/item/bedsheet/yellow = 8, + /obj/item/bedsheet/brown = 8, + /obj/item/bedsheet/black = 8, + /obj/item/bedsheet/patriot = 2, + /obj/item/bedsheet/rainbow = 2, + /obj/item/bedsheet/ian = 2, + /obj/item/bedsheet/runtime = 2, + /obj/item/bedsheet/cosmos = 2, + /obj/item/bedsheet/nanotrasen = 2, + /obj/item/bedsheet/pirate = 2, + /obj/item/bedsheet/gondola = 1, + ) + +/obj/effect/spawner/random/bedsheet/double + name = "random dorm double bedsheet" + icon_state = "random_doublesheet" + loot = list( + /obj/item/bedsheet/double = 4, + /obj/item/bedsheet/blue/double = 4, + /obj/item/bedsheet/green/double = 4, + /obj/item/bedsheet/grey/double = 4, + /obj/item/bedsheet/orange/double = 4, + /obj/item/bedsheet/purple/double = 4, + /obj/item/bedsheet/red/double = 4, + /obj/item/bedsheet/yellow/double = 4, + /obj/item/bedsheet/brown/double = 4, + /obj/item/bedsheet/black/double = 4, + /obj/item/bedsheet/patriot/double = 1, + /obj/item/bedsheet/rainbow/double = 1, + /obj/item/bedsheet/ian/double = 1, + /obj/item/bedsheet/runtime/double = 1, + /obj/item/bedsheet/cosmos/double = 1, + /obj/item/bedsheet/nanotrasen/double = 1, + ) + +/obj/effect/spawner/random/bedsheet/any + name = "random single bedsheet" + loot = null + var/static/list/bedsheet_list = list() + var/spawn_type = BEDSHEET_SINGLE + +/obj/effect/spawner/random/bedsheet/any/Initialize(mapload) + if(isnull(bedsheet_list[spawn_type])) + var/list/spawn_list = list() + for(var/obj/item/bedsheet/sheet as anything in typesof(/obj/item/bedsheet)) + if(initial(sheet.bedsheet_type) == spawn_type) + spawn_list += sheet + bedsheet_list[spawn_type] = spawn_list + loot = bedsheet_list[spawn_type] + return ..() + +/obj/effect/spawner/random/bedsheet/any/double + icon_state = "random_doublesheet" + spawn_type = BEDSHEET_DOUBLE diff --git a/code/game/objects/items/knives.dm b/code/game/objects/items/knives.dm index b7273ed0a3264..315862d2d79ff 100644 --- a/code/game/objects/items/knives.dm +++ b/code/game/objects/items/knives.dm @@ -124,6 +124,7 @@ name = "combat knife" icon = 'icons/obj/weapons/stabby.dmi' icon_state = "buckknife" + worn_icon_state = "buckknife" desc = "A military combat utility survival knife." embedding = list("pain_mult" = 4, "embed_chance" = 65, "fall_chance" = 10, "ignore_throwspeed_threshold" = TRUE) force = 20 @@ -131,11 +132,33 @@ attack_verb_continuous = list("slashes", "stabs", "slices", "tears", "lacerates", "rips", "cuts") attack_verb_simple = list("slash", "stab", "slice", "tear", "lacerate", "rip", "cut") bayonet = TRUE + slot_flags = ITEM_SLOT_MASK + +/obj/item/knife/combat/Initialize(mapload) + . = ..() + AddComponent(/datum/component/knockoff, 90, list(BODY_ZONE_PRECISE_MOUTH), slot_flags) //90% to knock off when wearing a mask + +/obj/item/knife/combat/dropped(mob/living/user, slot) + . = ..() + if(user.get_item_by_slot(ITEM_SLOT_MASK) == src && !user.has_status_effect(/datum/status_effect/choke) && prob(20)) + user.apply_damage(5, BRUTE, BODY_ZONE_HEAD) + playsound(user, 'sound/weapons/slice.ogg', 50, TRUE) + user.visible_message(span_danger("[user] accidentally cuts [user.p_them()]self while pulling [src] out of [user.p_them()] teeth! What a doofus!"), span_userdanger("You accidentally cut your mouth with [src]!")) + . = ..() + +/obj/item/knife/combat/equipped(mob/living/user, slot, initial = FALSE) + . = ..() + if(HAS_TRAIT(user, TRAIT_CLUMSY) && prob(20)) + if(user.get_item_by_slot(ITEM_SLOT_MASK) == src) + user.apply_status_effect(/datum/status_effect/choke, src) + user.visible_message(span_danger("[user] accidentally swallows [src]!")) + playsound(user, 'sound/items/eatfood.ogg', 100, TRUE) /obj/item/knife/combat/survival name = "survival knife" icon = 'icons/obj/weapons/stabby.dmi' icon_state = "survivalknife" + worn_icon_state = "survivalknife" embedding = list("pain_mult" = 4, "embed_chance" = 35, "fall_chance" = 10) desc = "A hunting grade survival knife." force = 15 @@ -153,6 +176,7 @@ desc = "A sharpened bone. The bare minimum in survival." embedding = list("pain_mult" = 4, "embed_chance" = 35, "fall_chance" = 10) obj_flags = parent_type::obj_flags & ~CONDUCTS_ELECTRICITY + slot_flags = NONE force = 15 throwforce = 15 custom_materials = null diff --git a/code/game/objects/items/melee/baton.dm b/code/game/objects/items/melee/baton.dm index da0bf1dbc64fb..b692b58bfcf2d 100644 --- a/code/game/objects/items/melee/baton.dm +++ b/code/game/objects/items/melee/baton.dm @@ -427,6 +427,12 @@ on_stun_volume = 50 active = FALSE context_living_rmb_active = "Harmful Stun" + light_range = 1.5 + light_system = OVERLAY_LIGHT + light_on = FALSE + light_color = LIGHT_COLOR_ORANGE + light_power = 0.5 + var/throw_stun_chance = 35 var/obj/item/stock_parts/cell/cell @@ -541,6 +547,8 @@ active = !active balloon_alert(user, "turned [active ? "on" : "off"]") playsound(src, SFX_SPARKS, 75, TRUE, -1) + toggle_light(user) + do_sparks(1, TRUE, src) else active = FALSE if(!cell) @@ -550,6 +558,11 @@ update_appearance() add_fingerprint(user) +/// Toggles the stun baton's light +/obj/item/melee/baton/security/proc/toggle_light(mob/user) + set_light_on(!light_on) + return + /obj/item/melee/baton/security/proc/deductcharge(deducted_charge) if(!cell) return @@ -559,6 +572,7 @@ if(active && cell.charge < cell_hit_cost) //we're below minimum, turn off active = FALSE + set_light_on(FALSE) update_appearance() playsound(src, SFX_SPARKS, 75, TRUE, -1) @@ -649,6 +663,8 @@ if (!cell || cell.charge < cell_hit_cost) return active = !active + toggle_light() + do_sparks(1, TRUE, src) playsound(src, SFX_SPARKS, 75, TRUE, -1) update_appearance() diff --git a/code/game/objects/items/stacks/sheets/leather.dm b/code/game/objects/items/stacks/sheets/leather.dm index 500b2500c8ad5..e9426a913ec70 100644 --- a/code/game/objects/items/stacks/sheets/leather.dm +++ b/code/game/objects/items/stacks/sheets/leather.dm @@ -40,11 +40,6 @@ GLOBAL_LIST_INIT(human_recipes, list( \ inhand_icon_state = null merge_type = /obj/item/stack/sheet/animalhide/corgi -GLOBAL_LIST_INIT(gondola_recipes, list ( \ - new/datum/stack_recipe("gondola mask", /obj/item/clothing/mask/gondola, 1, check_density = FALSE, category = CAT_CLOTHING), \ - new/datum/stack_recipe("gondola suit", /obj/item/clothing/under/costume/gondola, 2, check_density = FALSE, category = CAT_CLOTHING), \ - )) - /obj/item/stack/sheet/animalhide/corgi/five amount = 5 @@ -59,6 +54,12 @@ GLOBAL_LIST_INIT(gondola_recipes, list ( \ /obj/item/stack/sheet/animalhide/mothroach/five amount = 5 +GLOBAL_LIST_INIT(gondola_recipes, list ( \ + new/datum/stack_recipe("gondola mask", /obj/item/clothing/mask/gondola, 1, check_density = FALSE, category = CAT_CLOTHING), \ + new/datum/stack_recipe("gondola suit", /obj/item/clothing/under/costume/gondola, 2, check_density = FALSE, category = CAT_CLOTHING), \ + new/datum/stack_recipe("gondola bedsheet", /obj/item/bedsheet/gondola, 1, check_density = FALSE, category = CAT_FURNITURE), \ + )) + /obj/item/stack/sheet/animalhide/gondola name = "gondola hide" desc = "The extremely valuable product of gondola hunting." diff --git a/code/game/objects/items/storage/boxes/job_boxes.dm b/code/game/objects/items/storage/boxes/job_boxes.dm index bb656061c1c55..220fdc2f79522 100644 --- a/code/game/objects/items/storage/boxes/job_boxes.dm +++ b/code/game/objects/items/storage/boxes/job_boxes.dm @@ -30,10 +30,8 @@ if(!isnull(mask_type)) new mask_type(src) - if(!isplasmaman(loc)) + if(!isnull(internal_type)) new internal_type(src) - else - new /obj/item/tank/internals/plasmaman/belt(src) if(!isnull(medipen_type)) new medipen_type(src) diff --git a/code/game/objects/items/storage/lockbox.dm b/code/game/objects/items/storage/lockbox.dm index 902af39bbea0e..3e7b73c93f332 100644 --- a/code/game/objects/items/storage/lockbox.dm +++ b/code/game/objects/items/storage/lockbox.dm @@ -237,6 +237,8 @@ name = "order lockbox" desc = "A box used to secure small cargo orders from being looted by those who didn't order it. Yeah, cargo tech, that means you." icon_state = "secure" + icon_closed = "secure" + icon_locked = "secure_locked" icon_broken = "secure+b" inhand_icon_state = "sec-case" lefthand_file = 'icons/mob/inhands/equipment/briefcase_lefthand.dmi' @@ -265,8 +267,10 @@ if(privacy_lock) atom_storage.locked = STORAGE_NOT_LOCKED + icon_state = icon_locked else atom_storage.locked = STORAGE_FULLY_LOCKED + icon_state = icon_closed privacy_lock = atom_storage.locked user.visible_message(span_notice("[user] [privacy_lock ? "" : "un"]locks [src]'s privacy lock."), span_notice("You [privacy_lock ? "" : "un"]lock [src]'s privacy lock.")) diff --git a/code/game/objects/structures/bedsheet_bin.dm b/code/game/objects/structures/bedsheet_bin.dm index 66de98bd50ab4..f80042f5679a7 100644 --- a/code/game/objects/structures/bedsheet_bin.dm +++ b/code/game/objects/structures/bedsheet_bin.dm @@ -4,10 +4,6 @@ BEDSHEETS LINEN BINS */ -#define BEDSHEET_ABSTRACT "abstract" -#define BEDSHEET_SINGLE "single" -#define BEDSHEET_DOUBLE "double" - /obj/item/bedsheet name = "bedsheet" desc = "A surprisingly soft linen bedsheet." @@ -28,7 +24,9 @@ LINEN BINS dog_fashion = /datum/dog_fashion/head/ghost /// Custom nouns to act as the subject of dreams var/list/dream_messages = list("white") - /// The number of cloth sheets to be dropped by this bedsheet when cut + /// Cutting it up will yield this. + var/stack_type = /obj/item/stack/sheet/cloth + /// The number of sheets dropped by this bedsheet when cut var/stack_amount = 3 /// Denotes if the bedsheet is a single, double, or other kind of bedsheet var/bedsheet_type = BEDSHEET_SINGLE @@ -126,7 +124,7 @@ LINEN BINS /obj/item/bedsheet/attackby(obj/item/I, mob/user, params) if(I.tool_behaviour == TOOL_WIRECUTTER || I.get_sharpness()) if (!(flags_1 & HOLOGRAM_1)) - var/obj/item/stack/sheet/cloth/shreds = new (get_turf(src), stack_amount) + var/obj/item/stack/shreds = new stack_type(get_turf(src), stack_amount) if(!QDELETED(shreds)) //stacks merged transfer_fingerprints_to(shreds) shreds.add_fingerprint(user) @@ -338,6 +336,60 @@ LINEN BINS inhand_icon_state = "sheetian" dream_messages = list("a dog", "a corgi", "woof", "bark", "arf") +/obj/item/bedsheet/runtime + icon_state = "sheetruntime" + inhand_icon_state = "sheetruntime" + dream_messages = list("a kitty", "a cat", "meow", "purr", "nya~") + +/obj/item/bedsheet/pirate + name = "pirate's bedsheet" + desc = "It has a Jolly Roger emblem on it and has a faint scent of grog." + icon_state = "sheetpirate" + inhand_icon_state = "sheetpirate" + dream_messages = list( + "a buried treasure", + "an island", + "a monkey", + "a parrot", + "a swashbuckler", + "a talking skull", + "avast", + "being a pirate", + "'cause a pirate is free", + "doing whatever you want", + "gold", + "landlubbers", + "stealing", + "sailing the Seven Seas", + "yarr", + ) + +/obj/item/bedsheet/gondola + name = "gondola bedsheet" + desc = "A precious bedsheet made from the hide of a endangered and peculiar critter." + icon_state = "sheetgondola" + inhand_icon_state = "sheetgondola" + dream_messages = list("peace", "comfiness", "a rare critter", "a harmless creature") + stack_type = /obj/item/stack/sheet/animalhide/gondola + stack_amount = 1 + ///one of four icon states that represent its mouth + var/gondola_mouth + ///one of four icon states that represent its eyes + var/gondola_eyes + +/obj/item/bedsheet/gondola/Initialize(mapload) + . = ..() + gondola_mouth = "sheetgondola_mouth[rand(1, 4)]" + gondola_eyes = "sheetgondola_eyes[rand(1, 4)]" + add_overlay(gondola_mouth) + add_overlay(gondola_eyes) + +/obj/item/bedsheet/gondola/worn_overlays(mutable_appearance/standing, isinhands, icon_file) + . = ..() + if(!isinhands) + . += mutable_appearance(icon_file, gondola_mouth) + . += mutable_appearance(icon_file, gondola_eyes) + /obj/item/bedsheet/cosmos name = "cosmic space bedsheet" desc = "Made from the dreams of those who wonder at the stars." @@ -347,66 +399,6 @@ LINEN BINS light_power = 2 light_range = 1.4 -/obj/item/bedsheet/random - icon_state = "random_bedsheet" - name = "random bedsheet" - desc = "If you're reading this description ingame, something has gone wrong! Honk!" - bedsheet_type = BEDSHEET_ABSTRACT - item_flags = ABSTRACT - var/static/list/bedsheet_list - var/spawn_type = BEDSHEET_SINGLE - -/obj/item/bedsheet/random/Initialize(mapload) - ..() - if(!LAZYACCESS(bedsheet_list, spawn_type)) - var/list/spawn_list = list() - var/list/possible_types = typesof(/obj/item/bedsheet) - for(var/obj/item/bedsheet/sheet as anything in possible_types) - if(initial(sheet.bedsheet_type) == spawn_type) - spawn_list += sheet - LAZYSET(bedsheet_list, spawn_type, spawn_list) - var/chosen_type = pick(bedsheet_list[spawn_type]) - var/obj/item/bedsheet = new chosen_type(loc) - bedsheet.dir = dir - return INITIALIZE_HINT_QDEL - -/obj/item/bedsheet/random/double - icon_state = "random_bedsheet" - spawn_type = BEDSHEET_DOUBLE - -/obj/item/bedsheet/dorms - icon_state = "random_bedsheet" - name = "random dorms bedsheet" - desc = "If you're reading this description ingame, something has gone wrong! Honk!" - bedsheet_type = BEDSHEET_DOUBLE - item_flags = ABSTRACT - slot_flags = null - -/obj/item/bedsheet/dorms/Initialize(mapload) - ..() - var/type = pick_weight(list("Colors" = 80, "Special" = 20)) - switch(type) - if("Colors") - type = pick(list(/obj/item/bedsheet, - /obj/item/bedsheet/blue, - /obj/item/bedsheet/green, - /obj/item/bedsheet/grey, - /obj/item/bedsheet/orange, - /obj/item/bedsheet/purple, - /obj/item/bedsheet/red, - /obj/item/bedsheet/yellow, - /obj/item/bedsheet/brown, - /obj/item/bedsheet/black)) - if("Special") - type = pick(list(/obj/item/bedsheet/patriot, - /obj/item/bedsheet/rainbow, - /obj/item/bedsheet/ian, - /obj/item/bedsheet/cosmos, - /obj/item/bedsheet/nanotrasen)) - var/obj/item/bedsheet = new type(loc) - bedsheet.dir = dir - return INITIALIZE_HINT_QDEL - /obj/item/bedsheet/double icon_state = "double_sheetwhite" worn_icon_state = "sheetwhite" @@ -559,45 +551,16 @@ LINEN BINS worn_icon_state = "sheetian" bedsheet_type = BEDSHEET_DOUBLE +/obj/item/bedsheet/runtime/double + icon_state = "double_sheetruntime" + worn_icon_state = "sheetruntime" + bedsheet_type = BEDSHEET_DOUBLE + /obj/item/bedsheet/cosmos/double icon_state = "double_sheetcosmos" worn_icon_state = "sheetcosmos" bedsheet_type = BEDSHEET_DOUBLE -/obj/item/bedsheet/dorms_double - icon_state = "random_bedsheet" - item_flags = ABSTRACT - bedsheet_type = BEDSHEET_ABSTRACT - -/obj/item/bedsheet/dorms_double/Initialize(mapload) - ..() - var/type = pick_weight(list("Colors" = 80, "Special" = 20)) - switch(type) - if("Colors") - type = pick(list( - /obj/item/bedsheet/double, - /obj/item/bedsheet/blue/double, - /obj/item/bedsheet/green/double, - /obj/item/bedsheet/grey/double, - /obj/item/bedsheet/orange/double, - /obj/item/bedsheet/purple/double, - /obj/item/bedsheet/red/double, - /obj/item/bedsheet/yellow/double, - /obj/item/bedsheet/brown/double, - /obj/item/bedsheet/black/double, - )) - if("Special") - type = pick(list( - /obj/item/bedsheet/patriot/double, - /obj/item/bedsheet/rainbow/double, - /obj/item/bedsheet/ian/double, - /obj/item/bedsheet/cosmos/double, - /obj/item/bedsheet/nanotrasen/double, - )) - var/obj/item/bedsheet = new type(loc) - bedsheet.dir = dir - return INITIALIZE_HINT_QDEL - /obj/structure/bedsheetbin name = "linen bin" desc = "It looks rather cosy." @@ -736,7 +699,3 @@ LINEN BINS add_fingerprint(user) return COMPONENT_CANCEL_ATTACK_CHAIN - -#undef BEDSHEET_ABSTRACT -#undef BEDSHEET_SINGLE -#undef BEDSHEET_DOUBLE diff --git a/code/game/sound.dm b/code/game/sound.dm index 3c6a62eb781d3..e575534bdaeed 100644 --- a/code/game/sound.dm +++ b/code/game/sound.dm @@ -50,7 +50,7 @@ //allocate a channel if necessary now so its the same for everyone channel = channel || SSsounds.random_available_channel() - var/sound/S = sound(get_sfx(soundin)) + var/sound/S = isdatum(soundin) ? soundin : sound(get_sfx(soundin)) var/maxdistance = SOUND_RANGE + extrarange var/source_z = turf_source.z var/list/listeners = SSmobs.clients_by_zlevel[source_z].Copy() diff --git a/code/modules/antagonists/heretic/heretic_knowledge.dm b/code/modules/antagonists/heretic/heretic_knowledge.dm index cb9f3b75ccccf..f2cf7b0004771 100644 --- a/code/modules/antagonists/heretic/heretic_knowledge.dm +++ b/code/modules/antagonists/heretic/heretic_knowledge.dm @@ -211,7 +211,8 @@ /datum/heretic_knowledge/spell/on_lose(mob/user, datum/antagonist/heretic/our_heretic) var/datum/action/cooldown/spell/created_spell = created_spell_ref?.resolve() - created_spell?.Remove(user) + if(created_spell?.owner == user) + created_spell.Remove(user) /** * A knowledge subtype for knowledge that can only diff --git a/code/modules/antagonists/nightmare/nightmare_equipment.dm b/code/modules/antagonists/nightmare/nightmare_equipment.dm index 965b95ca6e892..fd80b3ea3ef56 100644 --- a/code/modules/antagonists/nightmare/nightmare_equipment.dm +++ b/code/modules/antagonists/nightmare/nightmare_equipment.dm @@ -64,7 +64,7 @@ remove_crit() /obj/item/light_eater/proc/prepare_crit_timer() - crit_timer = addtimer(CALLBACK(src, PROC_REF(add_crit)), 15 SECONDS, TIMER_DELETE_ME | TIMER_STOPPABLE) + crit_timer = addtimer(CALLBACK(src, PROC_REF(add_crit)), 7 SECONDS, TIMER_DELETE_ME | TIMER_STOPPABLE) /obj/item/light_eater/proc/stop_crit_timer() deltimer(crit_timer) diff --git a/code/modules/antagonists/wizard/equipment/spellbook_entries/mobility.dm b/code/modules/antagonists/wizard/equipment/spellbook_entries/mobility.dm index d5112a59611ba..6a8f322a3a5f4 100644 --- a/code/modules/antagonists/wizard/equipment/spellbook_entries/mobility.dm +++ b/code/modules/antagonists/wizard/equipment/spellbook_entries/mobility.dm @@ -50,3 +50,10 @@ item_path = /obj/item/gun/magic/staff/door cost = 1 category = "Mobility" + +/datum/spellbook_entry/item/teleport_rod + name = /obj/item/teleport_rod::name + desc = /obj/item/teleport_rod::desc + item_path = /obj/item/teleport_rod + cost = 2 // Puts it at 3 cost if you go for safety instant summons, but teleporting anywhere on screen is pretty good. + category = "Mobility" diff --git a/code/modules/antagonists/wizard/equipment/teleport_rod.dm b/code/modules/antagonists/wizard/equipment/teleport_rod.dm new file mode 100644 index 0000000000000..3c41cae525783 --- /dev/null +++ b/code/modules/antagonists/wizard/equipment/teleport_rod.dm @@ -0,0 +1,246 @@ +/// Totally NOT a Rod of Discord +/// Teleports you to where you click! +/obj/item/teleport_rod + name = "Telegram Scepter" + desc = "A magical rod that teleports you to the location you point it. \ + Using it puts you in a state of flux, removing some of your reagents and \ + causing you to take damage from further uses until you stabilize once more." + icon_state = "tele_wand_er" + inhand_icon_state = "tele_wand_er" + icon = 'icons/obj/weapons/guns/magic.dmi' + lefthand_file = 'icons/mob/inhands/weapons/staves_lefthand.dmi' + righthand_file = 'icons/mob/inhands/weapons/staves_righthand.dmi' + resistance_flags = LAVA_PROOF | FIRE_PROOF | ACID_PROOF | UNACIDABLE + item_flags = NOBLUDGEON + light_system = OVERLAY_LIGHT + light_color = COLOR_FADED_PINK + light_power = 1 + light_range = 2 + light_on = TRUE + /// Whether we apply the teleport flux debuff, damaging people who teleport + var/apply_debuffs = TRUE + /// Max range at which we can teleport, because it operates in view TECHNICALLY can click very very far + var/max_tp_range = 8 + +/obj/item/teleport_rod/Initialize(mapload) + . = ..() + particles = new /particles/teleport_flux/small() + +// Admin only version which just teleports you, so spam it all you want +/obj/item/teleport_rod/admin + name = "Harmonious " + parent_type::name + desc = "A magical rod that teleports you anywhere, no questions asked." + apply_debuffs = FALSE + max_tp_range = INFINITY + +/obj/item/teleport_rod/equipped(mob/living/user, slot, initial) + . = ..() + if(!isliving(user)) + return + if(HAS_MIND_TRAIT(user, TRAIT_MAGICALLY_GIFTED)) + return + if(!(slot & ITEM_SLOT_HANDS)) + return + if(!apply_debuffs) + return + user.apply_status_effect(/datum/status_effect/teleport_flux/perma) + +/obj/item/teleport_rod/dropped(mob/living/user, silent) + . = ..() + if(!isliving(user)) + return + if(HAS_MIND_TRAIT(user, TRAIT_MAGICALLY_GIFTED)) + return + + var/datum/status_effect/teleport_flux/perma/permaflux = user.has_status_effect(/datum/status_effect/teleport_flux/perma) + permaflux?.delayed_remove(src) + +/obj/item/teleport_rod/afterattack(atom/target, mob/living/user, proximity_flag, click_parameters) + . = ..() + if(!isliving(user)) + return + if(proximity_flag) // assuming you don't want to teleport 1 tile away + return + + . |= AFTERATTACK_PROCESSED_ITEM + + var/turf/start_turf = get_turf(user) + var/turf/target_turf = get_turf(target) + if(get_dist(start_turf, target_turf) > max_tp_range) + user.balloon_alert(user, "too far!") + return + + if(!(target_turf in view(user, user.client?.view || world.view))) + user.balloon_alert(user, "out of view!") + return + + if(target_turf.is_blocked_turf(exclude_mobs = TRUE, source_atom = user)) + user.balloon_alert(user, "obstructed!") + return + + var/tp_result = do_teleport( + teleatom = user, + destination = target_turf, + precision = (HAS_MIND_TRAIT(user, TRAIT_MAGICALLY_GIFTED) || !apply_debuffs) ? 0 : 2, + no_effects = TRUE, + channel = TELEPORT_CHANNEL_MAGIC, + ) + + if(!tp_result) + user.balloon_alert(user, "teleport failed!") + return + + var/sound/teleport_sound = sound('sound/magic/summonitems_generic.ogg') + teleport_sound.pitch = 0.5 + // Handle our own pizzaz rather than doing it in do_teleport + new /obj/effect/temp_visual/teleport_flux(start_turf, user.dir) + new /obj/effect/temp_visual/teleport_flux(get_turf(user), user.dir) + playsound(start_turf, teleport_sound, 90, extrarange = MEDIUM_RANGE_SOUND_EXTRARANGE) + playsound(user, teleport_sound, 90, extrarange = MEDIUM_RANGE_SOUND_EXTRARANGE) + // Some extra delay to prevent accidental double clicks + user.changeNext_move(CLICK_CD_SLOW * 1.2) + + if(!apply_debuffs) + return + + // Teleporting leaves some of your reagents behind! + // (Primarily a way to prevent cheese with damage healing chem mixes, + // but also serves as a counter-counter to stuff like mute toxin.) + var/obj/item/organ/user_stomach = user.get_organ_slot(ORGAN_SLOT_STOMACH) + user.reagents?.remove_all_direct(0.33) + user_stomach?.reagents?.remove_all_direct(0.33) + if(user.has_status_effect(/datum/status_effect/teleport_flux/perma)) + return + + if(user.has_status_effect(/datum/status_effect/teleport_flux)) + // The status effect handles the damage, but we'll add a special pop up for rod usage specifically + user.balloon_alert(user, "too soon!") + + user.apply_status_effect(/datum/status_effect/teleport_flux) + +/// Temp visual displayed on both sides of a teleport rod teleport +/obj/effect/temp_visual/teleport_flux + icon_state = "blank_white" + color = COLOR_MAGENTA + alpha = 255 + duration = 2 SECONDS + light_color = COLOR_MAGENTA + light_power = 2 + light_range = 1 + light_on = TRUE + randomdir = FALSE + +/obj/effect/temp_visual/teleport_flux/Initialize(mapload, copy_dir = SOUTH) + . = ..() + setDir(copy_dir) + particles = new /particles/teleport_flux() + apply_wibbly_filters(src) + animate(src, alpha = 0, time = duration, flags = ANIMATION_PARALLEL) + +/// Status effect applied to users of a Teleport Rod, damages them when they teleport +/datum/status_effect/teleport_flux + id = "teleport_flux" + status_type = STATUS_EFFECT_REFRESH + duration = 6 SECONDS + alert_type = /atom/movable/screen/alert/status_effect/teleport_flux + remove_on_fullheal = TRUE // staff of healing ~synergy~ + + /// Amount of damage to deal when teleporting in flux + var/tp_damage = 15 + /// Damage type to deal when teleporting in flux + var/tp_damage_type = BRUTE + +/datum/status_effect/teleport_flux/on_apply() + RegisterSignal(owner, COMSIG_MOVABLE_POST_TELEPORT, PROC_REF(teleported)) + return TRUE + +/datum/status_effect/teleport_flux/on_remove() + UnregisterSignal(owner, COMSIG_MOVABLE_POST_TELEPORT) + +/datum/status_effect/teleport_flux/proc/teleported(mob/living/source, turf/destination, channel) + SIGNAL_HANDLER + + if(channel != TELEPORT_CHANNEL_MAGIC) + return + + owner.apply_damage( + damage = tp_damage, + damagetype = tp_damage_type, + spread_damage = TRUE, + forced = TRUE, + ) + log_combat(owner, owner, "teleported too soon") + +/datum/status_effect/teleport_flux/update_particles() + if(isnull(particle_effect)) + particle_effect = new(owner, /particles/teleport_flux) + + particle_effect.alpha = 200 + var/original_duration = initial(duration) + if(original_duration == -1) + return + animate(particle_effect, alpha = 50, time = original_duration) + +/datum/status_effect/teleport_flux/refresh(effect, ...) + . = ..() + update_particles() + +/datum/status_effect/teleport_flux/perma + id = "perma_teleport_flux" + status_type = STATUS_EFFECT_REPLACE + duration = -1 + alert_type = /atom/movable/screen/alert/status_effect/teleport_flux/perma + remove_on_fullheal = FALSE + +/datum/status_effect/teleport_flux/perma/on_apply() + . = ..() + RegisterSignal(owner, SIGNAL_ADDTRAIT(TRAIT_MAGICALLY_GIFTED), PROC_REF(gained_gift)) + +/datum/status_effect/teleport_flux/perma/on_remove() + . = ..() + UnregisterSignal(owner, SIGNAL_ADDTRAIT(TRAIT_MAGICALLY_GIFTED)) + +/datum/status_effect/teleport_flux/perma/proc/gained_gift(mob/living/source, trait) + SIGNAL_HANDLER + + delayed_remove() + +/// Used to fade out the effect and remove it after a delay +/// This cannot be interrupted, but if a new permaflux effect is applied, +/// this one will be deleted instantly anyways, making it moot +/datum/status_effect/teleport_flux/perma/proc/delayed_remove() + var/del_duration = /datum/status_effect/teleport_flux::duration + QDEL_IN(src, del_duration) + animate(particle_effect, alpha = 50, del_duration) + +/// Alert for the Teleport Flux status effect +/atom/movable/screen/alert/status_effect/teleport_flux + name = "Teleport Flux" + desc = "Your body exists in a state of flux, making further teleportation dangerous." + icon_state = "flux" + +/atom/movable/screen/alert/status_effect/teleport_flux/perma + name = "Permanent " + parent_type::name + desc = "Your lack of magical talent has left you in a state of flux, making further teleportation dangerous." + +/// Particles for Teleport Flux and other similar effects +/particles/teleport_flux + icon = 'icons/effects/particles/echo.dmi' + icon_state = list("echo1" = 3, "echo2" = 1, "echo3" = 1) + width = 40 + height = 80 + count = 1000 + spawning = 3 + lifespan = 1 SECONDS + fade = 1 SECONDS + friction = 0.5 + position = generator(GEN_SPHERE, 12, 12, NORMAL_RAND) + drift = generator(GEN_VECTOR, list(-1, 1), list(1, 1), NORMAL_RAND) + color = COLOR_MAGENTA + +/particles/teleport_flux/small + spawning = 1.5 + scale = 0.75 + lifespan = 0.5 SECONDS + position = generator(GEN_SPHERE, 4, 12, NORMAL_RAND) + drift = generator(GEN_VECTOR, list(-1, 1), list(1, 2), NORMAL_RAND) diff --git a/code/modules/asset_cache/assets/achievements.dm b/code/modules/asset_cache/assets/achievements.dm index 1ba7b91af92b9..91f2d75b6d581 100644 --- a/code/modules/asset_cache/assets/achievements.dm +++ b/code/modules/asset_cache/assets/achievements.dm @@ -1,5 +1,11 @@ /datum/asset/spritesheet/simple/achievements - name ="achievements" + name = "achievements" /datum/asset/spritesheet/simple/achievements/create_spritesheets() - InsertAll("", ACHIEVEMENTS_SET) + InsertAll("achievement", ACHIEVEMENTS_SET) + // catch achievements which are pulling icons from another file + for(var/datum/award/other_award as anything in subtypesof(/datum/award)) + var/icon = initial(other_award.icon) + if (icon != ACHIEVEMENTS_SET) + var/icon_state = initial(other_award.icon_state) + Insert("achievement-[icon_state]", icon, icon_state=icon_state) diff --git a/code/modules/atmospherics/machinery/atmosmachinery.dm b/code/modules/atmospherics/machinery/atmosmachinery.dm index 0429b92377e0d..ce70c93a558bb 100644 --- a/code/modules/atmospherics/machinery/atmosmachinery.dm +++ b/code/modules/atmospherics/machinery/atmosmachinery.dm @@ -280,8 +280,8 @@ * * given_layer - the piping_layer we are checking */ /obj/machinery/atmospherics/proc/connection_check(obj/machinery/atmospherics/target, given_layer) - //if target is not multiz then we have to check if the target & src connect in the same direction - if(!istype(target, /obj/machinery/atmospherics/pipe/multiz) && !((initialize_directions & get_dir(src, target)) && (target.initialize_directions & get_dir(target, src)))) + //check if the target & src connect in the same direction + if(!((initialize_directions & get_dir(src, target)) && (target.initialize_directions & get_dir(target, src)))) return FALSE //both target & src can't be connected either way diff --git a/code/modules/atmospherics/machinery/components/components_base.dm b/code/modules/atmospherics/machinery/components/components_base.dm index 931a952658c40..130c144d42439 100644 --- a/code/modules/atmospherics/machinery/components/components_base.dm +++ b/code/modules/atmospherics/machinery/components/components_base.dm @@ -268,6 +268,10 @@ if(!.) return FALSE set_init_directions() + reconnect_nodes() + return TRUE + +/obj/machinery/atmospherics/components/proc/reconnect_nodes() for(var/i in 1 to device_type) var/obj/machinery/atmospherics/node = nodes[i] if(node) @@ -285,7 +289,6 @@ node.add_member(src) update_parents() SSair.add_to_rebuild_queue(src) - return TRUE /** * Disconnects all nodes from ourselves, remove us from the node's nodes. diff --git a/code/modules/atmospherics/machinery/components/unary_devices/thermomachine.dm b/code/modules/atmospherics/machinery/components/unary_devices/thermomachine.dm index 5067dcddae2bf..5c894274619ad 100644 --- a/code/modules/atmospherics/machinery/components/unary_devices/thermomachine.dm +++ b/code/modules/atmospherics/machinery/components/unary_devices/thermomachine.dm @@ -129,7 +129,7 @@ if(!initial(icon)) return var/mutable_appearance/thermo_overlay = new(initial(icon)) - . += get_pipe_image(thermo_overlay, "pipe", dir, COLOR_LIME, piping_layer) + . += get_pipe_image(thermo_overlay, "pipe", dir, pipe_color, piping_layer) /obj/machinery/atmospherics/components/unary/thermomachine/examine(mob/user) . = ..() @@ -222,6 +222,8 @@ return ITEM_INTERACT_SUCCESS piping_layer = (piping_layer >= PIPING_LAYER_MAX) ? PIPING_LAYER_MIN : (piping_layer + 1) to_chat(user, span_notice("You change the circuitboard to layer [piping_layer].")) + if(anchored) + reconnect_nodes() update_appearance() return ITEM_INTERACT_SUCCESS @@ -233,6 +235,8 @@ set_pipe_color(GLOB.pipe_paint_colors[GLOB.pipe_paint_colors[color_index]]) visible_message(span_notice("[user] set [src]'s pipe color to [GLOB.pipe_color_name[pipe_color]]."), ignored_mobs = user) to_chat(user, span_notice("You set [src]'s pipe color to [GLOB.pipe_color_name[pipe_color]].")) + if(anchored) + reconnect_nodes() update_appearance() return ITEM_INTERACT_SUCCESS diff --git a/code/modules/atmospherics/machinery/pipes/multiz.dm b/code/modules/atmospherics/machinery/pipes/multiz.dm index 7e14b8a98063e..ebe295313161e 100644 --- a/code/modules/atmospherics/machinery/pipes/multiz.dm +++ b/code/modules/atmospherics/machinery/pipes/multiz.dm @@ -9,7 +9,7 @@ initialize_directions = SOUTH layer = HIGH_OBJ_LAYER - device_type = UNARY + device_type = TRINARY paintable = FALSE construction_type = /obj/item/pipe/directional @@ -54,8 +54,8 @@ for(var/obj/machinery/atmospherics/pipe/multiz/above in GET_TURF_ABOVE(local_turf)) if(!is_connectable(above, piping_layer)) continue - nodes += above - above.nodes += src //Two way travel :) + nodes[2] = above + above.nodes[3] = src //Two way travel :) for(var/obj/machinery/atmospherics/pipe/multiz/below in GET_TURF_BELOW(local_turf)) if(!is_connectable(below, piping_layer)) continue diff --git a/code/modules/client/client_defines.dm b/code/modules/client/client_defines.dm index 15a8e4454fc1e..45ccda8b92bd1 100644 --- a/code/modules/client/client_defines.dm +++ b/code/modules/client/client_defines.dm @@ -240,6 +240,9 @@ var/list/keys_held = list() /// A buffer for combinations such of modifiers + keys (ex: CtrlD, AltE, ShiftT). Format: `"key"` -> `"combo"` (ex: `"D"` -> `"CtrlD"`) var/list/key_combos_held = list() + /// The direction we WANT to move, based off our keybinds + /// Will be udpated to be the actual direction later on + var/intended_direction = NONE /* ** These next two vars are to apply movement for keypresses and releases made while move delayed. ** Because discarding that input makes the game less responsive. diff --git a/code/modules/client/client_procs.dm b/code/modules/client/client_procs.dm index 3c0b5aa1db3b0..5de1341358230 100644 --- a/code/modules/client/client_procs.dm +++ b/code/modules/client/client_procs.dm @@ -1012,6 +1012,7 @@ GLOBAL_LIST_INIT(blacklisted_builds, list( winset(src, "default-[REF(key)]", "parent=default;name=[key];command=[asay]") else winset(src, "default-[REF(key)]", "parent=default;name=[key];command=") + calculate_move_dir() /client/proc/change_view(new_size) if (isnull(new_size)) diff --git a/code/modules/keybindings/bindings_atom.dm b/code/modules/keybindings/bindings_atom.dm index 6dadcd5768ee3..e9e38489a4df3 100644 --- a/code/modules/keybindings/bindings_atom.dm +++ b/code/modules/keybindings/bindings_atom.dm @@ -2,12 +2,18 @@ // Only way to do that is to tie the behavior into the focus's keyLoop(). /atom/movable/keyLoop(client/user) - var/movement_dir = NONE - for(var/_key in user?.keys_held) - movement_dir = movement_dir | user.movement_keys[_key] - if(user?.next_move_dir_add) - movement_dir |= user.next_move_dir_add - if(user?.next_move_dir_sub) + // Clients don't go null randomly. They do go null unexpectedly though, when they're poked in particular ways + // keyLoop is called by a for loop over mobs. We're guarenteed that all the mobs have clients at the START + // But the move of one mob might poke the client of another, so we do this + if(!user) + return FALSE + var/movement_dir = user.intended_direction | user.next_move_dir_add + // If we're not movin anywhere, we aren't movin anywhere + // Safe because nothing adds to movement_dir after this moment + if(!movement_dir) + return FALSE + + if(user.next_move_dir_sub) movement_dir &= ~user.next_move_dir_sub // Sanity checks in case you hold left and right and up to make sure you only go up if((movement_dir & NORTH) && (movement_dir & SOUTH)) @@ -15,14 +21,21 @@ if((movement_dir & EAST) && (movement_dir & WEST)) movement_dir &= ~(EAST|WEST) - if(user && movement_dir) //If we're not moving, don't compensate, as byond will auto-fill dir otherwise + if(user.dir != NORTH && movement_dir) //If we're not moving, don't compensate, as byond will auto-fill dir otherwise movement_dir = turn(movement_dir, -dir2angle(user.dir)) //By doing this we ensure that our input direction is offset by the client (camera) direction //turn without moving while using the movement lock key, unless something wants to ignore it and move anyway - if(user?.movement_locked && !(SEND_SIGNAL(src, COMSIG_MOVABLE_KEYBIND_FACE_DIR, movement_dir) & COMSIG_IGNORE_MOVEMENT_LOCK)) + if(user.movement_locked && !(SEND_SIGNAL(src, COMSIG_MOVABLE_KEYBIND_FACE_DIR, movement_dir) & COMSIG_IGNORE_MOVEMENT_LOCK)) keybind_face_direction(movement_dir) - else - user?.Move(get_step(src, movement_dir), movement_dir) + // Null check cause of the signal above + else if(user) + user.Move(get_step(src, movement_dir), movement_dir) return !!movement_dir //true if there was actually any player input return FALSE + +/client/proc/calculate_move_dir() + var/movement_dir = NONE + for(var/_key in keys_held) + movement_dir |= movement_keys[_key] + intended_direction = movement_dir diff --git a/code/modules/keybindings/bindings_client.dm b/code/modules/keybindings/bindings_client.dm index 0aa0fd6952ed2..0a8cc20b38fe5 100644 --- a/code/modules/keybindings/bindings_client.dm +++ b/code/modules/keybindings/bindings_client.dm @@ -47,9 +47,10 @@ //the time a key was pressed isn't actually used anywhere (as of 2019-9-10) but this allows easier access usage/checking keys_held[_key] = world.time - if(!movement_locked) - var/movement = movement_keys[_key] - if(!(next_move_dir_sub & movement)) + var/movement = movement_keys[_key] + if(movement) + calculate_move_dir() + if(!movement_locked && !(next_move_dir_sub & movement)) next_move_dir_add |= movement // Client-level keybindings are ones anyone should be able to do at any time @@ -93,9 +94,10 @@ keys_held -= _key - if(!movement_locked) - var/movement = movement_keys[_key] - if(!(next_move_dir_add & movement)) + var/movement = movement_keys[_key] + if(movement) + calculate_move_dir() + if(!movement_locked && !(next_move_dir_add & movement)) next_move_dir_sub |= movement // We don't do full key for release, because for mod keys you diff --git a/code/modules/mining/satchel_ore_box.dm b/code/modules/mining/satchel_ore_box.dm index 7a82b9483a042..3b2a5ce054c1d 100644 --- a/code/modules/mining/satchel_ore_box.dm +++ b/code/modules/mining/satchel_ore_box.dm @@ -5,58 +5,68 @@ icon = 'icons/obj/mining.dmi' icon_state = "orebox" name = "ore box" - desc = "A heavy wooden box, which can be filled with a lot of ores." + desc = "A heavy wooden box, which can be filled with a lot of ores or boulders" density = TRUE - pressure_resistance = 5*ONE_ATMOSPHERE - -/obj/structure/ore_box/attackby(obj/item/W, mob/user, params) - if (istype(W, /obj/item/stack/ore) || istype(W, /obj/item/boulder)) - if(!user.transferItemToLoc(W, src)) - return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN - else if(W.atom_storage) - W.atom_storage.remove_type(/obj/item/stack/ore, src, INFINITY, TRUE, FALSE, user, null) - to_chat(user, span_notice("You empty the ore in [W] into \the [src].")) - else - return ..() + pressure_resistance = 5 * ONE_ATMOSPHERE -/obj/structure/ore_box/crowbar_act(mob/living/user, obj/item/I) - if(I.use_tool(src, user, 50, volume=50)) - user.visible_message(span_notice("[user] pries \the [src] apart."), - span_notice("You pry apart \the [src]."), - span_hear("You hear splitting wood.")) - deconstruct(TRUE, user) - return TRUE - -/obj/structure/ore_box/examine(mob/living/user) - if(Adjacent(user) && istype(user)) - ui_interact(user) +/obj/structure/ore_box/Initialize(mapload) . = ..() + register_context() -/obj/structure/ore_box/attack_hand(mob/user, list/modifiers) - . = ..() - if(.) +///Dumps all contents of this ore box on the turf +/obj/structure/ore_box/proc/dump_box_contents() + var/drop = drop_location() + for(var/obj/item/weapon in src) + weapon.forceMove(drop) + +/obj/structure/ore_box/deconstruct(disassembled = TRUE) + new /obj/item/stack/sheet/mineral/wood(loc, 4) + + dump_box_contents() + + return ..() + +/obj/structure/ore_box/add_context(atom/source, list/context, obj/item/held_item, mob/user) + . = NONE + if(isnull(held_item)) return - if(Adjacent(user)) - ui_interact(user) -/obj/structure/ore_box/attack_robot(mob/user) - if(Adjacent(user)) + if(held_item.tool_behaviour == TOOL_CROWBAR) + context[SCREENTIP_CONTEXT_LMB] = "Deconstruct" + return CONTEXTUAL_SCREENTIP_SET + else if(istype(held_item, /obj/item/stack/ore) || istype(held_item, /obj/item/boulder)) + context[SCREENTIP_CONTEXT_LMB] = "Insert Item" + return CONTEXTUAL_SCREENTIP_SET + else if(held_item.atom_storage) + context[SCREENTIP_CONTEXT_LMB] = "Transfer Contents" + return CONTEXTUAL_SCREENTIP_SET + + +/obj/structure/ore_box/examine(mob/living/user) + . = ..() + if(in_range(src, user) || isobserver(user)) + . += span_notice("Can be [EXAMINE_HINT("pried")] apart.") ui_interact(user) -/obj/structure/ore_box/proc/dump_box_contents() - var/drop = drop_location() - var/turf/our_turf = get_turf(src) - for(var/obj/item/O in src) - if(QDELETED(O)) - continue - if(QDELETED(src)) - break - O.forceMove(drop) - SET_PLANE(O, PLANE_TO_TRUE(O.plane), our_turf) - if(TICK_CHECK) - stoplag() - our_turf = get_turf(src) - drop = drop_location() +/obj/structure/ore_box/crowbar_act(mob/living/user, obj/item/I) + . = ITEM_INTERACT_BLOCKING + if(I.use_tool(src, user, 50, volume = 50)) + user.visible_message(span_notice("[user] pries \the [src] apart."), + span_notice("You pry apart \the [src]."), + span_hear("You hear splitting wood.")) + deconstruct(TRUE) + return ITEM_INTERACT_SUCCESS + +/obj/structure/ore_box/attackby(obj/item/weapon, mob/user, params) + if(istype(weapon, /obj/item/stack/ore) || istype(weapon, /obj/item/boulder)) + user.transferItemToLoc(weapon, src) + return TRUE + else if(weapon.atom_storage) + weapon.atom_storage.remove_type(/obj/item/stack/ore, src, INFINITY, TRUE, FALSE, user, null) + to_chat(user, span_notice("You empty the ore in [weapon] into \the [src].")) + return TRUE + else + return ..() /obj/structure/ore_box/ui_interact(mob/user, datum/tgui/ui) ui = SStgui.try_update_ui(user, src, ui) @@ -65,43 +75,36 @@ ui.open() /obj/structure/ore_box/ui_data() - var/item_contents = list() - var/boulder_count = 0 + var/list/materials = list() + var/name + var/amount for(var/obj/item/stack/ore/potental_ore as anything in contents) if(istype(potental_ore, /obj/item/stack/ore)) - item_contents[potental_ore.type] += potental_ore.amount + name = potental_ore.name + amount = potental_ore.amount else - boulder_count++ + name = "Boulders" + amount = 1 - var/data = list() + var/item_found = FALSE + for(var/list/item as anything in materials) + if(item["name"] == name) + item_found = TRUE + item["amount"] += amount + break + if(!item_found) + materials += list(list("name" = name, "amount" = amount)) - data["materials"] = list() - - for(var/obj/item/stone as anything in item_contents) - if(ispath(stone, /obj/item/stack/ore)) - var/obj/item/stack/ore/found_ore = stone - var/name = initial(found_ore.name) - data["materials"] += list(list("name" = name, "amount" = item_contents[stone], "id" = type)) - data["boulders"] = boulder_count - return data + return list("materials" = materials) /obj/structure/ore_box/ui_act(action, params) . = ..() if(.) return - if(!Adjacent(usr)) - return - switch(action) - if("removeall") - dump_box_contents() - to_chat(usr, span_notice("You open the release hatch on the box..")) - -/obj/structure/ore_box/deconstruct(disassembled = TRUE, mob/user) - var/obj/item/stack/sheet/mineral/wood/WD = new (loc, 4) - if(user && !QDELETED(WD)) - WD.add_fingerprint(user) - dump_box_contents() - qdel(src) + + if(action == "removeall") + dump_box_contents() + return TRUE /// Special override for notify_contents = FALSE. /obj/structure/ore_box/on_changed_z_level(turf/old_turf, turf/new_turf, same_z_layer, notify_contents = FALSE) diff --git a/code/modules/mob/living/basic/blob_minions/blob_zombie.dm b/code/modules/mob/living/basic/blob_minions/blob_zombie.dm index c9bf3b7346a98..3cbce54cf29db 100644 --- a/code/modules/mob/living/basic/blob_minions/blob_zombie.dm +++ b/code/modules/mob/living/basic/blob_minions/blob_zombie.dm @@ -51,13 +51,13 @@ . = ..() death() -/mob/living/basic/blob_minion/zombie/update_overlays() - . = ..() +//Sets up our appearance +/mob/living/basic/blob_minion/zombie/proc/set_up_zombie_appearance() copy_overlays(corpse, TRUE) var/mutable_appearance/blob_head_overlay = mutable_appearance('icons/mob/nonhuman-player/blob.dmi', "blob_head") blob_head_overlay.color = LAZYACCESS(atom_colours, FIXED_COLOUR_PRIORITY) || COLOR_WHITE color = initial(color) // reversing what our component did lol, but we needed the value for the overlay - . += blob_head_overlay + overlays += blob_head_overlay /// Create an explosion of spores on death /mob/living/basic/blob_minion/zombie/proc/death_burst() @@ -73,6 +73,7 @@ new_corpse.forceMove(src) corpse = new_corpse update_appearance(UPDATE_ICON) + set_up_zombie_appearance() RegisterSignal(corpse, COMSIG_LIVING_REVIVE, PROC_REF(on_corpse_revived)) /// Dynamic changeling reentry diff --git a/code/modules/mob/living/basic/drone/_drone.dm b/code/modules/mob/living/basic/drone/_drone.dm index 76f09318b7acb..9298083c67c21 100644 --- a/code/modules/mob/living/basic/drone/_drone.dm +++ b/code/modules/mob/living/basic/drone/_drone.dm @@ -161,6 +161,12 @@ /obj/item/clothing/mask, /obj/item/storage/box/lights, /obj/item/lightreplacer, + /obj/item/construction/rcd, + /obj/item/rcd_ammo, + /obj/item/rcd_upgrade, + /obj/item/storage/part_replacer, + /obj/item/soap, + /obj/item/holosign_creator, ) /// machines whitelisted from being shy with var/list/shy_machine_whitelist = list( diff --git a/code/modules/mob/living/basic/pets/cat/cat.dm b/code/modules/mob/living/basic/pets/cat/cat.dm index 207599a1d164a..dd8a588e91502 100644 --- a/code/modules/mob/living/basic/pets/cat/cat.dm +++ b/code/modules/mob/living/basic/pets/cat/cat.dm @@ -134,6 +134,7 @@ icon_state = "spacecat" icon_living = "spacecat" icon_dead = "spacecat_dead" + unsuitable_atmos_damage = 0 minimum_survivable_temperature = TCMB maximum_survivable_temperature = T0C + 40 held_state = "spacecat" diff --git a/code/modules/mob/living/carbon/human/emote.dm b/code/modules/mob/living/carbon/human/emote.dm index a7be681a22e2f..b205eb2e2e217 100644 --- a/code/modules/mob/living/carbon/human/emote.dm +++ b/code/modules/mob/living/carbon/human/emote.dm @@ -81,10 +81,14 @@ only_forced_audio = TRUE vary = TRUE +/datum/emote/carbon/human/scream/run_emote(mob/user, params, type_override, intentional = FALSE) + if(!intentional && HAS_TRAIT(user, TRAIT_ANALGESIA)) + return + return ..() + /datum/emote/living/carbon/human/scream/get_sound(mob/living/carbon/human/user) if(!istype(user)) return - return user.dna.species.get_scream_sound(user) /datum/emote/living/carbon/human/scream/screech //If a human tries to screech it'll just scream. diff --git a/code/modules/mob/living/emote.dm b/code/modules/mob/living/emote.dm index db8302b49dfa9..5c13e489395b1 100644 --- a/code/modules/mob/living/emote.dm +++ b/code/modules/mob/living/emote.dm @@ -342,6 +342,11 @@ emote_type = EMOTE_VISIBLE | EMOTE_AUDIBLE mob_type_blacklist_typecache = list(/mob/living/carbon/human) //Humans get specialized scream. +/datum/emote/living/scream/run_emote(mob/user, params, type_override, intentional = FALSE) + if(!intentional && HAS_TRAIT(user, TRAIT_ANALGESIA)) + return + return ..() + /datum/emote/living/scream/select_message_type(mob/user, message, intentional) . = ..() if(!intentional && isanimal_or_basicmob(user)) diff --git a/code/modules/mob/living/silicon/ai/ai.dm b/code/modules/mob/living/silicon/ai/ai.dm index 23de5d9417f5d..041d964f5dc50 100644 --- a/code/modules/mob/living/silicon/ai/ai.dm +++ b/code/modules/mob/living/silicon/ai/ai.dm @@ -77,7 +77,7 @@ var/mob/camera/ai_eye/eyeobj var/sprint = 10 - var/cooldown = 0 + var/last_moved = 0 var/acceleration = TRUE var/obj/structure/ai_core/deactivated/linked_core //For exosuit control @@ -191,7 +191,8 @@ builtInCamera.network = list("ss13") ai_tracking_tool = new(src) - RegisterSignal(src, COMSIG_TRACKABLE_TRACKING_TARGET, PROC_REF(on_track_target)) + RegisterSignal(ai_tracking_tool, COMSIG_TRACKABLE_TRACKING_TARGET, PROC_REF(on_track_target)) + RegisterSignal(ai_tracking_tool, COMSIG_TRACKABLE_GLIDE_CHANGED, PROC_REF(tracked_glidesize_changed)) add_traits(list(TRAIT_PULL_BLOCKED, TRAIT_HANDS_BLOCKED), ROUNDSTART_TRAIT) @@ -211,8 +212,7 @@ switch(_key) if("`", "0") if(cam_prev) - if(ai_tracking_tool.tracking) - ai_tracking_tool.set_tracking(FALSE) + ai_tracking_tool.reset_tracking() eyeobj.setLoc(cam_prev) return if("1", "2", "3", "4", "5", "6", "7", "8", "9") @@ -223,8 +223,7 @@ return if(cam_hotkeys[_key]) //if this is false, no hotkey for this slot exists. cam_prev = eyeobj.loc - if(ai_tracking_tool.tracking) - ai_tracking_tool.set_tracking(FALSE) + ai_tracking_tool.reset_tracking() eyeobj.setLoc(cam_hotkeys[_key]) return return ..() @@ -250,7 +249,6 @@ if(ai_voicechanger) ai_voicechanger.owner = null ai_voicechanger = null - UnregisterSignal(src, COMSIG_TRACKABLE_TRACKING_TARGET) return ..() /// Removes all malfunction-related abilities from the AI @@ -401,7 +399,7 @@ set name = "track" set hidden = TRUE //Don't display it on the verb lists. This verb exists purely so you can type "track Oldman Robustin" and follow his ass - ai_tracking_tool.set_tracked_mob(src) + ai_tracking_tool.track_input(src) ///Called when an AI finds their tracking target. /mob/living/silicon/ai/proc/on_track_target(datum/trackable/source, mob/living/target) @@ -411,6 +409,12 @@ else view_core() +/// Keeps our rate of gliding in step with the mob we're following +/mob/living/silicon/ai/proc/tracked_glidesize_changed(datum/trackable/source, mob/living/target, new_glide_size) + SIGNAL_HANDLER + if(eyeobj) + eyeobj.glide_size = new_glide_size + /mob/living/silicon/ai/verb/toggle_anchor() set category = "AI Commands" set name = "Toggle Floor Bolts" @@ -524,7 +528,7 @@ else to_chat(src, span_notice("Unable to project to the holopad.")) if(href_list["track"]) - ai_tracking_tool.set_tracked_mob(src, href_list["track"]) + ai_tracking_tool.track_name(src, href_list["track"]) return if (href_list["ai_take_control"]) //Mech domination var/obj/vehicle/sealed/mecha/M = locate(href_list["ai_take_control"]) in GLOB.mechas_list @@ -567,8 +571,7 @@ view_core() return - if(ai_tracking_tool.tracking) - ai_tracking_tool.set_tracking(FALSE) + ai_tracking_tool.reset_tracking() // ok, we're alive, camera is good and in our network... eyeobj.setLoc(get_turf(C)) @@ -642,8 +645,7 @@ set category = "AI Commands" set name = "Jump To Network" unset_machine() - if(ai_tracking_tool.tracking) - ai_tracking_tool.set_tracking(FALSE) + ai_tracking_tool.reset_tracking() var/cameralist[0] if(incapacitated()) diff --git a/code/modules/mob/living/silicon/ai/freelook/eye.dm b/code/modules/mob/living/silicon/ai/freelook/eye.dm index 416bbb19912e8..e8c1919b020f9 100644 --- a/code/modules/mob/living/silicon/ai/freelook/eye.dm +++ b/code/modules/mob/living/silicon/ai/freelook/eye.dm @@ -154,35 +154,44 @@ return var/mob/living/silicon/ai/AI = usr if(AI.eyeobj && (AI.multicam_on || (AI.client.eye == AI.eyeobj)) && (AI.eyeobj.z == z)) - if(AI.ai_tracking_tool.tracking) - AI.ai_tracking_tool.set_tracking(FALSE) + AI.ai_tracking_tool.reset_tracking() if (isturf(loc) || isturf(src)) AI.eyeobj.setLoc(src) // This will move the AIEye. It will also cause lights near the eye to light up, if toggled. // This is handled in the proc below this one. - -/client/proc/AIMove(n, direct, mob/living/silicon/ai/user) - - var/initial = initial(user.sprint) - var/max_sprint = 50 - - if(user.cooldown && user.cooldown < world.timeofday) // 3 seconds - user.sprint = initial - - for(var/i = 0; i < max(user.sprint, initial); i += 20) - var/turf/step = get_turf(get_step(user.eyeobj, direct)) +#define SPRINT_PER_TICK 0.5 +#define MAX_SPRINT 50 +#define SPRINT_PER_STEP 20 +/mob/living/silicon/ai/proc/AIMove(direction) + if(last_moved && last_moved + 1 < world.timeofday) + // Decay sprint based off how long it took us to input this next move + var/missed_sprint = max((world.timeofday + 1) - last_moved, 0) * SPRINT_PER_TICK + sprint = max(sprint - missed_sprint * 7, initial(sprint)) + + // We move a full step, at least. Can't glide more with our current movement mode, so this is how I have to live + var/step_count = 0 + for(var/i = 0; i < max(sprint, initial(sprint)); i += SPRINT_PER_STEP) + step_count += 1 + var/turf/step = get_turf(get_step(eyeobj, direction)) if(step) - user.eyeobj.setLoc(step) + eyeobj.setLoc(step) + + // I'd like to make this scale with the steps we take, but it like, just can't + // So we're doin this instead + eyeobj.glide_size = world.icon_size - user.cooldown = world.timeofday + 5 - if(user.acceleration) - user.sprint = min(user.sprint + 0.5, max_sprint) + last_moved = world.timeofday + if(acceleration) + sprint = min(sprint + SPRINT_PER_TICK, MAX_SPRINT) else - user.sprint = initial + sprint = initial(sprint) + + ai_tracking_tool.reset_tracking() - if(user.ai_tracking_tool.tracking) - user.ai_tracking_tool.set_tracking(FALSE) +#undef SPRINT_PER_STEP +#undef MAX_SPRINT +#undef SPRINT_PER_TICK // Return to the Core. /mob/living/silicon/ai/proc/view_core() @@ -191,8 +200,8 @@ H.clear_holo(src) else current = null - if(ai_tracking_tool && ai_tracking_tool.tracking) - ai_tracking_tool.set_tracking(FALSE) + if(ai_tracking_tool) + ai_tracking_tool.reset_tracking() unset_machine() if(isturf(loc) && (QDELETED(eyeobj) || !eyeobj.loc)) diff --git a/code/modules/mob/mob_movement.dm b/code/modules/mob/mob_movement.dm index 9b62bd0774331..c54d0fd7c33d0 100644 --- a/code/modules/mob/mob_movement.dm +++ b/code/modules/mob/mob_movement.dm @@ -76,7 +76,8 @@ return mob.remote_control.relaymove(mob, direct) if(isAI(mob)) - return AIMove(new_loc,direct,mob) + var/mob/living/silicon/ai/smoovin_ai = mob + return smoovin_ai.AIMove(direct) if(Process_Grab()) //are we restrained by someone's grip? return diff --git a/code/modules/modular_computers/file_system/programs/secureye.dm b/code/modules/modular_computers/file_system/programs/secureye.dm index c9e4fc087f364..2b3b8f6ea8c95 100644 --- a/code/modules/modular_computers/file_system/programs/secureye.dm +++ b/code/modules/modular_computers/file_system/programs/secureye.dm @@ -61,7 +61,6 @@ cam_background = new cam_background.assigned_map = map_name cam_background.del_on_map_removal = FALSE - RegisterSignal(src, COMSIG_TRACKABLE_TRACKING_TARGET, PROC_REF(on_track_target)) /datum/computer_file/program/secureye/Destroy() QDEL_NULL(cam_screen) @@ -138,8 +137,8 @@ playsound(computer, get_sfx(SFX_TERMINAL_TYPE), 25, FALSE) if(isnull(camera_ref)) return TRUE - if(internal_tracker && internal_tracker.tracking) - internal_tracker.set_tracking(FALSE) + if(internal_tracker) + internal_tracker.reset_tracking() update_active_camera_screen() return TRUE @@ -147,7 +146,8 @@ if("start_tracking") if(!internal_tracker) internal_tracker = new(src) - internal_tracker.set_tracked_mob(usr) + RegisterSignal(internal_tracker, COMSIG_TRACKABLE_TRACKING_TARGET, PROC_REF(on_track_target)) + internal_tracker.track_input(usr) return TRUE /datum/computer_file/program/secureye/proc/on_track_target(datum/trackable/source, mob/living/target) @@ -169,8 +169,8 @@ /datum/computer_file/program/secureye/ui_close(mob/user) . = ..() //don't track anyone while we're shutting off. - if(internal_tracker && internal_tracker.tracking) - internal_tracker.set_tracking(FALSE) + if(internal_tracker) + internal_tracker.reset_tracking() var/user_ref = REF(user) var/is_living = isliving(user) // Living creature or not, we remove you anyway. diff --git a/code/modules/reagents/chemistry/holder/holder.dm b/code/modules/reagents/chemistry/holder/holder.dm index a4e149a2bc862..e6a861b851d33 100644 --- a/code/modules/reagents/chemistry/holder/holder.dm +++ b/code/modules/reagents/chemistry/holder/holder.dm @@ -333,6 +333,25 @@ handle_reactions() return round(total_removed_amount, CHEMICAL_VOLUME_ROUNDING) +/** + * Like remove_all but removes a percentage of every reagent directly rather than by volume + * + * Arguments + * * percentage - the percentage of each reagent to remove + */ +/datum/reagents/proc/remove_all_direct(percentage = 0.5) + if(!total_volume) + return 0 + if(percentage <= 0) + stack_trace("non positive percentage passed to remove all reagents direct [percentage]") + return 0 + var/total_removed_amount = 0 + for(var/datum/reagent/reagent as anything in reagent_list) + total_removed_amount += remove_reagent(reagent.type, reagent.volume * percentage) + + handle_reactions() + return round(total_removed_amount, CHEMICAL_VOLUME_ROUNDING) + /** * Removes an specific reagent from this holder * Arguments diff --git a/code/modules/reagents/chemistry/reagents.dm b/code/modules/reagents/chemistry/reagents.dm index 714b2ac21979f..f51532b28b19d 100644 --- a/code/modules/reagents/chemistry/reagents.dm +++ b/code/modules/reagents/chemistry/reagents.dm @@ -74,6 +74,10 @@ /// The affected respiration type, if the reagent damages/heals oxygen damage of an affected mob. /// See "Mob bio-types flags" in /code/_DEFINES/mobs.dm var/affected_respiration_type = ALL + /// A list of traits to apply while the reagent is being metabolized. + var/list/metabolized_traits + /// A list of traits to apply while the reagent is in a mob. + var/list/added_traits ///The default reagent container for the reagent, used for icon generation var/obj/item/reagent_containers/default_container = /obj/item/reagent_containers/cup/bottle @@ -191,20 +195,24 @@ Primarily used in reagents/reaction_agents /// Called when this reagent is first added to a mob /datum/reagent/proc/on_mob_add(mob/living/affected_mob, amount) overdose_threshold /= max(normalise_creation_purity(), 1) //Maybe??? Seems like it would help pure chems be even better but, if I normalised this to 1, then everything would take a 25% reduction - return + if(added_traits) + affected_mob.add_traits(added_traits, "base:[type]") /// Called when this reagent is removed while inside a mob /datum/reagent/proc/on_mob_delete(mob/living/affected_mob) affected_mob.clear_mood_event("[type]_overdose") - return + REMOVE_TRAITS_IN(affected_mob, "base:[type]") /// Called when this reagent first starts being metabolized by a liver /datum/reagent/proc/on_mob_metabolize(mob/living/affected_mob) - return + SHOULD_CALL_PARENT(TRUE) + if(metabolized_traits) + affected_mob.add_traits(metabolized_traits, "metabolize:[type]") /// Called when this reagent stops being metabolized by a liver /datum/reagent/proc/on_mob_end_metabolize(mob/living/affected_mob) - return + SHOULD_CALL_PARENT(TRUE) + REMOVE_TRAITS_IN(affected_mob, "metabolize:[type]") /** * Called when a reagent is inside of a mob when they are dead if the reagent has the REAGENT_DEAD_PROCESS flag diff --git a/code/modules/reagents/chemistry/reagents/atmos_gas_reagents.dm b/code/modules/reagents/chemistry/reagents/atmos_gas_reagents.dm index 7b13b2d28b1d2..1406e37369359 100644 --- a/code/modules/reagents/chemistry/reagents/atmos_gas_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/atmos_gas_reagents.dm @@ -23,16 +23,15 @@ color = "90560B" taste_description = "minty" chemical_flags = REAGENT_CAN_BE_SYNTHESIZED|REAGENT_NO_RANDOM_RECIPE + metabolized_traits = list(TRAIT_RESISTHEAT) /datum/reagent/halon/on_mob_metabolize(mob/living/breather) . = ..() breather.add_movespeed_modifier(/datum/movespeed_modifier/reagent/halon) - ADD_TRAIT(breather, TRAIT_RESISTHEAT, type) /datum/reagent/halon/on_mob_end_metabolize(mob/living/breather) . = ..() breather.remove_movespeed_modifier(/datum/movespeed_modifier/reagent/halon) - REMOVE_TRAIT(breather, TRAIT_RESISTHEAT, type) /datum/reagent/healium name = "Healium" @@ -81,14 +80,7 @@ ph = 1.8 chemical_flags = REAGENT_CAN_BE_SYNTHESIZED|REAGENT_NO_RANDOM_RECIPE addiction_types = list(/datum/addiction/stimulants = 14) - -/datum/reagent/nitrium_high_metabolization/on_mob_metabolize(mob/living/breather) - . = ..() - ADD_TRAIT(breather, TRAIT_SLEEPIMMUNE, type) - -/datum/reagent/nitrium_high_metabolization/on_mob_end_metabolize(mob/living/breather) - . = ..() - REMOVE_TRAIT(breather, TRAIT_SLEEPIMMUNE, type) + metabolized_traits = list(TRAIT_SLEEPIMMUNE) /datum/reagent/nitrium_high_metabolization/on_mob_life(mob/living/carbon/breather, seconds_per_tick, times_fired) . = ..() diff --git a/code/modules/reagents/chemistry/reagents/cat2_medicine_reagents.dm b/code/modules/reagents/chemistry/reagents/cat2_medicine_reagents.dm index 8fb16f6333ac6..039bce7eaa8eb 100644 --- a/code/modules/reagents/chemistry/reagents/cat2_medicine_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/cat2_medicine_reagents.dm @@ -584,8 +584,10 @@ if(affected_mob.health <= (affected_mob.crit_threshold + HEALTH_THRESHOLD_FULLCRIT*(2*normalise_creation_purity()))) //certain death below this threshold REMOVE_TRAIT(affected_mob, TRAIT_STABLEHEART, type) //we have to remove the stable heart trait before we give them a heart attack - to_chat(affected_mob,span_danger("You feel something rupturing inside your chest!")) - affected_mob.emote("scream") + affected_mob.remove_traits(subject_traits, type) + to_chat(affected_mob, span_danger("You feel something rupturing inside your chest!")) + if(!HAS_TRAIT(affected_mob, TRAIT_ANALGESIA)) + affected_mob.emote("scream") affected_mob.set_heartattack(TRUE) volume = 0 if(need_mob_update) diff --git a/code/modules/reagents/chemistry/reagents/drinks/alcohol_reagents.dm b/code/modules/reagents/chemistry/reagents/drinks/alcohol_reagents.dm index 2cc88da41ade8..87033589812cb 100644 --- a/code/modules/reagents/chemistry/reagents/drinks/alcohol_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/drinks/alcohol_reagents.dm @@ -158,6 +158,7 @@ drinker.add_atom_colour(color, TEMPORARY_COLOUR_PRIORITY) /datum/reagent/consumable/ethanol/beer/green/on_mob_end_metabolize(mob/living/drinker) + . = ..() drinker.remove_atom_colour(TEMPORARY_COLOUR_PRIORITY, color) /datum/reagent/consumable/ethanol/beer/green/overdose_process(mob/living/affected_mob, seconds_per_tick, times_fired) @@ -684,6 +685,7 @@ taste_description = "alcoholic bravery" chemical_flags = REAGENT_CAN_BE_SYNTHESIZED glass_price = DRINK_PRICE_EASY + metabolized_traits = list(TRAIT_FEARLESS, TRAIT_ANALGESIA) var/tough_text /datum/reagent/consumable/ethanol/brave_bull/on_mob_metabolize(mob/living/drinker) @@ -692,14 +694,12 @@ to_chat(drinker, span_notice("You feel [tough_text]!")) drinker.maxHealth += 10 //Brave Bull makes you sturdier, and thus capable of withstanding a tiny bit more punishment. drinker.health += 10 - ADD_TRAIT(drinker, TRAIT_FEARLESS, type) /datum/reagent/consumable/ethanol/brave_bull/on_mob_end_metabolize(mob/living/drinker) . = ..() to_chat(drinker, span_notice("You no longer feel [tough_text].")) drinker.maxHealth -= 10 drinker.health = min(drinker.health - 10, drinker.maxHealth) //This can indeed crit you if you're alive solely based on alchol ingestion - REMOVE_TRAIT(drinker, TRAIT_FEARLESS, type) /datum/reagent/consumable/ethanol/tequila_sunrise name = "Tequila Sunrise" @@ -1073,15 +1073,11 @@ quality = DRINK_VERYGOOD taste_description = "concentrated matter" chemical_flags = REAGENT_CAN_BE_SYNTHESIZED + metabolized_traits = list(TRAIT_MADNESS_IMMUNE) var/static/list/ray_filter = list(type = "rays", size = 40, density = 15, color = SUPERMATTER_SINGULARITY_RAYS_COLOUR, factor = 15) -/datum/reagent/consumable/ethanol/singulo/on_mob_metabolize(mob/living/drinker) - . = ..() - ADD_TRAIT(drinker, TRAIT_MADNESS_IMMUNE, type) - /datum/reagent/consumable/ethanol/singulo/on_mob_end_metabolize(mob/living/drinker) . = ..() - REMOVE_TRAIT(drinker, TRAIT_MADNESS_IMMUNE, type) drinker.remove_filter("singulo_rays") /datum/reagent/consumable/ethanol/singulo/on_mob_life(mob/living/carbon/drinker, seconds_per_tick, times_fired) @@ -2173,14 +2169,7 @@ quality = DRINK_GOOD taste_description = "artifical fruityness" chemical_flags = REAGENT_CAN_BE_SYNTHESIZED - -/datum/reagent/consumable/ethanol/rubberneck/on_mob_metabolize(mob/living/drinker) - . = ..() - ADD_TRAIT(drinker, TRAIT_SHOCKIMMUNE, type) - -/datum/reagent/consumable/ethanol/rubberneck/on_mob_end_metabolize(mob/living/drinker) - REMOVE_TRAIT(drinker, TRAIT_SHOCKIMMUNE, type) - return ..() + metabolized_traits = list(TRAIT_SHOCKIMMUNE) /datum/reagent/consumable/ethanol/duplex name = "Duplex" @@ -2260,6 +2249,7 @@ quality = DRINK_NICE taste_description = "sugary tartness" chemical_flags = REAGENT_CAN_BE_SYNTHESIZED + metabolized_traits = list(TRAIT_ANALGESIA) /datum/reagent/consumable/ethanol/pina_colada name = "Pina Colada" @@ -2642,20 +2632,13 @@ /datum/reagent/consumable/ethanol/telepole name = "Telepole" - description = "A grounding rod in the form of a drink. Recharges ethereals, and gives temporary shock resistance." + description = "A grounding rod in the form of a drink. Recharges ethereals, and gives temporary shock resistance." boozepwr = 50 color = "#b300ff" quality = DRINK_NICE taste_description = "the howling storm" chemical_flags = REAGENT_CAN_BE_SYNTHESIZED - -/datum/reagent/consumable/ethanol/telepole/on_mob_metabolize(mob/living/affected_mob) - . = ..() - ADD_TRAIT(affected_mob, TRAIT_SHOCKIMMUNE, type) - -/datum/reagent/consumable/ethanol/telepole/on_mob_end_metabolize(mob/living/affected_mob) - . = ..() - REMOVE_TRAIT(affected_mob, TRAIT_SHOCKIMMUNE, type) + metabolized_traits = list(TRAIT_SHOCKIMMUNE) /datum/reagent/consumable/ethanol/telepole/expose_mob(mob/living/exposed_mob, methods=TOUCH, reac_volume) //can't be on life because of the way blood works. . = ..() diff --git a/code/modules/reagents/chemistry/reagents/drinks/drink_reagents.dm b/code/modules/reagents/chemistry/reagents/drinks/drink_reagents.dm index 5365cea34841f..43430d0946916 100644 --- a/code/modules/reagents/chemistry/reagents/drinks/drink_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/drinks/drink_reagents.dm @@ -454,8 +454,10 @@ affected_mob.set_drugginess(1 MINUTES * REM * seconds_per_tick) affected_mob.adjust_dizzy(3 SECONDS * REM * seconds_per_tick) affected_mob.remove_status_effect(/datum/status_effect/drowsiness) - affected_mob.AdjustSleeping(-40 * REM * seconds_per_tick) + affected_mob.AdjustSleeping(-4 SECONDS * REM * seconds_per_tick) affected_mob.adjust_bodytemperature(-5 * REM * TEMPERATURE_DAMAGE_COEFFICIENT * seconds_per_tick, affected_mob.get_body_temp_normal()) + if (SSradiation.can_irradiate_basic(affected_mob)) + affected_mob.AddComponent(/datum/component/irradiated) /datum/reagent/consumable/rootbeer name = "root beer" @@ -497,19 +499,15 @@ quality = DRINK_VERYGOOD taste_description = "carbonated oil" chemical_flags = REAGENT_CAN_BE_SYNTHESIZED + metabolized_traits = list(TRAIT_SHOCKIMMUNE) /datum/reagent/consumable/grey_bull/on_mob_metabolize(mob/living/carbon/affected_atom) . = ..() - ADD_TRAIT(affected_atom, TRAIT_SHOCKIMMUNE, type) var/obj/item/organ/internal/liver/liver = affected_atom.get_organ_slot(ORGAN_SLOT_LIVER) if(HAS_TRAIT(liver, TRAIT_MAINTENANCE_METABOLISM)) affected_atom.add_mood_event("maintenance_fun", /datum/mood_event/maintenance_high) metabolization_rate *= 0.8 -/datum/reagent/consumable/grey_bull/on_mob_end_metabolize(mob/living/affected_mob) - . = ..() - REMOVE_TRAIT(affected_mob, TRAIT_SHOCKIMMUNE, type) - /datum/reagent/consumable/grey_bull/on_mob_life(mob/living/carbon/affected_mob, seconds_per_tick, times_fired) . = ..() affected_mob.set_jitter_if_lower(40 SECONDS * REM * seconds_per_tick) diff --git a/code/modules/reagents/chemistry/reagents/drug_reagents.dm b/code/modules/reagents/chemistry/reagents/drug_reagents.dm index 837a34daf7f15..6363a9766a35a 100644 --- a/code/modules/reagents/chemistry/reagents/drug_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/drug_reagents.dm @@ -5,6 +5,7 @@ var/trippy = TRUE //Does this drug make you trip? /datum/reagent/drug/on_mob_end_metabolize(mob/living/affected_mob) + . = ..() if(trippy) affected_mob.clear_mood_event("[type]_high") @@ -214,13 +215,13 @@ overdose_threshold = 20 taste_description = "salt" // because they're bathsalts? addiction_types = list(/datum/addiction/stimulants = 25) //8 per 2 seconds - var/datum/brain_trauma/special/psychotic_brawling/bath_salts/rage ph = 8.2 chemical_flags = REAGENT_CAN_BE_SYNTHESIZED + metabolized_traits = list(TRAIT_STUNIMMUNE, TRAIT_SLEEPIMMUNE, TRAIT_ANALGESIA) + var/datum/brain_trauma/special/psychotic_brawling/bath_salts/rage /datum/reagent/drug/bath_salts/on_mob_metabolize(mob/living/affected_mob) . = ..() - affected_mob.add_traits(list(TRAIT_STUNIMMUNE, TRAIT_SLEEPIMMUNE), type) if(iscarbon(affected_mob)) var/mob/living/carbon/carbon_mob = affected_mob rage = new() @@ -228,7 +229,6 @@ /datum/reagent/drug/bath_salts/on_mob_end_metabolize(mob/living/affected_mob) . = ..() - affected_mob.remove_traits(list(TRAIT_STUNIMMUNE, TRAIT_SLEEPIMMUNE), type) if(rage) QDEL_NULL(rage) @@ -290,15 +290,14 @@ chemical_flags = REAGENT_CAN_BE_SYNTHESIZED taste_description = "paint thinner" addiction_types = list(/datum/addiction/hallucinogens = 18) + metabolized_traits = list(TRAIT_FEARLESS, TRAIT_ANALGESIA) /datum/reagent/drug/happiness/on_mob_metabolize(mob/living/affected_mob) . = ..() - ADD_TRAIT(affected_mob, TRAIT_FEARLESS, type) affected_mob.add_mood_event("happiness_drug", /datum/mood_event/happiness_drug) /datum/reagent/drug/happiness/on_mob_delete(mob/living/affected_mob) . = ..() - REMOVE_TRAIT(affected_mob, TRAIT_FEARLESS, type) affected_mob.clear_mood_event("happiness_drug") /datum/reagent/drug/happiness/on_mob_life(mob/living/carbon/affected_mob, seconds_per_tick, times_fired) @@ -335,19 +334,15 @@ overdose_threshold = 30 chemical_flags = REAGENT_CAN_BE_SYNTHESIZED addiction_types = list(/datum/addiction/stimulants = 6) //2.6 per 2 seconds + metabolized_traits = list(TRAIT_BATON_RESISTANCE, TRAIT_ANALGESIA) /datum/reagent/drug/pumpup/on_mob_metabolize(mob/living/carbon/affected_mob) . = ..() - ADD_TRAIT(affected_mob, TRAIT_BATON_RESISTANCE, type) var/obj/item/organ/internal/liver/liver = affected_mob.get_organ_slot(ORGAN_SLOT_LIVER) if(liver && HAS_TRAIT(liver, TRAIT_MAINTENANCE_METABOLISM)) affected_mob.add_mood_event("maintenance_fun", /datum/mood_event/maintenance_high) metabolization_rate *= 0.8 -/datum/reagent/drug/pumpup/on_mob_end_metabolize(mob/living/affected_mob) - . = ..() - REMOVE_TRAIT(affected_mob, TRAIT_BATON_RESISTANCE, type) - /datum/reagent/drug/pumpup/on_mob_life(mob/living/carbon/affected_mob, seconds_per_tick, times_fired) . = ..() affected_mob.set_jitter_if_lower(10 SECONDS * REM * seconds_per_tick) @@ -432,20 +427,13 @@ overdose_threshold = 25 chemical_flags = REAGENT_CAN_BE_SYNTHESIZED addiction_types = list(/datum/addiction/maintenance_drugs = 8) - -/datum/reagent/drug/maint/sludge/on_mob_metabolize(mob/living/affected_mob) - . = ..() - ADD_TRAIT(affected_mob,TRAIT_HARDLY_WOUNDED,type) + metabolized_traits = list(TRAIT_HARDLY_WOUNDED, TRAIT_ANALGESIA) /datum/reagent/drug/maint/sludge/on_mob_life(mob/living/carbon/affected_mob, seconds_per_tick, times_fired) . = ..() if(affected_mob.adjustToxLoss(0.5 * REM * seconds_per_tick, required_biotype = affected_biotype)) return UPDATE_MOB_HEALTH -/datum/reagent/drug/maint/sludge/on_mob_end_metabolize(mob/living/affected_mob) - . = ..() - REMOVE_TRAIT(affected_mob, TRAIT_HARDLY_WOUNDED,type) - /datum/reagent/drug/maint/sludge/overdose_process(mob/living/affected_mob, seconds_per_tick, times_fired) . = ..() if(!iscarbon(affected_mob)) diff --git a/code/modules/reagents/chemistry/reagents/food_reagents.dm b/code/modules/reagents/chemistry/reagents/food_reagents.dm index f7d070ee33dab..a9fad04ff7f1f 100644 --- a/code/modules/reagents/chemistry/reagents/food_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/food_reagents.dm @@ -525,14 +525,7 @@ taste_description = "garlic" metabolization_rate = 0.15 * REAGENTS_METABOLISM chemical_flags = REAGENT_CAN_BE_SYNTHESIZED - -/datum/reagent/consumable/garlic/on_mob_add(mob/living/affected_mob, amount) - . = ..() - ADD_TRAIT(affected_mob, TRAIT_GARLIC_BREATH, type) - -/datum/reagent/consumable/garlic/on_mob_delete(mob/living/affected_mob) - . = ..() - REMOVE_TRAIT(affected_mob, TRAIT_GARLIC_BREATH, type) + added_traits = list(TRAIT_GARLIC_BREATH) /datum/reagent/consumable/garlic/on_mob_life(mob/living/carbon/affected_mob, seconds_per_tick, times_fired) . = ..() diff --git a/code/modules/reagents/chemistry/reagents/impure_reagents/impure_medicine_reagents.dm b/code/modules/reagents/chemistry/reagents/impure_reagents/impure_medicine_reagents.dm index a54f117265da1..3c677e43d1c07 100644 --- a/code/modules/reagents/chemistry/reagents/impure_reagents/impure_medicine_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/impure_reagents/impure_medicine_reagents.dm @@ -847,14 +847,7 @@ Basically, we fill the time between now and 2s from now with hands based off the ph = 4.5 metabolization_rate = 0.08 * REM tox_damage = 0 - -/datum/reagent/inverse/salbutamol/on_mob_metabolize(mob/living/affected_mob) - . = ..() - ADD_TRAIT(affected_mob, TRAIT_EASYBLEED, type) - -/datum/reagent/inverse/salbutamol/on_mob_end_metabolize(mob/living/affected_mob) - . = ..() - REMOVE_TRAIT(affected_mob, TRAIT_EASYBLEED, type) + metabolized_traits = list(TRAIT_EASYBLEED) /datum/reagent/inverse/pen_acid name = "Pendetide" diff --git a/code/modules/reagents/chemistry/reagents/medicine_reagents.dm b/code/modules/reagents/chemistry/reagents/medicine_reagents.dm index 303a85c6b4b6a..aface2dce34b5 100644 --- a/code/modules/reagents/chemistry/reagents/medicine_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/medicine_reagents.dm @@ -41,6 +41,7 @@ color = "#E0BB00" //golden for the gods taste_description = "badmins" chemical_flags = REAGENT_DEAD_PROCESS + metabolized_traits = list(TRAIT_ANALGESIA) /// Flags to fullheal every metabolism tick var/full_heal_flags = ~(HEAL_BRUTE|HEAL_BURN|HEAL_TOX|HEAL_RESTRAINTS|HEAL_REFRESH_ORGANS) @@ -252,14 +253,7 @@ metabolization_rate = 0.1 * REAGENTS_METABOLISM ph = 8.1 chemical_flags = REAGENT_CAN_BE_SYNTHESIZED - -/datum/reagent/medicine/spaceacillin/on_mob_add(mob/living/affected_mob) - . = ..() - ADD_TRAIT(affected_mob, TRAIT_VIRUS_RESISTANCE, type) - -/datum/reagent/medicine/spaceacillin/on_mob_delete(mob/living/affected_mob) - . = ..() - REMOVE_TRAIT(affected_mob, TRAIT_VIRUS_RESISTANCE, type) + added_traits = list(TRAIT_VIRUS_RESISTANCE) //Goon Chems. Ported mainly from Goonstation. Easily mixable (or not so easily) and provide a variety of effects. @@ -349,6 +343,7 @@ metabolization_rate = 0.4 * REAGENTS_METABOLISM ph = 2.6 chemical_flags = REAGENT_CAN_BE_SYNTHESIZED|REAGENT_AFFECTS_WOUNDS + metabolized_traits = list(TRAIT_ANALGESIA) /datum/reagent/medicine/mine_salve/on_mob_life(mob/living/carbon/affected_mob, seconds_per_tick, times_fired) . = ..() @@ -496,14 +491,7 @@ metabolization_rate = 2 * REAGENTS_METABOLISM ph = 12 //It's a reducing agent chemical_flags = REAGENT_CAN_BE_SYNTHESIZED - -/datum/reagent/medicine/potass_iodide/on_mob_metabolize(mob/living/affected_mob) - . = ..() - ADD_TRAIT(affected_mob, TRAIT_HALT_RADIATION_EFFECTS, "[type]") - -/datum/reagent/medicine/potass_iodide/on_mob_end_metabolize(mob/living/affected_mob) - . = ..() - REMOVE_TRAIT(affected_mob, TRAIT_HALT_RADIATION_EFFECTS, "[type]") + metabolized_traits = list(TRAIT_HALT_RADIATION_EFFECTS) /datum/reagent/medicine/potass_iodide/on_mob_life(mob/living/carbon/affected_mob, seconds_per_tick, times_fired) . = ..() @@ -521,14 +509,7 @@ chemical_flags = REAGENT_CAN_BE_SYNTHESIZED inverse_chem_val = 0.4 inverse_chem = /datum/reagent/inverse/pen_acid - -/datum/reagent/medicine/pen_acid/on_mob_metabolize(mob/living/affected_mob) - . = ..() - ADD_TRAIT(affected_mob, TRAIT_HALT_RADIATION_EFFECTS, "[type]") - -/datum/reagent/medicine/pen_acid/on_mob_end_metabolize(mob/living/affected_mob) - . = ..() - REMOVE_TRAIT(affected_mob, TRAIT_HALT_RADIATION_EFFECTS, "[type]") + metabolized_traits = list(TRAIT_HALT_RADIATION_EFFECTS) /datum/reagent/medicine/pen_acid/on_mob_life(mob/living/carbon/affected_mob, seconds_per_tick, times_fired) . = ..() @@ -603,16 +584,15 @@ addiction_types = list(/datum/addiction/stimulants = 4) //1.6 per 2 seconds inverse_chem = /datum/reagent/inverse/corazargh inverse_chem_val = 0.4 + metabolized_traits = list(TRAIT_BATON_RESISTANCE) /datum/reagent/medicine/ephedrine/on_mob_metabolize(mob/living/affected_mob) . = ..() affected_mob.add_movespeed_modifier(/datum/movespeed_modifier/reagent/ephedrine) - ADD_TRAIT(affected_mob, TRAIT_BATON_RESISTANCE, type) /datum/reagent/medicine/ephedrine/on_mob_end_metabolize(mob/living/affected_mob) . = ..() affected_mob.remove_movespeed_modifier(/datum/movespeed_modifier/reagent/ephedrine) - REMOVE_TRAIT(affected_mob, TRAIT_BATON_RESISTANCE, type) /datum/reagent/medicine/ephedrine/on_mob_life(mob/living/carbon/affected_mob, seconds_per_tick, times_fired) . = ..() @@ -668,6 +648,7 @@ ph = 8.96 chemical_flags = REAGENT_CAN_BE_SYNTHESIZED addiction_types = list(/datum/addiction/opioids = 10) + metabolized_traits = list(TRAIT_ANALGESIA) /datum/reagent/medicine/morphine/on_mob_metabolize(mob/living/affected_mob) . = ..() @@ -820,14 +801,7 @@ chemical_flags = REAGENT_CAN_BE_SYNTHESIZED inverse_chem_val = 0.35 inverse_chem = /datum/reagent/inverse/atropine - -/datum/reagent/medicine/atropine/on_mob_add(mob/living/affected_mob) - . = ..() - ADD_TRAIT(affected_mob, TRAIT_PREVENT_IMPLANT_AUTO_EXPLOSION, "[type]") - -/datum/reagent/medicine/atropine/on_mob_delete(mob/living/affected_mob) - . = ..() - REMOVE_TRAIT(affected_mob, TRAIT_PREVENT_IMPLANT_AUTO_EXPLOSION, "[type]") + added_traits = list(TRAIT_PREVENT_IMPLANT_AUTO_EXPLOSION) /datum/reagent/medicine/atropine/on_mob_life(mob/living/carbon/affected_mob, seconds_per_tick, times_fired) . = ..() @@ -863,14 +837,7 @@ overdose_threshold = 30 ph = 10.2 chemical_flags = REAGENT_CAN_BE_SYNTHESIZED - -/datum/reagent/medicine/epinephrine/on_mob_metabolize(mob/living/affected_mob) - . = ..() - ADD_TRAIT(affected_mob, TRAIT_NOCRITDAMAGE, type) - -/datum/reagent/medicine/epinephrine/on_mob_end_metabolize(mob/living/affected_mob) - . = ..() - REMOVE_TRAIT(affected_mob, TRAIT_NOCRITDAMAGE, type) + metabolized_traits = list(TRAIT_NOCRITDAMAGE) /datum/reagent/medicine/epinephrine/on_mob_life(mob/living/carbon/affected_mob, seconds_per_tick, times_fired) . = ..() @@ -1039,21 +1006,13 @@ purity = REAGENT_STANDARD_PURITY inverse_chem = /datum/reagent/inverse inverse_chem_val = 0.45 + metabolized_traits = list(TRAIT_TUMOR_SUPPRESSED) //Having mannitol in you will pause the brain damage from brain tumor (so it heals an even 2 brain damage instead of 1.8) /datum/reagent/medicine/mannitol/on_mob_life(mob/living/carbon/affected_mob, seconds_per_tick, times_fired) . = ..() if(affected_mob.adjustOrganLoss(ORGAN_SLOT_BRAIN, -2 * REM * seconds_per_tick * normalise_creation_purity(), required_organ_flag = affected_organ_flags)) return UPDATE_MOB_HEALTH -//Having mannitol in you will pause the brain damage from brain tumor (so it heals an even 2 brain damage instead of 1.8) -/datum/reagent/medicine/mannitol/on_mob_metabolize(mob/living/carbon/affected_mob) - . = ..() - ADD_TRAIT(affected_mob, TRAIT_TUMOR_SUPPRESSED, TRAIT_GENERIC) - -/datum/reagent/medicine/mannitol/on_mob_end_metabolize(mob/living/carbon/affected_mob) - . = ..() - REMOVE_TRAIT(affected_mob, TRAIT_TUMOR_SUPPRESSED, TRAIT_GENERIC) - /datum/reagent/medicine/mannitol/overdose_start(mob/living/affected_mob) . = ..() to_chat(affected_mob, span_notice("You suddenly feel E N L I G H T E N E D!")) @@ -1080,12 +1039,12 @@ purity = REAGENT_STANDARD_PURITY inverse_chem_val = 0.5 inverse_chem = /datum/reagent/inverse/neurine + added_traits = list(TRAIT_ANTICONVULSANT) ///brain damage level when we first started taking the chem var/initial_bdamage = 200 /datum/reagent/medicine/neurine/on_mob_add(mob/living/affected_mob, amount) . = ..() - ADD_TRAIT(affected_mob, TRAIT_ANTICONVULSANT, name) if(!iscarbon(affected_mob)) return var/mob/living/carbon/affected_carbon = affected_mob @@ -1094,7 +1053,6 @@ /datum/reagent/medicine/neurine/on_mob_delete(mob/living/affected_mob) . = ..() - REMOVE_TRAIT(affected_mob, TRAIT_ANTICONVULSANT, name) if(!iscarbon(affected_mob)) return var/mob/living/carbon/affected_carbon = affected_mob @@ -1172,16 +1130,15 @@ ph = 8.7 chemical_flags = REAGENT_CAN_BE_SYNTHESIZED|REAGENT_NO_RANDOM_RECIPE addiction_types = list(/datum/addiction/stimulants = 4) //0.8 per 2 seconds + metabolized_traits = list(TRAIT_BATON_RESISTANCE, TRAIT_ANALGESIA) /datum/reagent/medicine/stimulants/on_mob_metabolize(mob/living/affected_mob) . = ..() affected_mob.add_movespeed_modifier(/datum/movespeed_modifier/reagent/stimulants) - ADD_TRAIT(affected_mob, TRAIT_BATON_RESISTANCE, type) /datum/reagent/medicine/stimulants/on_mob_end_metabolize(mob/living/affected_mob) . = ..() affected_mob.remove_movespeed_modifier(/datum/movespeed_modifier/reagent/stimulants) - REMOVE_TRAIT(affected_mob, TRAIT_BATON_RESISTANCE, type) /datum/reagent/medicine/stimulants/on_mob_life(mob/living/carbon/affected_mob, seconds_per_tick, times_fired) . = ..() @@ -1298,6 +1255,7 @@ ph = 11 chemical_flags = REAGENT_CAN_BE_SYNTHESIZED addiction_types = list(/datum/addiction/hallucinogens = 14) + metabolized_traits = list(TRAIT_PACIFISM) /datum/reagent/medicine/earthsblood/on_mob_life(mob/living/carbon/affected_mob, seconds_per_tick, times_fired) . = ..() @@ -1323,14 +1281,6 @@ if(need_mob_update) return UPDATE_MOB_HEALTH -/datum/reagent/medicine/earthsblood/on_mob_metabolize(mob/living/affected_mob) - . = ..() - ADD_TRAIT(affected_mob, TRAIT_PACIFISM, type) - -/datum/reagent/medicine/earthsblood/on_mob_end_metabolize(mob/living/affected_mob) - . = ..() - REMOVE_TRAIT(affected_mob, TRAIT_PACIFISM, type) - /datum/reagent/medicine/earthsblood/overdose_process(mob/living/affected_mob, seconds_per_tick, times_fired) . = ..() affected_mob.adjust_hallucinations_up_to(10 SECONDS * REM * seconds_per_tick, 120 SECONDS) @@ -1446,14 +1396,7 @@ color = "#FF3542" self_consuming = TRUE chemical_flags = REAGENT_CAN_BE_SYNTHESIZED - -/datum/reagent/medicine/higadrite/on_mob_metabolize(mob/living/affected_mob) - . = ..() - ADD_TRAIT(affected_mob, TRAIT_STABLELIVER, type) - -/datum/reagent/medicine/higadrite/on_mob_end_metabolize(mob/living/affected_mob) - . = ..() - REMOVE_TRAIT(affected_mob, TRAIT_STABLELIVER, type) + metabolized_traits = list(TRAIT_STABLELIVER) /datum/reagent/medicine/cordiolis_hepatico name = "Cordiolis Hepatico" @@ -1474,6 +1417,7 @@ name = "Muscle Stimulant" description = "A potent chemical that allows someone under its influence to be at full physical ability even when under massive amounts of pain." chemical_flags = REAGENT_CAN_BE_SYNTHESIZED|REAGENT_NO_RANDOM_RECIPE + metabolized_traits = list(TRAIT_ANALGESIA) /datum/reagent/medicine/muscle_stimulant/on_mob_metabolize(mob/living/affected_mob) . = ..() @@ -1494,14 +1438,7 @@ var/overdose_progress = 0 // to track overdose progress ph = 7.89 chemical_flags = REAGENT_CAN_BE_SYNTHESIZED - -/datum/reagent/medicine/modafinil/on_mob_metabolize(mob/living/affected_mob) - . = ..() - ADD_TRAIT(affected_mob, TRAIT_SLEEPIMMUNE, type) - -/datum/reagent/medicine/modafinil/on_mob_end_metabolize(mob/living/affected_mob) - . = ..() - REMOVE_TRAIT(affected_mob, TRAIT_SLEEPIMMUNE, type) + metabolized_traits = list(TRAIT_SLEEPIMMUNE) /datum/reagent/medicine/modafinil/on_mob_life(mob/living/carbon/metabolizer, seconds_per_tick, times_fired) . = ..() @@ -1565,14 +1502,7 @@ overdose_threshold = 30 ph = 9.12 chemical_flags = REAGENT_CAN_BE_SYNTHESIZED - -/datum/reagent/medicine/psicodine/on_mob_metabolize(mob/living/affected_mob) - . = ..() - ADD_TRAIT(affected_mob, TRAIT_FEARLESS, type) - -/datum/reagent/medicine/psicodine/on_mob_end_metabolize(mob/living/affected_mob) - . = ..() - REMOVE_TRAIT(affected_mob, TRAIT_FEARLESS, type) + metabolized_traits = list(TRAIT_FEARLESS) /datum/reagent/medicine/psicodine/on_mob_life(mob/living/carbon/affected_mob, seconds_per_tick, times_fired) . = ..() @@ -1694,19 +1624,16 @@ /// For tracking when we tell the person we're no longer bleeding var/was_working chemical_flags = REAGENT_CAN_BE_SYNTHESIZED + metabolized_traits = list(TRAIT_COAGULATING) /datum/reagent/medicine/coagulant/on_mob_metabolize(mob/living/affected_mob) . = ..() - ADD_TRAIT(affected_mob, TRAIT_COAGULATING, /datum/reagent/medicine/coagulant) - if(ishuman(affected_mob)) var/mob/living/carbon/human/blood_boy = affected_mob blood_boy.physiology?.bleed_mod *= passive_bleed_modifier /datum/reagent/medicine/coagulant/on_mob_end_metabolize(mob/living/affected_mob) . = ..() - REMOVE_TRAIT(affected_mob, TRAIT_COAGULATING, /datum/reagent/medicine/coagulant) - if(was_working) to_chat(affected_mob, span_warning("The medicine thickening your blood loses its effect!")) if(ishuman(affected_mob)) diff --git a/code/modules/reagents/chemistry/reagents/other_reagents.dm b/code/modules/reagents/chemistry/reagents/other_reagents.dm index 48c30271158f9..25751c5903319 100644 --- a/code/modules/reagents/chemistry/reagents/other_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/other_reagents.dm @@ -347,6 +347,7 @@ ph = 7.5 //God is alkaline chemical_flags = REAGENT_CAN_BE_SYNTHESIZED|REAGENT_CLEANS|REAGENT_UNAFFECTED_BY_METABOLISM // Operates at fixed metabolism for balancing memes. default_container = /obj/item/reagent_containers/cup/glass/bottle/holywater + metabolized_traits = list(TRAIT_HOLY) /datum/glass_style/drinking_glass/holywater required_drink_type = /datum/reagent/water/holywater @@ -369,14 +370,6 @@ mytray.adjust_plant_health(round(volume * 0.1)) mytray.myseed?.adjust_instability(round(volume * 0.15)) -/datum/reagent/water/holywater/on_mob_metabolize(mob/living/affected_mob) - . = ..() - ADD_TRAIT(affected_mob, TRAIT_HOLY, type) - -/datum/reagent/water/holywater/on_mob_end_metabolize(mob/living/affected_mob) - . = ..() - REMOVE_TRAIT(affected_mob, TRAIT_HOLY, type) - /datum/reagent/water/holywater/on_mob_add(mob/living/affected_mob, amount) . = ..() if(IS_CULTIST(affected_mob)) @@ -2507,14 +2500,7 @@ metabolization_rate = 0.25 * REAGENTS_METABOLISM ph = 15 chemical_flags = REAGENT_CAN_BE_SYNTHESIZED - -/datum/reagent/pax/on_mob_metabolize(mob/living/affected_mob) - . = ..() - ADD_TRAIT(affected_mob, TRAIT_PACIFISM, type) - -/datum/reagent/pax/on_mob_end_metabolize(mob/living/affected_mob) - . = ..() - REMOVE_TRAIT(affected_mob, TRAIT_PACIFISM, type) + metabolized_traits = list(TRAIT_PACIFISM) /datum/reagent/bz_metabolites name = "BZ Metabolites" @@ -2523,14 +2509,7 @@ taste_description = "acrid cinnamon" metabolization_rate = 0.2 * REAGENTS_METABOLISM chemical_flags = REAGENT_CAN_BE_SYNTHESIZED|REAGENT_NO_RANDOM_RECIPE - -/datum/reagent/bz_metabolites/on_mob_metabolize(mob/living/ling) - . = ..() - ADD_TRAIT(ling, TRAIT_CHANGELING_HIVEMIND_MUTE, type) - -/datum/reagent/bz_metabolites/on_mob_end_metabolize(mob/living/ling) - . = ..() - REMOVE_TRAIT(ling, TRAIT_CHANGELING_HIVEMIND_MUTE, type) + metabolized_traits = list(TRAIT_CHANGELING_HIVEMIND_MUTE) /datum/reagent/bz_metabolites/on_mob_life(mob/living/carbon/target, seconds_per_tick, times_fired) . = ..() @@ -2767,6 +2746,7 @@ metabolization_rate = 0.75 * REAGENTS_METABOLISM // 5u (WOUND_DETERMINATION_CRITICAL) will last for ~34 seconds chemical_flags = REAGENT_CAN_BE_SYNTHESIZED self_consuming = TRUE + metabolized_traits = list(TRAIT_ANALGESIA) /// Whether we've had at least WOUND_DETERMINATION_SEVERE (2.5u) of determination at any given time. No damage slowdown immunity or indication we're having a second wind if it's just a single moderate wound var/significant = FALSE @@ -3055,6 +3035,7 @@ addtimer(CALLBACK(exposed_obj, TYPE_PROC_REF(/atom/movable/, remove_haunted), HAUNTIUM_REAGENT_TRAIT), volume * 20 SECONDS) /datum/reagent/hauntium/on_mob_metabolize(mob/living/carbon/affected_mob, seconds_per_tick, times_fired) + . = ..() to_chat(affected_mob, span_userdanger("You feel an evil presence inside you!")) if(affected_mob.mob_biotypes & MOB_UNDEAD || HAS_MIND_TRAIT(affected_mob, TRAIT_MORBID)) affected_mob.add_mood_event("morbid_hauntium", /datum/mood_event/morbid_hauntium, name) //8 minutes of slight mood buff if undead or morbid diff --git a/code/modules/reagents/chemistry/reagents/toxin_reagents.dm b/code/modules/reagents/chemistry/reagents/toxin_reagents.dm index 7457acd0687b9..e9bea91fbed64 100644 --- a/code/modules/reagents/chemistry/reagents/toxin_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/toxin_reagents.dm @@ -295,14 +295,7 @@ taste_description = "death" ph = 14.5 chemical_flags = REAGENT_CAN_BE_SYNTHESIZED - -/datum/reagent/toxin/ghoulpowder/on_mob_metabolize(mob/living/affected_mob) - . = ..() - ADD_TRAIT(affected_mob, TRAIT_FAKEDEATH, type) - -/datum/reagent/toxin/ghoulpowder/on_mob_end_metabolize(mob/living/affected_mob) - . = ..() - REMOVE_TRAIT(affected_mob, TRAIT_FAKEDEATH, type) + metabolized_traits = list(TRAIT_FAKEDEATH) /datum/reagent/toxin/ghoulpowder/on_mob_life(mob/living/carbon/affected_mob, seconds_per_tick, times_fired) . = ..() @@ -321,14 +314,7 @@ inverse_chem = /datum/reagent/impurity/rosenol chemical_flags = REAGENT_CAN_BE_SYNTHESIZED addiction_types = list(/datum/addiction/hallucinogens = 18) //7.2 per 2 seconds - -/datum/reagent/toxin/mindbreaker/on_mob_metabolize(mob/living/affected_mob) - . = ..() - ADD_TRAIT(affected_mob, TRAIT_RDS_SUPPRESSED, type) - -/datum/reagent/toxin/mindbreaker/on_mob_end_metabolize(mob/living/affected_mob) - . = ..() - REMOVE_TRAIT(affected_mob, TRAIT_RDS_SUPPRESSED, type) + metabolized_traits = list(TRAIT_RDS_SUPPRESSED) /datum/reagent/toxin/mindbreaker/on_mob_life(mob/living/carbon/affected_mob, seconds_per_tick, times_fired) . = ..() @@ -848,14 +834,7 @@ metabolization_rate = 0.75 * REAGENTS_METABOLISM toxpwr = 0 chemical_flags = REAGENT_CAN_BE_SYNTHESIZED|REAGENT_NO_RANDOM_RECIPE - -/datum/reagent/toxin/sodium_thiopental/on_mob_add(mob/living/affected_mob, amount) - . = ..() - ADD_TRAIT(affected_mob, TRAIT_ANTICONVULSANT, name) - -/datum/reagent/toxin/sodium_thiopental/on_mob_delete(mob/living/affected_mob) - . = ..() - REMOVE_TRAIT(affected_mob, TRAIT_ANTICONVULSANT, name) + added_traits = list(TRAIT_ANTICONVULSANT) /datum/reagent/toxin/sodium_thiopental/on_mob_life(mob/living/carbon/affected_mob, seconds_per_tick, times_fired) . = ..() @@ -1000,20 +979,13 @@ toxpwr = 0 ph = 11.6 chemical_flags = REAGENT_CAN_BE_SYNTHESIZED + metabolized_traits = list(TRAIT_BLOODY_MESS) /datum/reagent/toxin/heparin/on_mob_life(mob/living/carbon/affected_mob, seconds_per_tick, times_fired) if(holder.has_reagent(/datum/reagent/medicine/coagulant)) //Directly purges coagulants from the system. Get rid of the heparin BEFORE attempting to use coagulants. holder.remove_reagent(/datum/reagent/medicine/coagulant, 2 * REM * seconds_per_tick) return ..() -/datum/reagent/toxin/heparin/on_mob_metabolize(mob/living/affected_mob) - . = ..() - ADD_TRAIT(affected_mob, TRAIT_BLOODY_MESS, /datum/reagent/toxin/heparin) - -/datum/reagent/toxin/heparin/on_mob_end_metabolize(mob/living/affected_mob) - . = ..() - REMOVE_TRAIT(affected_mob, TRAIT_BLOODY_MESS, /datum/reagent/toxin/heparin) - /datum/reagent/toxin/rotatium //Rotatium. Fucks up your rotation and is hilarious name = "Rotatium" description = "A constantly swirling, oddly colourful fluid. Causes the consumer's sense of direction and hand-eye coordination to become wild." @@ -1184,14 +1156,7 @@ ph = 1.7 taste_description = "stillness" chemical_flags = REAGENT_CAN_BE_SYNTHESIZED - -/datum/reagent/toxin/mimesbane/on_mob_metabolize(mob/living/affected_mob) - . = ..() - ADD_TRAIT(affected_mob, TRAIT_EMOTEMUTE, type) - -/datum/reagent/toxin/mimesbane/on_mob_end_metabolize(mob/living/affected_mob) - . = ..() - REMOVE_TRAIT(affected_mob, TRAIT_EMOTEMUTE, type) + metabolized_traits = list(TRAIT_EMOTEMUTE) /datum/reagent/toxin/bonehurtingjuice //oof ouch name = "Bone Hurting Juice" diff --git a/code/modules/surgery/organs/external/spines.dm b/code/modules/surgery/organs/external/spines.dm index 524810a2a67c3..743b7fa8d47f2 100644 --- a/code/modules/surgery/organs/external/spines.dm +++ b/code/modules/surgery/organs/external/spines.dm @@ -7,6 +7,8 @@ zone = BODY_ZONE_CHEST slot = ORGAN_SLOT_EXTERNAL_SPINES + preference = "feature_lizard_spines" + dna_block = DNA_SPINES_BLOCK restyle_flags = EXTERNAL_RESTYLE_FLESH diff --git a/code/modules/surgery/surgery_step.dm b/code/modules/surgery/surgery_step.dm index 6d20a58b9e426..342f984042fec 100644 --- a/code/modules/surgery/surgery_step.dm +++ b/code/modules/surgery/surgery_step.dm @@ -70,6 +70,8 @@ #define SURGERY_SPEED_DISSECTION_MODIFIER 0.8 ///Modifier given to users with TRAIT_MORBID on certain surgeries #define SURGERY_SPEED_MORBID_CURIOSITY 0.7 +///Modifier given to patients with TRAIT_ANALGESIA +#define SURGERY_SPEED_TRAIT_ANALGESIA 0.8 /datum/surgery_step/proc/initiate(mob/living/user, mob/living/target, target_zone, obj/item/tool, datum/surgery/surgery, try_to_fail = FALSE) // Only followers of Asclepius have the ability to use Healing Touch and perform miracle feats of surgery. @@ -95,6 +97,9 @@ if(check_morbid_curiosity(user, tool, surgery)) speed_mod *= SURGERY_SPEED_MORBID_CURIOSITY + if(HAS_TRAIT(target, TRAIT_ANALGESIA)) + speed_mod *= SURGERY_SPEED_TRAIT_ANALGESIA + var/implement_speed_mod = 1 if(implement_type) //this means it isn't a require hand or any item step. implement_speed_mod = implements[implement_type] / 100.0 @@ -260,10 +265,14 @@ */ /datum/surgery_step/proc/display_pain(mob/living/target, pain_message, mechanical_surgery = FALSE) if(target.stat < UNCONSCIOUS) - to_chat(target, span_userdanger(pain_message)) - if(prob(30) && !mechanical_surgery) - target.emote("scream") + if(HAS_TRAIT(target, TRAIT_ANALGESIA)) + to_chat(target, span_notice("You feel a dull, numb sensation as your body is surgically operated on.")) + else + to_chat(target, span_userdanger(pain_message)) + if(prob(30) && !mechanical_surgery) + target.emote("scream") +#undef SURGERY_SPEED_TRAIT_ANALGESIA #undef SURGERY_SPEED_DISSECTION_MODIFIER #undef SURGERY_SPEED_MORBID_CURIOSITY #undef SURGERY_SLOWDOWN_CAP_MULTIPLIER diff --git a/code/modules/unit_tests/achievements.dm b/code/modules/unit_tests/achievements.dm index 44e1384c2e01a..decda52a2f5d7 100644 --- a/code/modules/unit_tests/achievements.dm +++ b/code/modules/unit_tests/achievements.dm @@ -2,13 +2,13 @@ /datum/unit_test/achievements /datum/unit_test/achievements/Run() - var/award_icons = icon_states(ACHIEVEMENTS_SET) for(var/datum/award/award as anything in subtypesof(/datum/award)) if(!initial(award.name)) //Skip abstract achievements types continue var/init_icon = initial(award.icon) - if(!init_icon || !(init_icon in award_icons)) - TEST_FAIL("Award [initial(award.name)] has an unexistent icon: \"[init_icon || "null"]\"") + var/init_icon_state = initial(award.icon_state) + if(!init_icon_state || !icon_exists(init_icon, init_icon_state)) + TEST_FAIL("Award [initial(award.name)] has a non-existent icon in [init_icon]: \"[init_icon_state || "null"]\"") if(length(initial(award.database_id)) > 32) //sql schema limit TEST_FAIL("Award [initial(award.name)] database id is too long") var/init_category = initial(award.category) diff --git a/html/changelogs/AutoChangeLog-pr-81354.yml b/html/changelogs/AutoChangeLog-pr-81354.yml deleted file mode 100644 index db9fbbabb28e6..0000000000000 --- a/html/changelogs/AutoChangeLog-pr-81354.yml +++ /dev/null @@ -1,6 +0,0 @@ -author: "Aylong" -delete-after: True -changes: - - rscadd: "Added `Mute` button into `Chat Tabs` settings, it disables tab unread counter" - - rscadd: "Added `Clear chat` button into `General` settings, you can clear your dirty chat like you did it before TGchat" - - bugfix: "Case-sensitive highlighting now works properly" \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-81385.yml b/html/changelogs/AutoChangeLog-pr-81385.yml deleted file mode 100644 index 23f3aab42b1af..0000000000000 --- a/html/changelogs/AutoChangeLog-pr-81385.yml +++ /dev/null @@ -1,5 +0,0 @@ -author: "ViktorKoL" -delete-after: True -changes: - - bugfix: "knit flesh now heals organs as intended, and does not cause its victims to be red forever if interrupted" - - spellcheck: "knit flesh chat messages are no longer gramatically incorrect" \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-81409.yml b/html/changelogs/AutoChangeLog-pr-81409.yml new file mode 100644 index 0000000000000..f3f1949b1ad00 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-81409.yml @@ -0,0 +1,4 @@ +author: "Thunder12345" +delete-after: True +changes: + - qol: "The bitrunning quantum console UI now lists domains in tabs by difficulty." \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-81413.yml b/html/changelogs/AutoChangeLog-pr-81413.yml new file mode 100644 index 0000000000000..b64eee4e917c7 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-81413.yml @@ -0,0 +1,4 @@ +author: "Melbert" +delete-after: True +changes: + - rscadd: "Wizards have a new mobility option available, the Telegram Scepter. The ability to travel anywhere you can see at the point of a wand... but at a price?" \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-81420.yml b/html/changelogs/AutoChangeLog-pr-81420.yml deleted file mode 100644 index c83fff17957ef..0000000000000 --- a/html/changelogs/AutoChangeLog-pr-81420.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "JohnFulpWillard" -delete-after: True -changes: - - bugfix: "Revenants (and other flying mobs) will not make noise when walking into pools of gibs," \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-81432.yml b/html/changelogs/AutoChangeLog-pr-81432.yml deleted file mode 100644 index 0b74f0ee4c90e..0000000000000 --- a/html/changelogs/AutoChangeLog-pr-81432.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "Rhials" -delete-after: True -changes: - - spellcheck: "Some space ruin area names have been made more distinct." \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-81435.yml b/html/changelogs/AutoChangeLog-pr-81435.yml new file mode 100644 index 0000000000000..0ef4705974e09 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-81435.yml @@ -0,0 +1,4 @@ +author: "Ghommie" +delete-after: True +changes: + - rscadd: "Added three new 'special' bedsheets. One of them is quite rare and made from gondola hide." \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-81437.yml b/html/changelogs/AutoChangeLog-pr-81437.yml deleted file mode 100644 index c27dd8a0fa994..0000000000000 --- a/html/changelogs/AutoChangeLog-pr-81437.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "vinylspiders" -delete-after: True -changes: - - bugfix: "*wag emote is now functional again" \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-81452.yml b/html/changelogs/AutoChangeLog-pr-81452.yml new file mode 100644 index 0000000000000..d501307c8ba40 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-81452.yml @@ -0,0 +1,5 @@ +author: "mogeoko" +delete-after: True +changes: + - bugfix: "Thermomachines now reconnect to pipes on multitool's act." + - bugfix: "Multi-deck connectors won't connect pipes not located in front/top/bottom of it." \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-81459.yml b/html/changelogs/AutoChangeLog-pr-81459.yml new file mode 100644 index 0000000000000..39addd9cbe676 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-81459.yml @@ -0,0 +1,6 @@ +author: "SyncIt21" +delete-after: True +changes: + - qol: "adds examines & screentips for ore box" + - code_imp: "cleans up some procs for ore box" + - spellcheck: "corrected description & ui notice of ore box to specify it can hold boulders too" \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-81472.yml b/html/changelogs/AutoChangeLog-pr-81472.yml new file mode 100644 index 0000000000000..0ca1b4ccb0f35 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-81472.yml @@ -0,0 +1,4 @@ +author: "kawaiinick" +delete-after: True +changes: + - rscadd: "Your mouth now fits combat or survival knives(it's totally safe)" \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-81481.yml b/html/changelogs/AutoChangeLog-pr-81481.yml new file mode 100644 index 0000000000000..d076280f163ec --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-81481.yml @@ -0,0 +1,4 @@ +author: "Sylphet" +delete-after: True +changes: + - bugfix: "cargo lockboxes update iconstates correctly now" \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-81482.yml b/html/changelogs/AutoChangeLog-pr-81482.yml new file mode 100644 index 0000000000000..7306b7c28b4de --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-81482.yml @@ -0,0 +1,4 @@ +author: "00-Steven" +delete-after: True +changes: + - bugfix: "Space cats CAN into space. (They're back to surviving being in unsuitable atmos.)" \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-81483.yml b/html/changelogs/AutoChangeLog-pr-81483.yml new file mode 100644 index 0000000000000..8c82b8396d588 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-81483.yml @@ -0,0 +1,4 @@ +author: "IndieanaJones" +delete-after: True +changes: + - bugfix: "Tank spider corpses should no longer be conditionally invisible" \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-81485.yml b/html/changelogs/AutoChangeLog-pr-81485.yml new file mode 100644 index 0000000000000..bac62bcf734ae --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-81485.yml @@ -0,0 +1,4 @@ +author: "IndieanaJones" +delete-after: True +changes: + - bugfix: "Blob Zombies now render their blob heads correctly again." \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-81487.yml b/html/changelogs/AutoChangeLog-pr-81487.yml new file mode 100644 index 0000000000000..db13b1e0f97da --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-81487.yml @@ -0,0 +1,4 @@ +author: "SyncIt21" +delete-after: True +changes: + - bugfix: "Indestructible items like the pai card don't teleport to the ore silo when you insert them into silo linked machine & also displays a message saying it was rejected." \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-81492.yml b/html/changelogs/AutoChangeLog-pr-81492.yml new file mode 100644 index 0000000000000..d2aeff28762c2 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-81492.yml @@ -0,0 +1,4 @@ +author: "13spacemen" +delete-after: True +changes: + - code_imp: "Removed unused global lists and sprite accessories related to tail spines" \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-81493.yml b/html/changelogs/AutoChangeLog-pr-81493.yml new file mode 100644 index 0000000000000..4f7d4b4b89c23 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-81493.yml @@ -0,0 +1,4 @@ +author: "13spacemen" +delete-after: True +changes: + - code_imp: "removed redundant check for plasmamen in survival box code" \ No newline at end of file diff --git a/html/changelogs/archive/2024-02.yml b/html/changelogs/archive/2024-02.yml index 7c8d89aa9282a..6afd8b08c3696 100644 --- a/html/changelogs/archive/2024-02.yml +++ b/html/changelogs/archive/2024-02.yml @@ -387,3 +387,62 @@ - bugfix: Holding bloodied gloves no longer makes your hands look bloody, bloodied gloves now look bloody when worn, and damaged gloves now look damaged when worn - bugfix: Gaining or losing an arm now correctly updates your hand overlays +2024-02-14: + Absolucy: + - rscadd: Painkillers (i.e morphine, miner's salve) now actually induce analgesic + effects, preventing various pain-related effects, such as screaming due to pain, + and also provides a speed bonus during surgery. + - rscadd: The tenacity trauma (traumatic neuropathy) also applies analgesic effects. + - refactor: Simplified code related to reagents adding traits. + Aylong: + - rscadd: Added `Mute` button into `Chat Tabs` settings, it disables tab unread + counter + - rscadd: Added `Clear chat` button into `General` settings, you can clear your + dirty chat like you did it before TGchat + - bugfix: Case-sensitive highlighting now works properly + JohnFulpWillard: + - bugfix: Revenants (and other flying mobs) will not make noise when walking into + pools of gibs, + Rhials: + - spellcheck: Some space ruin area names have been made more distinct. + - bugfix: Ghost role polls should spam you less when multiple of the same roll occur + in succession. + ViktorKoL: + - bugfix: heretics no longer lose their spells when returning from a shapeshift + - bugfix: knit flesh now heals organs as intended, and does not cause its victims + to be red forever if interrupted + - spellcheck: knit flesh chat messages are no longer gramatically incorrect + vinylspiders: + - bugfix: '*wag emote is now functional again' +2024-02-15: + CandleJaxx and Iamgoofball: + - bugfix: Fixes Krav Maga allowing pacifism bypasses. + IndieanaJones: + - balance: Nightmare's Light Eater takes less time in jaunt to gain a critical strike, + being reduced to 7 seconds from 15 seconds. + K4rlox: + - balance: Maintenance drones now can use RPED, RCD, Holosign, and Spray bottles + LemonInTheDark: + - rscadd: AI's acceleration now smoothly decays, instead of just falling back down + to 0 after 0.5 seconds + - bugfix: AI's standard movement (non accelerated) is smooth now, instead of constantly + jumping around + - bugfix: AIs will now follow their targets more closely, shouldn't have any issues + with them lagging behind anymore + Melbert: + - bugfix: Valentines no longer see themselves covered in hearts. They only see their + Valentine covered in hearts. + - balance: Scientists have discovered Nuka Cola is not good for short term health. +2024-02-16: + 00-Steven: + - bugfix: Fixed the lizardperson spine preference dropdown not showing up in the + character menu. + Kylerace: + - admin: admins/maintainers can now make the profiler focus on specific subsystems + by setting the subsystem var profile_focused to TRUE + LemonInTheDark: + - refactor: Fucks with how movement keys are handled. Please report any bugs + WinterDarkraven: + - rscadd: In an attempt to stop the greytide, NanoTrasen has increased security's + baton energy output. This has, through testing, done nothing but make the device + spark more than it used to. diff --git a/icons/effects/effects.dmi b/icons/effects/effects.dmi index 0b01e4dd6a8cb..fcb4e262d7c89 100644 Binary files a/icons/effects/effects.dmi and b/icons/effects/effects.dmi differ diff --git a/icons/effects/random_spawners.dmi b/icons/effects/random_spawners.dmi index c03b196a13798..08df14c0ffc99 100644 Binary files a/icons/effects/random_spawners.dmi and b/icons/effects/random_spawners.dmi differ diff --git a/icons/hud/screen_alert.dmi b/icons/hud/screen_alert.dmi index 289d02da46ada..7aa32c94b8e2a 100644 Binary files a/icons/hud/screen_alert.dmi and b/icons/hud/screen_alert.dmi differ diff --git a/icons/mob/clothing/mask.dmi b/icons/mob/clothing/mask.dmi index 4c05979ff2bad..24e8622344e4e 100644 Binary files a/icons/mob/clothing/mask.dmi and b/icons/mob/clothing/mask.dmi differ diff --git a/icons/mob/clothing/neck.dmi b/icons/mob/clothing/neck.dmi index fcfdb55f52250..5440bf9d99dae 100644 Binary files a/icons/mob/clothing/neck.dmi and b/icons/mob/clothing/neck.dmi differ diff --git a/icons/mob/inhands/items/bedsheet_lefthand.dmi b/icons/mob/inhands/items/bedsheet_lefthand.dmi index 1f2d7df00753d..2795277a183ca 100644 Binary files a/icons/mob/inhands/items/bedsheet_lefthand.dmi and b/icons/mob/inhands/items/bedsheet_lefthand.dmi differ diff --git a/icons/mob/inhands/items/bedsheet_righthand.dmi b/icons/mob/inhands/items/bedsheet_righthand.dmi index 5c831140c9eab..4fe73af823a4c 100644 Binary files a/icons/mob/inhands/items/bedsheet_righthand.dmi and b/icons/mob/inhands/items/bedsheet_righthand.dmi differ diff --git a/icons/mob/inhands/weapons/staves_lefthand.dmi b/icons/mob/inhands/weapons/staves_lefthand.dmi index 83504696b61a3..5e4eb552f2a5c 100644 Binary files a/icons/mob/inhands/weapons/staves_lefthand.dmi and b/icons/mob/inhands/weapons/staves_lefthand.dmi differ diff --git a/icons/mob/inhands/weapons/staves_righthand.dmi b/icons/mob/inhands/weapons/staves_righthand.dmi index c83e0eed3abee..9de32d8cd9533 100644 Binary files a/icons/mob/inhands/weapons/staves_righthand.dmi and b/icons/mob/inhands/weapons/staves_righthand.dmi differ diff --git a/icons/mob/simple/arachnoid.dmi b/icons/mob/simple/arachnoid.dmi index d17297f2ccf57..7e15fde685240 100644 Binary files a/icons/mob/simple/arachnoid.dmi and b/icons/mob/simple/arachnoid.dmi differ diff --git a/icons/obj/bedsheets.dmi b/icons/obj/bedsheets.dmi index 8db48b45fc684..daa0c3cdd7904 100644 Binary files a/icons/obj/bedsheets.dmi and b/icons/obj/bedsheets.dmi differ diff --git a/icons/obj/weapons/guns/magic.dmi b/icons/obj/weapons/guns/magic.dmi index 90eb4bdc669a5..3d7238a72bb0b 100644 Binary files a/icons/obj/weapons/guns/magic.dmi and b/icons/obj/weapons/guns/magic.dmi differ diff --git a/tgstation.dme b/tgstation.dme index aa58962102c40..0a32dc4496121 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -184,6 +184,7 @@ #include "code\__DEFINES\radiation.dm" #include "code\__DEFINES\radio.dm" #include "code\__DEFINES\radioactive_nebula.dm" +#include "code\__DEFINES\random_spawner.dm" #include "code\__DEFINES\reactions.dm" #include "code\__DEFINES\reagents.dm" #include "code\__DEFINES\reagents_specific_heat.dm" @@ -2176,6 +2177,7 @@ #include "code\game\objects\effects\spawners\random\ai_module.dm" #include "code\game\objects\effects\spawners\random\animalhide.dm" #include "code\game\objects\effects\spawners\random\armory.dm" +#include "code\game\objects\effects\spawners\random\bedsheet.dm" #include "code\game\objects\effects\spawners\random\bureaucracy.dm" #include "code\game\objects\effects\spawners\random\clothing.dm" #include "code\game\objects\effects\spawners\random\contraband.dm" @@ -3195,6 +3197,7 @@ #include "code\modules\antagonists\wizard\equipment\chuunibyou_spell.dm" #include "code\modules\antagonists\wizard\equipment\enchanted_clown_suit.dm" #include "code\modules\antagonists\wizard\equipment\soulstone.dm" +#include "code\modules\antagonists\wizard\equipment\teleport_rod.dm" #include "code\modules\antagonists\wizard\equipment\wizard_spellbook.dm" #include "code\modules\antagonists\wizard\equipment\spellbook_entries\_entry.dm" #include "code\modules\antagonists\wizard\equipment\spellbook_entries\assistance.dm" diff --git a/tgui/packages/tgui/interfaces/AntagInfoNightmare.tsx b/tgui/packages/tgui/interfaces/AntagInfoNightmare.tsx index 2552bf4b86e41..f0b897e764545 100644 --- a/tgui/packages/tgui/interfaces/AntagInfoNightmare.tsx +++ b/tgui/packages/tgui/interfaces/AntagInfoNightmare.tsx @@ -63,7 +63,7 @@ export const AntagInfoNightmare = (props) => { Your twisted appendage. It will consume the light of what it - touches, be it victim or object. After 15 seconds of being in + touches, be it victim or object. After 7 seconds of being in jaunt, stabbing a foe will stun them or do extra damage. diff --git a/tgui/packages/tgui/interfaces/OreBox.tsx b/tgui/packages/tgui/interfaces/OreBox.tsx index bcafaa7245459..63716b021db40 100644 --- a/tgui/packages/tgui/interfaces/OreBox.tsx +++ b/tgui/packages/tgui/interfaces/OreBox.tsx @@ -4,40 +4,42 @@ import { useBackend } from '../backend'; import { Box, Button, Section, Table } from '../components'; import { Window } from '../layouts'; -type Data = { - materials: Material[]; - boulders: number; -}; - type Material = { - type: string; name: string; amount: number; }; -const OREBOX_INFO = `All ores will be placed in here when you are wearing a -mining stachel on your belt or in a pocket while dragging the ore box.`; +type Data = { + materials: Material[]; +}; export const OreBox = (props) => { const { act, data } = useBackend(); - const { materials, boulders } = data; + const { materials } = data; return (
act('removeall')} />} + title="Ores & Boulders" + buttons={ + + } > - Ore + Item Amount - {materials.map((material) => ( - + {materials.map((material, id) => ( + {toTitleCase(material.name)} @@ -46,21 +48,12 @@ export const OreBox = (props) => { ))} - {boulders > 0 && ( - - Boulders - - - {boulders} - - - - )}
- {OREBOX_INFO} + Ores can be loaded here via a mining satchel or by hand. Boulders + can also be stored here
Gibtonite is not accepted.
diff --git a/tgui/packages/tgui/interfaces/QuantumConsole.tsx b/tgui/packages/tgui/interfaces/QuantumConsole.tsx index 8730220dff14b..dca8f2dbf1554 100644 --- a/tgui/packages/tgui/interfaces/QuantumConsole.tsx +++ b/tgui/packages/tgui/interfaces/QuantumConsole.tsx @@ -1,6 +1,6 @@ import { BooleanLike } from 'common/react'; -import { useBackend } from '../backend'; +import { useBackend, useSharedState } from '../backend'; import { Button, Collapsible, @@ -10,6 +10,7 @@ import { Section, Stack, Table, + Tabs, Tooltip, } from '../components'; import { TableCell, TableRow } from '../components/Table'; @@ -82,7 +83,7 @@ const getColor = (difficulty: number) => { case Difficulty.High: return 'bad'; default: - return ''; + return 'green'; } }; @@ -101,6 +102,7 @@ export const QuantumConsole = (props) => { const AccessView = (props) => { const { act, data } = useBackend(); + const [tab, setTab] = useSharedState('tab', 0); if (!isConnected(data)) { return No server connected!; @@ -117,6 +119,10 @@ const AccessView = (props) => { const sorted = available_domains.sort((a, b) => a.cost - b.cost); + const filtered = sorted.filter((domain) => { + return domain.difficulty === tab; + }); + let selected; if (generated_domain) { selected = randomized @@ -153,7 +159,45 @@ const AccessView = (props) => { scrollable title="Virtual Domains" > - {sorted.map((domain) => ( + + setTab(0)} + icon="chevron-down" + > + Peaceful + + setTab(1)} + icon="chevron-down" + > + Easy + + setTab(2)} + icon="chevron-down" + > + Medium + + setTab(3)} + icon="chevron-down" + > + Hard {' '} + + + {filtered.map((domain) => ( ))}
@@ -223,7 +267,6 @@ const DomainEntry = (props: DomainEntryProps) => { title={ <> {name} - {difficulty === Difficulty.High && } {!!is_modular && name !== '???' && } } @@ -232,19 +275,19 @@ const DomainEntry = (props: DomainEntryProps) => { {desc} {!!is_modular && ' (Modular)'} - {difficulty === Difficulty.High && ' (Hard)'} - - - - + + + - + + +
diff --git a/tools/UpdatePaths/Scripts/81435_bedsheet_spawners.txt b/tools/UpdatePaths/Scripts/81435_bedsheet_spawners.txt new file mode 100644 index 0000000000000..85520034921d3 --- /dev/null +++ b/tools/UpdatePaths/Scripts/81435_bedsheet_spawners.txt @@ -0,0 +1,3 @@ +/obj/item/bedsheet/dorms : /obj/effect/spawner/random/bedsheet{@OLD} +/obj/item/bedsheet/dorms_double : /obj/effect/spawner/random/bedsheet/double{@OLD} +/obj/item/bedsheet/random/@SUBTYPES: /obj/effect/spawner/random/bedsheet/any/@SUBTYPES{@OLD}