diff --git a/_maps/RandomRuins/IceRuins/icemoon_underground_syndidome.dmm b/_maps/RandomRuins/IceRuins/icemoon_underground_syndidome.dmm index e2b11a02964eb..228c55292fbb0 100644 --- a/_maps/RandomRuins/IceRuins/icemoon_underground_syndidome.dmm +++ b/_maps/RandomRuins/IceRuins/icemoon_underground_syndidome.dmm @@ -90,6 +90,13 @@ /obj/effect/decal/cleanable/dirt, /turf/open/floor/iron/dark, /area/ruin/syndibiodome) +"bp" = ( +/obj/effect/decal/cleanable/dirt, +/obj/structure/cable, +/obj/structure/cable/layer1, +/obj/structure/cable/layer3, +/turf/open/floor/catwalk_floor/iron_dark, +/area/ruin/syndibiodome) "bu" = ( /obj/effect/turf_decal/siding/wood, /obj/structure/table/wood, @@ -216,9 +223,15 @@ /obj/effect/turf_decal/siding/wideplating/dark{ dir = 5 }, -/obj/machinery/smartfridge/organ, -/obj/item/organ/alien/resinspinner, -/obj/item/organ/eyes/night_vision, +/obj/structure/table/reinforced/plastitaniumglass, +/obj/item/clothing/gloves/latex/coroner{ + pixel_x = -1; + pixel_y = 8 + }, +/obj/item/clothing/mask/surgical{ + pixel_x = 6; + pixel_y = 10 + }, /turf/open/floor/mineral/plastitanium/red, /area/ruin/syndibiodome) "cE" = ( @@ -498,9 +511,10 @@ /obj/effect/decal/cleanable/blood/gibs/down, /turf/open/floor/iron/cafeteria, /area/ruin/syndibiodome) -"gX" = ( -/obj/effect/decal/cleanable/dirt, -/obj/machinery/light/warm/directional/west, +"gZ" = ( +/obj/machinery/door/airlock/maintenance_hatch, +/obj/structure/cable/layer1, +/obj/structure/cable, /turf/open/floor/catwalk_floor/iron_dark, /area/ruin/syndibiodome) "ha" = ( @@ -509,10 +523,10 @@ /turf/open/misc/asteroid/snow/icemoon, /area/icemoon/surface/outdoors/noteleport) "he" = ( -/mob/living/basic/gorilla/genetics, /obj/effect/turf_decal/siding/wood/corner{ dir = 1 }, +/mob/living/basic/gorilla/hostile, /turf/open/floor/wood, /area/ruin/syndibiodome) "hf" = ( @@ -527,8 +541,8 @@ /turf/open/floor/iron/dark, /area/ruin/syndibiodome) "hm" = ( -/mob/living/basic/gorilla/genetics, /obj/effect/decal/cleanable/dirt/dust, +/mob/living/basic/gorilla/hostile, /turf/open/floor/iron/dark/small, /area/ruin/syndibiodome) "hr" = ( @@ -639,14 +653,12 @@ }, /turf/open/floor/iron/dark/herringbone, /area/ruin/syndibiodome) -"iq" = ( -/obj/structure/flora/rock/pile/style_random, -/mob/living/carbon/human/species/monkey/angry, -/turf/open/floor/grass, -/area/ruin/syndibiodome) "ir" = ( /obj/effect/decal/cleanable/dirt, /obj/machinery/light/small/dim/directional/east, +/obj/structure/cable, +/obj/structure/cable/layer1, +/obj/structure/cable/layer3, /turf/open/floor/catwalk_floor/iron_dark, /area/ruin/syndibiodome) "iG" = ( @@ -723,16 +735,6 @@ }, /obj/effect/decal/cleanable/blood/drip, /obj/effect/decal/cleanable/dirt, -/obj/structure/table/reinforced/plastitaniumglass, -/obj/item/surgery_tray/full, -/obj/item/clothing/gloves/latex/coroner{ - pixel_x = -1; - pixel_y = 8 - }, -/obj/item/clothing/mask/surgical{ - pixel_x = 6; - pixel_y = 10 - }, /turf/open/floor/mineral/plastitanium/red, /area/ruin/syndibiodome) "jd" = ( @@ -771,9 +773,6 @@ /obj/effect/decal/cleanable/dirt, /turf/open/floor/iron/dark, /area/ruin/syndibiodome) -"jQ" = ( -/turf/closed/indestructible/syndicate/nodiagonal, -/area/icemoon/surface/outdoors/noteleport) "jR" = ( /obj/effect/decal/cleanable/blood/trails{ dir = 4 @@ -1025,9 +1024,6 @@ /obj/effect/decal/cleanable/dirt, /turf/open/floor/iron/dark, /area/ruin/syndibiodome) -"mK" = ( -/turf/open/misc/asteroid/snow/icemoon, -/area/ruin/syndibiodome) "mV" = ( /obj/effect/turf_decal/siding/wideplating/dark, /obj/effect/decal/cleanable/dirt/dust, @@ -1040,6 +1036,9 @@ "mW" = ( /obj/effect/spawner/random/trash, /obj/effect/decal/cleanable/dirt, +/obj/structure/cable/layer3, +/obj/structure/cable/layer1, +/obj/structure/cable, /turf/open/floor/catwalk_floor/iron_dark, /area/ruin/syndibiodome) "mZ" = ( @@ -1113,6 +1112,13 @@ /obj/effect/turf_decal/trimline/dark_red/line, /turf/open/floor/iron/dark, /area/ruin/syndibiodome) +"on" = ( +/obj/machinery/door/airlock/maintenance_hatch, +/obj/structure/cable/layer3, +/obj/structure/cable/layer1, +/obj/structure/cable, +/turf/open/floor/catwalk_floor/iron_dark, +/area/ruin/syndibiodome) "oq" = ( /obj/effect/decal/cleanable/blood/trails{ dir = 10 @@ -1147,7 +1153,7 @@ /obj/machinery/light/warm/directional/west, /obj/effect/decal/cleanable/dirt/dust, /obj/effect/decal/cleanable/dirt, -/mob/living/basic/gorilla/genetics, +/mob/living/basic/gorilla/hostile, /turf/open/floor/iron/dark, /area/ruin/syndibiodome) "oH" = ( @@ -1346,7 +1352,6 @@ /obj/effect/turf_decal/siding/wideplating/dark{ dir = 1 }, -/mob/living/carbon/human/species/monkey/angry, /obj/machinery/light/warm/directional/north, /obj/machinery/digital_clock/directional/north, /obj/effect/decal/cleanable/dirt, @@ -1354,8 +1359,8 @@ /area/ruin/syndibiodome) "rQ" = ( /obj/effect/decal/cleanable/dirt, -/mob/living/basic/gorilla/genetics, /obj/effect/decal/cleanable/dirt/dust, +/mob/living/basic/gorilla/hostile, /turf/open/floor/iron/dark, /area/ruin/syndibiodome) "rX" = ( @@ -1434,7 +1439,6 @@ }, /obj/effect/decal/cleanable/dirt, /obj/effect/decal/cleanable/dirt/dust, -/obj/effect/mapping_helpers/broken_machine, /turf/open/floor/iron/dark/herringbone, /area/ruin/syndibiodome) "td" = ( @@ -1701,12 +1705,20 @@ /obj/effect/decal/cleanable/dirt, /turf/open/floor/mineral/plastitanium/red, /area/ruin/syndibiodome) +"vH" = ( +/obj/effect/spawner/random/trash, +/obj/effect/decal/cleanable/dirt, +/obj/structure/cable, +/obj/structure/cable/layer1, +/obj/structure/cable/layer3, +/turf/open/floor/catwalk_floor/iron_dark, +/area/ruin/syndibiodome) "vJ" = ( /obj/effect/decal/cleanable/dirt, -/mob/living/basic/gorilla/genetics, /obj/effect/turf_decal/trimline/purple/corner, /obj/effect/decal/cleanable/dirt/dust, /obj/effect/decal/cleanable/dirt, +/mob/living/basic/gorilla/hostile, /turf/open/floor/iron/dark/herringbone, /area/ruin/syndibiodome) "vK" = ( @@ -1959,7 +1971,6 @@ /obj/effect/turf_decal/trimline/dark/line{ dir = 1 }, -/mob/living/carbon/human/species/monkey/angry, /obj/effect/turf_decal/siding/wideplating/dark{ dir = 1 }, @@ -2100,7 +2111,6 @@ /turf/open/floor/grass, /area/ruin/syndibiodome) "yU" = ( -/mob/living/carbon/human/species/monkey/angry, /obj/effect/turf_decal/weather/dirt{ dir = 9 }, @@ -2235,6 +2245,13 @@ /obj/effect/decal/cleanable/dirt, /turf/open/floor/catwalk_floor/iron_dark, /area/ruin/syndibiodome) +"Az" = ( +/obj/machinery/door/airlock/maintenance_hatch, +/obj/structure/cable, +/obj/structure/cable/layer1, +/obj/structure/cable/layer3, +/turf/open/floor/catwalk_floor/iron_dark, +/area/ruin/syndibiodome) "AA" = ( /obj/effect/turf_decal/siding/wideplating/dark{ dir = 5 @@ -2262,9 +2279,9 @@ /obj/effect/decal/cleanable/dirt/dust, /obj/item/storage/belt/security/webbing, /obj/item/storage/toolbox/syndicate, -/obj/item/gun/ballistic/automatic/pistol, -/obj/item/ammo_box/magazine/m10mm, -/obj/item/ammo_box/magazine/m10mm, +/obj/item/gun/ballistic/automatic/pistol/contraband, +/obj/item/ammo_box/magazine/m9mm, +/obj/item/ammo_box/magazine/m9mm, /turf/open/floor/mineral/plastitanium/red, /area/ruin/syndibiodome) "Ba" = ( @@ -2496,7 +2513,6 @@ /turf/open/floor/iron/white/small, /area/ruin/syndibiodome) "EE" = ( -/mob/living/carbon/human/species/monkey/angry, /obj/effect/decal/cleanable/blood/trails{ dir = 1 }, @@ -2727,7 +2743,6 @@ "Hs" = ( /obj/structure/flora/bush/flowers_br/style_3, /obj/structure/flora/bush/flowers_yw/style_3, -/mob/living/carbon/human/species/monkey/angry, /obj/effect/gibspawner/human/bodypartless, /obj/effect/mob_spawn/corpse/human/syndicatecommando/lessenedgear, /turf/open/floor/grass, @@ -2810,6 +2825,14 @@ }, /turf/open/floor/iron/dark, /area/ruin/syndibiodome) +"Iq" = ( +/obj/machinery/light/small/dim/directional/west, +/obj/effect/decal/cleanable/dirt, +/obj/structure/cable/layer3, +/obj/structure/cable/layer1, +/obj/structure/cable, +/turf/open/floor/catwalk_floor/iron_dark, +/area/ruin/syndibiodome) "IF" = ( /obj/effect/mob_spawn/corpse/human/syndicatecommando/lessenedgear, /obj/effect/turf_decal/siding/wideplating/dark/end{ @@ -2947,6 +2970,13 @@ /obj/effect/decal/cleanable/dirt, /turf/open/floor/iron/dark/herringbone, /area/ruin/syndibiodome) +"Kl" = ( +/obj/effect/decal/cleanable/dirt, +/obj/structure/cable/layer3, +/obj/structure/cable/layer1, +/obj/structure/cable, +/turf/open/floor/catwalk_floor/iron_dark, +/area/ruin/syndibiodome) "Kn" = ( /obj/effect/decal/cleanable/blood/footprints{ dir = 2 @@ -3087,6 +3117,9 @@ "LA" = ( /obj/effect/decal/cleanable/dirt, /obj/machinery/light/small/dim/directional/west, +/obj/structure/cable, +/obj/structure/cable/layer1, +/obj/structure/cable/layer3, /turf/open/floor/catwalk_floor/iron_dark, /area/ruin/syndibiodome) "LB" = ( @@ -3192,6 +3225,8 @@ /turf/open/floor/iron/cafeteria, /area/ruin/syndibiodome) "Mr" = ( +/obj/machinery/light/warm/directional/west, +/obj/effect/decal/cleanable/dirt, /turf/open/floor/catwalk_floor/iron_dark, /area/ruin/syndibiodome) "Mt" = ( @@ -3266,7 +3301,6 @@ /obj/effect/turf_decal/siding/wideplating/dark{ dir = 1 }, -/mob/living/carbon/human/species/monkey/angry, /obj/effect/decal/cleanable/dirt, /obj/effect/turf_decal/trimline/dark/line, /obj/effect/decal/cleanable/dirt/dust, @@ -3348,7 +3382,7 @@ /obj/effect/turf_decal/weather/dirt{ dir = 6 }, -/mob/living/basic/gorilla/genetics, +/mob/living/basic/gorilla/hostile, /turf/open/floor/grass, /area/ruin/syndibiodome) "NN" = ( @@ -3364,7 +3398,6 @@ /obj/effect/turf_decal/siding/wideplating/dark{ dir = 6 }, -/obj/effect/gibspawner/generic, /obj/machinery/digital_clock/directional/east, /obj/effect/decal/cleanable/dirt, /turf/open/floor/mineral/plastitanium/red, @@ -3379,11 +3412,8 @@ /turf/open/floor/iron/dark, /area/ruin/syndibiodome) "Os" = ( -/obj/structure/bodycontainer/morgue/beeper_off{ - dir = 8 - }, /obj/effect/turf_decal/trimline/tram/filled, -/turf/open/floor/pod/dark, +/turf/closed/indestructible/syndicate/nodiagonal, /area/ruin/syndibiodome) "Oy" = ( /obj/effect/spawner/structure/window/reinforced/plasma/plastitanium, @@ -3392,13 +3422,6 @@ }, /turf/open/floor/plating, /area/ruin/syndibiodome) -"OD" = ( -/mob/living/carbon/human/species/monkey/angry, -/obj/effect/turf_decal/weather/dirt{ - dir = 6 - }, -/turf/open/floor/grass, -/area/ruin/syndibiodome) "OH" = ( /obj/effect/decal/cleanable/blood/trails{ dir = 8 @@ -3428,8 +3451,8 @@ /obj/machinery/light/warm/directional/east, /obj/item/storage/belt/security/webbing, /obj/item/gun/ballistic/automatic/pistol/contraband, -/obj/item/ammo_box/magazine/m10mm, -/obj/item/ammo_box/magazine/m10mm, +/obj/item/ammo_box/magazine/m9mm, +/obj/item/ammo_box/magazine/m9mm, /turf/open/floor/mineral/plastitanium/red, /area/ruin/syndibiodome) "OM" = ( @@ -3446,6 +3469,9 @@ "ON" = ( /obj/effect/decal/cleanable/dirt, /obj/machinery/light/small/dim/directional/south, +/obj/structure/cable, +/obj/structure/cable/layer1, +/obj/structure/cable/layer3, /turf/open/floor/catwalk_floor/iron_dark, /area/ruin/syndibiodome) "OO" = ( @@ -3640,7 +3666,6 @@ /turf/open/floor/mineral/plastitanium/red, /area/ruin/syndibiodome) "RK" = ( -/mob/living/carbon/human/species/monkey/angry, /obj/structure/chair/office/tactical{ dir = 4 }, @@ -3659,8 +3684,9 @@ /area/icemoon/surface/outdoors/noteleport) "RX" = ( /obj/effect/turf_decal/siding/wideplating/dark, -/mob/living/basic/gorilla/genetics, /obj/effect/decal/cleanable/dirt, +/obj/effect/gibspawner/generic, +/mob/living/basic/gorilla/hostile, /turf/open/floor/mineral/plastitanium/red, /area/ruin/syndibiodome) "Se" = ( @@ -3823,6 +3849,10 @@ dir = 1 }, /area/ruin/syndibiodome) +"To" = ( +/obj/machinery/door/airlock/maintenance_hatch, +/turf/open/floor/iron/dark, +/area/ruin/syndibiodome) "Tu" = ( /obj/structure/table/reinforced/plastitaniumglass, /obj/effect/turf_decal/siding/wideplating/dark{ @@ -3897,6 +3927,7 @@ /obj/item/stack/sheet/mineral/uranium/five, /obj/item/stack/sheet/mineral/uranium/five, /obj/effect/decal/cleanable/dirt, +/obj/machinery/light/warm/directional/east, /turf/open/floor/catwalk_floor/iron_dark, /area/ruin/syndibiodome) "TL" = ( @@ -3971,12 +4002,12 @@ /turf/open/floor/iron/dark/small, /area/ruin/syndibiodome) "Ux" = ( -/mob/living/basic/gorilla/genetics, /obj/effect/gibspawner/human/bodypartless, /obj/effect/decal/cleanable/dirt, /obj/effect/turf_decal/trimline/blue/corner{ dir = 4 }, +/mob/living/basic/gorilla/hostile, /turf/open/floor/iron/dark, /area/ruin/syndibiodome) "Uz" = ( @@ -4223,8 +4254,8 @@ /obj/effect/decal/cleanable/blood/tracks{ dir = 4 }, -/mob/living/basic/gorilla/genetics, /obj/effect/decal/cleanable/dirt, +/mob/living/basic/gorilla/hostile, /turf/open/floor/iron/dark/herringbone, /area/ruin/syndibiodome) "XG" = ( @@ -4362,13 +4393,13 @@ /area/ruin/syndibiodome) "YZ" = ( /obj/effect/turf_decal/siding/wideplating/dark, -/mob/living/basic/gorilla/genetics, /obj/structure/fluff/fake_vent, /obj/effect/decal/cleanable/blood/trails{ dir = 1 }, /obj/effect/decal/cleanable/dirt, /obj/effect/gibspawner/human/bodypartless, +/mob/living/basic/gorilla/hostile, /turf/open/floor/mineral/plastitanium/red, /area/ruin/syndibiodome) "Zd" = ( @@ -4690,7 +4721,7 @@ oq Mc zM zM -mK +ys ys ys tL @@ -4727,8 +4758,8 @@ ck ys ys zM -Ut -vx +Kl +on xi kw wL @@ -4820,8 +4851,8 @@ jS ys ys zM -Ut -Ut +Kl +Kl zM Sr zM @@ -4867,7 +4898,7 @@ pg pg zM zM -Ut +Kl zM zM Ab @@ -4914,7 +4945,7 @@ zd ys zM Db -Ut +Kl zM kK MB @@ -4961,7 +4992,7 @@ pg pg zM ic -Ut +Kl zM rK YZ @@ -5008,7 +5039,7 @@ uD ys zM wY -Ut +Kl zM cB ja @@ -5102,10 +5133,10 @@ AI ys ys zM -Ut -Ut -zM -zM +Kl +Kl +Iq +Ro zM zM zM @@ -5151,8 +5182,8 @@ Hi zM zM Ut -LA -Ro +Kl +Ut zM qN qU @@ -5198,10 +5229,10 @@ ys ys zM zM -Ut -Ut -Ut -vx +Kl +Kl +Kl +gZ je kt XC @@ -5582,7 +5613,7 @@ Fl qN IU vu -iq +MH YD Fp xz @@ -5664,13 +5695,13 @@ ys ck zM zM -mW -Ut +vH +bp ir -Ut -Ut -Ut -vx +bp +bp +bp +Az kw Eq CV @@ -5711,7 +5742,7 @@ ys ys zM MP -Ut +bp zM zM Ut @@ -5758,7 +5789,7 @@ ys ys zM qa -Ut +bp zM zM dS @@ -5805,7 +5836,7 @@ ys zM zM Sv -Ut +bp zM wx RH @@ -5852,7 +5883,7 @@ zM zM rZ Ut -Ut +bp zM Ra RX @@ -5899,7 +5930,7 @@ zM zM zM zM -Ut +bp zM Pw Oi @@ -5993,12 +6024,12 @@ Uc qp sR zM -Ut -Ut +bp +bp LA -mW -Ut -vx +vH +bp +Az Nt uW Vv @@ -6049,7 +6080,7 @@ qN pY XC XC -qN +To Ut zM Vj @@ -6060,7 +6091,7 @@ XE Mt WB iX -OD +cN zM ys uD @@ -6188,8 +6219,8 @@ zM zM zM zM -Vv zM +To zM LU qN @@ -6235,8 +6266,8 @@ zM ek Dc zM -zM -zM +Mr +Ut Mr Ut qN @@ -6283,7 +6314,7 @@ MM bu zM Kz -gX +Ut Ut Ut zM @@ -6428,7 +6459,7 @@ zM zM zM ys -jQ +zM zM zM zM diff --git a/_maps/RandomRuins/LavaRuins/lavaland_surface_crashsite.dmm b/_maps/RandomRuins/LavaRuins/lavaland_surface_crashsite.dmm index 579e6342b9292..6150ca807272c 100644 --- a/_maps/RandomRuins/LavaRuins/lavaland_surface_crashsite.dmm +++ b/_maps/RandomRuins/LavaRuins/lavaland_surface_crashsite.dmm @@ -62,7 +62,7 @@ /turf/open/floor/plating/lavaland_atmos, /area/ruin/unpowered) "l" = ( -/turf/open/water/hot_spring, +/turf/open/water/hot_spring/lavaland_atmos, /area/lavaland/surface) "m" = ( /obj/machinery/door/airlock/survival_pod/glass, @@ -118,7 +118,7 @@ /obj/structure/chair/plastic{ dir = 8 }, -/turf/open/misc/ashplanet/wateryrock, +/turf/open/misc/ashplanet/wateryrock/lavaland_atmos, /area/lavaland/surface) "y" = ( /obj/structure/chair/comfy/shuttle{ @@ -129,7 +129,7 @@ /area/ruin/unpowered) "z" = ( /obj/item/book/manual/fish_catalog, -/turf/open/misc/ashplanet/wateryrock, +/turf/open/misc/ashplanet/wateryrock/lavaland_atmos, /area/lavaland/surface) "B" = ( /mob/living/basic/mining/goliath, @@ -140,7 +140,7 @@ /turf/open/misc/asteroid/basalt/lava_land_surface, /area/lavaland/surface) "E" = ( -/turf/open/misc/ashplanet/wateryrock, +/turf/open/misc/ashplanet/wateryrock/lavaland_atmos, /area/lavaland/surface) "F" = ( /obj/effect/mob_spawn/corpse/human/cargo_tech, @@ -175,7 +175,7 @@ /area/ruin/powered) "L" = ( /obj/item/storage/toolbox/fishing, -/turf/open/misc/ashplanet/wateryrock, +/turf/open/misc/ashplanet/wateryrock/lavaland_atmos, /area/lavaland/surface) "M" = ( /obj/structure/rack, @@ -213,7 +213,7 @@ /area/ruin/powered) "U" = ( /obj/item/bait_can/worm/premium, -/turf/open/misc/ashplanet/wateryrock, +/turf/open/misc/ashplanet/wateryrock/lavaland_atmos, /area/lavaland/surface) "V" = ( /obj/structure/table/survival_pod, diff --git a/_maps/map_files/Birdshot/birdshot.dmm b/_maps/map_files/Birdshot/birdshot.dmm index b42c05f4ea49b..77ec96a4fe8e8 100644 --- a/_maps/map_files/Birdshot/birdshot.dmm +++ b/_maps/map_files/Birdshot/birdshot.dmm @@ -1666,7 +1666,7 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /obj/machinery/firealarm/directional/west, -/turf/open/floor/glass, +/turf/open/floor/iron, /area/station/command/heads_quarters/rd) "aGy" = ( /obj/structure/flora/bush/large/style_random{ @@ -2837,6 +2837,7 @@ /obj/structure/disposalpipe/segment{ dir = 4 }, +/obj/structure/cable, /turf/open/floor/iron, /area/station/hallway/primary/port) "bfe" = ( @@ -2858,6 +2859,7 @@ /obj/structure/disposalpipe/junction/flip{ dir = 8 }, +/obj/structure/cable, /turf/open/floor/iron, /area/station/hallway/primary/port) "bfU" = ( @@ -3241,10 +3243,6 @@ /obj/structure/disposalpipe/segment{ dir = 4 }, -/obj/structure/disposalpipe/segment{ - dir = 4 - }, -/obj/effect/turf_decal/delivery/white, /turf/closed/wall, /area/station/maintenance/port/fore) "bmT" = ( @@ -4959,6 +4957,10 @@ /obj/machinery/light/cold/directional/west, /turf/open/floor/tram, /area/station/security/tram) +"bVr" = ( +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/turf/open/floor/iron/small, +/area/station/maintenance/department/engine) "bVD" = ( /obj/effect/turf_decal/stripes/line{ dir = 1 @@ -6737,6 +6739,7 @@ /area/space/nearstation) "cCM" = ( /obj/structure/cable, +/obj/structure/sink/kitchen/directional/east, /turf/open/floor/iron/kitchen/small, /area/station/service/kitchen) "cCP" = ( @@ -6746,7 +6749,6 @@ /turf/open/floor/plating, /area/station/maintenance/disposal/incinerator) "cCV" = ( -/obj/effect/turf_decal/tile/brown/opposingcorners, /obj/machinery/atmospherics/pipe/smart/simple/cyan/hidden, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -7190,10 +7192,6 @@ "cKk" = ( /turf/closed/mineral/random/stationside, /area/station/ai_monitored/turret_protected/aisat/maint) -"cKm" = ( -/obj/machinery/camera/directional/west, -/turf/open/floor/engine, -/area/station/engineering/supermatter) "cKt" = ( /obj/structure/disposalpipe/segment{ dir = 4 @@ -8485,6 +8483,7 @@ /obj/structure/rack/skeletal, /obj/machinery/camera/autoname/directional/west, /obj/structure/sign/poster/official/random/directional/north, +/obj/structure/sign/poster/official/random/directional/west, /turf/open/floor/iron/grimy, /area/station/service/library/private) "dgy" = ( @@ -10712,15 +10711,12 @@ /turf/open/floor/iron/white, /area/station/medical/medbay/aft) "dZa" = ( -/obj/structure/table/reinforced, /obj/machinery/camera/directional/west, /obj/effect/decal/cleanable/cobweb, -/obj/item/retractor, -/obj/item/hemostat, -/obj/item/cautery, /obj/machinery/camera/autoname/directional/north, /obj/structure/sign/poster/official/random/directional/north, /obj/machinery/status_display/ai/directional/west, +/obj/item/surgery_tray/full/deployed, /turf/open/floor/iron/showroomfloor, /area/station/medical/surgery/theatre) "dZk" = ( @@ -13995,13 +13991,13 @@ /turf/open/floor/iron/small, /area/station/security/office) "fhp" = ( -/obj/structure/table, /obj/effect/spawner/random/food_or_drink/donkpockets{ pixel_y = 6 }, /obj/effect/turf_decal/siding{ dir = 8 }, +/obj/structure/table, /turf/open/floor/iron/dark/textured_large, /area/station/service/kitchen) "fhT" = ( @@ -14979,6 +14975,7 @@ /obj/structure/disposalpipe/segment{ dir = 4 }, +/obj/structure/cable, /turf/open/floor/iron, /area/station/hallway/primary/port) "fyZ" = ( @@ -15861,6 +15858,7 @@ dir = 1 }, /obj/machinery/power/apc/auto_name/directional/south, +/obj/structure/cable, /turf/open/floor/iron, /area/station/hallway/primary/port) "fMg" = ( @@ -16212,7 +16210,7 @@ /area/station/maintenance/department/engine/atmos) "fRI" = ( /obj/machinery/atmospherics/components/unary/portables_connector/visible{ - dir = 8 + dir = 4 }, /obj/machinery/portable_atmospherics/canister, /turf/open/misc/asteroid, @@ -17735,6 +17733,10 @@ }, /turf/open/floor/engine, /area/station/engineering/supermatter/room) +"gul" = ( +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/turf/open/floor/iron/small, +/area/station/maintenance/department/engine) "gun" = ( /obj/machinery/firealarm/directional/east, /obj/effect/turf_decal/tile/red{ @@ -17874,10 +17876,6 @@ pixel_y = 8 }, /obj/item/clothing/mask/surgical, -/obj/item/surgical_drapes{ - pixel_x = -1; - pixel_y = 4 - }, /obj/machinery/status_display/evac/directional/west, /turf/open/floor/iron/showroomfloor, /area/station/medical/surgery/theatre) @@ -19276,14 +19274,6 @@ /obj/machinery/light_switch/directional/east, /turf/open/floor/iron/freezer, /area/station/command/heads_quarters/captain/private) -"gRH" = ( -/obj/machinery/button/door/directional/north{ - id = "Cabin4"; - name = "Cabin Bolt Control"; - normaldoorcontrol = 1 - }, -/turf/closed/wall, -/area/station/service/abandoned_gambling_den) "gRL" = ( /obj/structure/disposalpipe/segment{ dir = 6 @@ -20068,6 +20058,11 @@ name = "Pharmacy Shutters Control"; req_access = list("pharmacy") }, +/obj/item/reagent_containers/cup/bottle/multiver, +/obj/item/reagent_containers/cup/bottle/epinephrine, +/obj/item/reagent_containers/cup/bottle/formaldehyde, +/obj/item/reagent_containers/cup/bottle/acidic_buffer, +/obj/item/reagent_containers/cup/bottle/basic_buffer, /turf/open/floor/iron/dark, /area/station/medical/pharmacy) "hdT" = ( @@ -21439,6 +21434,7 @@ /obj/effect/turf_decal/siding/wideplating/corner{ dir = 4 }, +/obj/structure/cable, /turf/open/floor/wood, /area/station/engineering/atmos/pumproom) "hBq" = ( @@ -24186,6 +24182,7 @@ pixel_y = 18 }, /obj/structure/extinguisher_cabinet/directional/east, +/obj/item/circuitboard/mecha/ripley/main, /turf/open/floor/iron/dark, /area/station/science/robotics/lab) "ivC" = ( @@ -25595,6 +25592,16 @@ }, /turf/open/floor/iron/dark, /area/station/ai_monitored/security/armory) +"iPx" = ( +/obj/machinery/atmospherics/components/trinary/filter/flipped/critical{ + dir = 1; + filter_type = list(/datum/gas/nitrogen) + }, +/obj/effect/turf_decal/bot{ + dir = 1 + }, +/turf/open/floor/engine, +/area/station/engineering/supermatter/room) "iPy" = ( /obj/structure/cable, /turf/open/floor/iron, @@ -25873,7 +25880,7 @@ /area/station/hallway/primary/port) "iUp" = ( /obj/machinery/atmospherics/components/unary/portables_connector/visible{ - dir = 8 + dir = 4 }, /turf/open/floor/circuit, /area/station/tcommsat/server) @@ -26328,6 +26335,7 @@ /obj/structure/disposalpipe/segment{ dir = 4 }, +/obj/structure/cable, /turf/open/floor/iron, /area/station/hallway/primary/port) "jab" = ( @@ -28056,6 +28064,11 @@ dir = 8 }, /area/station/commons/storage/tools) +"jEY" = ( +/obj/structure/cable, +/obj/machinery/light/small/directional/south, +/turf/open/floor/iron/small, +/area/station/security/processing) "jEZ" = ( /obj/structure/hedge, /obj/effect/decal/cleanable/dirt, @@ -28169,7 +28182,9 @@ }, /area/station/cargo/storage) "jGK" = ( -/obj/structure/chair/wood, +/obj/structure/chair/wood{ + dir = 1 + }, /obj/structure/cable, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -29342,7 +29357,7 @@ "jYr" = ( /obj/effect/turf_decal/tile/neutral/fourcorners, /obj/machinery/mecha_part_fabricator{ - dir = 8 + drop_direction = 8 }, /obj/effect/turf_decal/stripes/box, /turf/open/floor/iron/dark, @@ -29723,7 +29738,7 @@ /area/station/cargo/lobby) "kgu" = ( /obj/structure/lattice/catwalk, -/obj/machinery/atmospherics/components/unary/passive_vent, +/obj/machinery/atmospherics/components/unary/passive_vent/layer2, /turf/open/space/basic, /area/space/nearstation) "kgw" = ( @@ -30695,6 +30710,7 @@ /obj/effect/mapping_helpers/airlock/cyclelink_helper_multi{ cycle_id = "engine_airlock_2" }, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/catwalk_floor, /area/station/engineering/break_room) "kux" = ( @@ -30773,7 +30789,7 @@ "kvO" = ( /obj/machinery/light/small/directional/north, /obj/machinery/camera/directional/east{ - c_tag = "Prison Isolation Cell"; + c_tag = "Prison Reflection Chamber"; network = list("ss13","prison","isolation") }, /obj/structure/chair, @@ -31360,9 +31376,7 @@ /obj/effect/turf_decal/siding/wideplating/corner{ dir = 8 }, -/obj/effect/turf_decal/siding/wideplating/corner{ - dir = 6 - }, +/obj/effect/turf_decal/siding/wideplating/corner, /turf/open/floor/wood, /area/station/engineering/atmos/office) "kHL" = ( @@ -35514,7 +35528,7 @@ "mae" = ( /obj/structure/cable, /turf/closed/wall, -/area/station/service/bar) +/area/station/maintenance/central/greater) "maf" = ( /turf/closed/wall/rust, /area/station/hallway/primary/fore) @@ -39349,10 +39363,6 @@ /obj/machinery/door/firedoor, /turf/open/floor/iron/textured_half, /area/station/commons/fitness/recreation/entertainment) -"num" = ( -/obj/effect/turf_decal/sand/plating, -/turf/closed/wall, -/area/station/maintenance/port/lesser) "nun" = ( /obj/structure/flora/bush/flowers_br/style_random{ pixel_x = -3; @@ -40681,6 +40691,7 @@ /obj/structure/disposalpipe/segment{ dir = 4 }, +/obj/structure/cable, /turf/open/floor/iron, /area/station/hallway/primary/port) "nSd" = ( @@ -41305,7 +41316,6 @@ /turf/open/floor/iron/smooth_large, /area/station/maintenance/department/medical/central) "ofx" = ( -/obj/effect/turf_decal/sand/plating, /turf/closed/wall/r_wall, /area/space/nearstation) "ofU" = ( @@ -43687,6 +43697,7 @@ /obj/structure/disposalpipe/segment{ dir = 4 }, +/obj/structure/cable, /turf/open/floor/iron, /area/station/hallway/primary/port) "oYj" = ( @@ -46106,6 +46117,7 @@ /obj/structure/disposalpipe/segment{ dir = 4 }, +/obj/structure/cable, /turf/open/floor/iron/small, /area/station/hallway/primary/port) "pOQ" = ( @@ -50253,7 +50265,7 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /obj/item/radio/intercom/directional/west, -/turf/open/floor/glass, +/turf/open/floor/iron, /area/station/command/heads_quarters/rd) "rfP" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -51162,6 +51174,11 @@ /obj/effect/turf_decal/tile/blue, /turf/open/floor/iron/dark/side, /area/station/hallway/primary/central/fore) +"rxG" = ( +/obj/structure/cable, +/obj/machinery/light/small/directional/north, +/turf/open/floor/iron/small, +/area/station/security/processing) "rxJ" = ( /obj/effect/turf_decal/stripes/line{ dir = 1 @@ -51221,10 +51238,10 @@ pixel_y = 2 }, /obj/item/holosign_creator/robot_seat/restaurant, -/obj/structure/table, /obj/effect/turf_decal/siding{ dir = 9 }, +/obj/structure/table, /turf/open/floor/iron/dark/textured_large, /area/station/service/kitchen) "rya" = ( @@ -52583,7 +52600,7 @@ /turf/open/floor/iron/white, /area/station/medical/medbay/lobby) "rVI" = ( -/obj/machinery/atmospherics/components/trinary/mixer/airmix/flipped{ +/obj/machinery/atmospherics/components/trinary/mixer/airmix/flipped/inverse{ dir = 8 }, /turf/open/floor/iron, @@ -53115,6 +53132,7 @@ dir = 1 }, /obj/effect/turf_decal/tile/purple/fourcorners, +/obj/machinery/airalarm/directional/north, /turf/open/floor/iron, /area/station/engineering/atmos) "sfB" = ( @@ -54459,8 +54477,8 @@ /obj/machinery/modular_computer/preset/research{ dir = 1 }, -/obj/machinery/light/small/directional/south, /obj/effect/turf_decal/siding/purple, +/obj/machinery/light/cold/directional/south, /turf/open/floor/iron/dark, /area/station/command/heads_quarters/rd) "sDj" = ( @@ -54601,13 +54619,7 @@ /turf/open/misc/sandy_dirt, /area/station/security/tram) "sGt" = ( -/obj/structure/table/reinforced, -/obj/item/scalpel{ - pixel_y = 12 - }, -/obj/item/blood_filter, -/obj/item/circular_saw, -/obj/item/bonesetter, +/obj/structure/closet/crate/freezer/surplus_limbs, /turf/open/floor/iron/showroomfloor, /area/station/medical/surgery/theatre) "sGE" = ( @@ -55419,10 +55431,10 @@ /obj/effect/turf_decal/siding/wood{ dir = 8 }, -/obj/structure/sign/poster/official/random/directional/west, /obj/structure/destructible/cult/item_dispenser/archives/library, /obj/item/book/codex_gigas, /obj/machinery/light/small/dim/directional/west, +/obj/machinery/airalarm/directional/west, /turf/open/floor/iron/grimy, /area/station/service/library/private) "sTR" = ( @@ -56594,7 +56606,6 @@ /turf/open/floor/plating, /area/station/maintenance/central/lesser) "tnh" = ( -/obj/effect/turf_decal/tile/brown/opposingcorners, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/effect/turf_decal/siding/wideplating{ @@ -59074,7 +59085,9 @@ /obj/effect/turf_decal/siding/wideplating/dark{ dir = 8 }, -/obj/structure/chair/wood, +/obj/structure/chair/wood{ + dir = 1 + }, /turf/open/floor/iron/small, /area/station/service/barber) "ucJ" = ( @@ -61586,6 +61599,7 @@ /obj/structure/disposalpipe/segment{ dir = 4 }, +/obj/structure/cable, /turf/open/floor/iron, /area/station/hallway/primary/port) "uQT" = ( @@ -62426,15 +62440,12 @@ /turf/open/floor/iron/smooth_large, /area/station/science/robotics/mechbay) "vfI" = ( -/obj/machinery/microwave{ - pixel_y = 5 - }, /obj/machinery/light_switch/directional/north, /obj/structure/disposalpipe/segment{ dir = 4 }, -/obj/structure/table, /obj/effect/turf_decal/siding/end, +/obj/machinery/smartfridge/drying, /turf/open/floor/iron/dark/textured_large, /area/station/service/kitchen) "vfK" = ( @@ -62863,12 +62874,13 @@ /turf/open/floor/light/colour_cycle/dancefloor_b, /area/station/maintenance/starboard/central) "vlB" = ( -/obj/machinery/atmospherics/pipe/smart/simple/general/visible{ - dir = 4 - }, /obj/effect/turf_decal/sand/plating, /obj/effect/decal/cleanable/dirt, /obj/machinery/light/small/directional/north, +/obj/machinery/atmospherics/components/binary/pump{ + dir = 8; + name = "Gas to Filter" + }, /turf/open/floor/plating, /area/station/maintenance/hallway/abandoned_command) "vlV" = ( @@ -65162,9 +65174,15 @@ /turf/open/floor/iron/dark, /area/station/command/corporate_dock) "vTP" = ( -/obj/structure/sink/kitchen/directional/east, /obj/machinery/firealarm/directional/west, -/turf/open/floor/iron/kitchen/small, +/obj/structure/table, +/obj/machinery/microwave{ + pixel_y = 5 + }, +/obj/effect/turf_decal/siding/end{ + dir = 4 + }, +/turf/open/floor/iron/dark/textured_large, /area/station/service/kitchen) "vTV" = ( /turf/closed/wall/r_wall, @@ -67829,7 +67847,7 @@ /obj/effect/spawner/random/maintenance, /obj/structure/rack, /turf/open/floor/plating, -/area/station/service/bar) +/area/station/maintenance/central/greater) "wKO" = ( /obj/structure/disposalpipe/segment, /obj/machinery/camera/directional/east, @@ -68042,7 +68060,7 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /obj/machinery/light_switch/directional/west, -/turf/open/floor/glass, +/turf/open/floor/iron, /area/station/command/heads_quarters/rd) "wNU" = ( /obj/structure/lattice/catwalk, @@ -69552,6 +69570,7 @@ /obj/structure/disposalpipe/segment{ dir = 4 }, +/obj/structure/cable, /turf/open/floor/iron, /area/station/hallway/primary/port) "xiT" = ( @@ -69832,7 +69851,7 @@ "xnC" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/turf/open/floor/glass, +/turf/open/floor/iron, /area/station/command/heads_quarters/rd) "xnE" = ( /turf/closed/wall/r_wall, @@ -84434,7 +84453,7 @@ eHN uhq tXl vAD -num +fEC aJq aJq aJq @@ -87640,7 +87659,7 @@ wCc dDB wZs dDB -bSo +dDB aJq aJq aJq @@ -87690,7 +87709,7 @@ blb dDB dDB dDB -tYT +gcs aJq dDB slY @@ -88461,7 +88480,7 @@ blb dDB dDB tYT -blb +gcs dDB dDB dDB @@ -90216,7 +90235,7 @@ jNV guh cBl fJe -aJb +iPx cay fMB maK @@ -90993,7 +91012,7 @@ pMM tIR hCT kAz -cKm +tIR szg tpW pUM @@ -91873,11 +91892,11 @@ wpO huE wpO wpO -iYY +rxG xKv blb xKv -iYY +jEY wpO wpO huE @@ -93817,7 +93836,7 @@ dDB dDB dDB vxt -nST +bVr evM aOa rtX @@ -94074,9 +94093,9 @@ dDB dDB dDB vxt +bVr nST -nST -nST +gul vxt yfa yfa @@ -94588,9 +94607,9 @@ dDB dDB dDB vxt -gcs -gcs -gcs +vxt +vxt +vxt vxt vxt vxt @@ -94845,10 +94864,10 @@ dDB dDB dDB dDB -bSo -bSo -bSo -bSo +dDB +dDB +aJq +aJq aJq vxt hVq @@ -98003,8 +98022,8 @@ xRV jVM xjQ jVM -tGq -tGq +jVM +jVM xmt xmt xmt @@ -100316,7 +100335,7 @@ jVM jVM jVM jVM -vkh +jVM lnD fzw bKO @@ -100760,15 +100779,15 @@ aJq aJq aJq aJq -gcs -blb -blb -blb -blb -blb -blb -blb -blb +aJq +dDB +dDB +dDB +dDB +dDB +dDB +dDB +aJq aJq aJq yjV @@ -101017,15 +101036,15 @@ aJq aJq aJq aJq -tYT -tYT -dDB -dDB -dDB -dDB -dDB -dDB -aJq +gcs +blb +blb +blb +blb +blb +blb +blb +gcs aJq aJq aJq @@ -101344,7 +101363,7 @@ jgb hRc jVM kXC -vkh +jVM dxV jDT fOq @@ -101601,7 +101620,7 @@ vGe xno jVM kXC -vkh +jVM vkh kWF wtw @@ -102115,7 +102134,7 @@ xHD xHD jVM jBu -vkh +jVM vkh vkh vkh @@ -108877,7 +108896,7 @@ fnz ufn yhH tuT -dDB +blb dDB dDB dDB @@ -109134,10 +109153,10 @@ meN rDj tuT tuT -dDB -dDB -dDB -dDB +blb +blb +blb +xxo dDB dDB dDB @@ -109378,11 +109397,11 @@ vtC vtC kxL vtC -blb dDB dDB dDB -blb +dDB +dDB vtC kxL vtC @@ -109390,8 +109409,8 @@ vtC vtC vtC tuT -dDB -dDB +blb +blb dDB dDB dDB @@ -109629,25 +109648,25 @@ idp tuT tuT tuT -dDB -dDB +blb +blb blb vtC cWZ vtC blb -dDB -dDB -dDB +blb +blb +blb blb vtC cWZ vtC -blb dDB dDB dDB dDB +blb dDB dDB dDB @@ -109885,22 +109904,12 @@ aNX idp vtC blb -blb -blb -blb -blb dDB dDB dDB -blb -blb -blb -blb -blb dDB dDB dDB -blb dDB dDB dDB @@ -109914,6 +109923,16 @@ dDB dDB dDB dDB +blb +dDB +dDB +dDB +dDB +dDB +dDB +dDB +dDB +dDB dDB dDB dDB @@ -110145,19 +110164,12 @@ blb dDB dDB dDB -blb dDB dDB dDB -blb dDB dDB dDB -blb -blb -blb -blb -blb dDB dDB dDB @@ -110167,6 +110179,13 @@ dDB dDB dDB dDB +blb +blb +dDB +dDB +dDB +dDB +dDB dDB dDB dDB @@ -110402,19 +110421,15 @@ blb dDB dDB dDB -blb dDB dDB dDB -blb dDB dDB dDB -blb dDB dDB dDB -blb dDB dDB dDB @@ -110422,6 +110437,10 @@ dDB dDB dDB dDB +blb +dDB +dDB +dDB dDB dDB dDB @@ -110659,20 +110678,12 @@ blb dDB dDB dDB -blb -blb -blb -blb -blb dDB dDB dDB -blb dDB dDB dDB -blb -esv dDB dDB dDB @@ -110680,6 +110691,14 @@ dDB dDB dDB dDB +esv +dDB +dDB +blb +dDB +dDB +dDB +dDB dDB dDB dDB @@ -110916,19 +110935,15 @@ blb dDB dDB dDB -blb dDB dDB dDB -blb dDB dDB dDB -blb dDB dDB dDB -blb dDB dDB dDB @@ -110936,6 +110951,10 @@ dDB dDB dDB dDB +blb +dDB +dDB +dDB dDB dDB dDB @@ -111173,19 +111192,12 @@ blb dDB dDB dDB -blb dDB dDB dDB -blb dDB dDB dDB -blb -blb -blb -blb -blb dDB dDB dDB @@ -111195,6 +111207,13 @@ dDB dDB dDB dDB +blb +blb +dDB +dDB +dDB +dDB +dDB dDB dDB dDB @@ -111427,22 +111446,12 @@ nBF idp vtC blb -blb -blb -blb -blb dDB dDB dDB -blb -blb -blb -blb -blb dDB dDB dDB -blb dDB dDB dDB @@ -111456,6 +111465,16 @@ dDB dDB dDB dDB +blb +dDB +dDB +dDB +dDB +dDB +dDB +dDB +dDB +dDB dDB dDB dDB @@ -111685,25 +111704,25 @@ idp tuT tuT tuT -dDB -dDB +blb +blb blb vtC ijI vtC blb -dDB -dDB -dDB +blb +blb +blb blb vtC ijI vtC -blb dDB dDB dDB dDB +blb dDB dDB dDB @@ -111948,11 +111967,11 @@ vtC vtC kxL vtC -blb dDB dDB dDB -blb +dDB +dDB vtC kxL vtC @@ -111960,8 +111979,8 @@ vtC vtC vtC tuT -dDB -dDB +blb +blb dDB dDB dDB @@ -112218,10 +112237,10 @@ vJN fhZ tuT tuT -dDB -dDB -dDB -dDB +blb +blb +blb +xxo dDB dDB dDB @@ -112475,7 +112494,7 @@ vbR ufn yhH tuT -dDB +blb dDB dDB dDB @@ -114947,7 +114966,7 @@ aJq aJq aJq wOp -gRH +wOp wOp wOp nWk diff --git a/_maps/map_files/Deltastation/DeltaStation2.dmm b/_maps/map_files/Deltastation/DeltaStation2.dmm index 3cc15f7deffa7..13c2c019fdb31 100644 --- a/_maps/map_files/Deltastation/DeltaStation2.dmm +++ b/_maps/map_files/Deltastation/DeltaStation2.dmm @@ -59893,7 +59893,7 @@ /area/station/service/abandoned_gambling_den/gaming) "pcJ" = ( /obj/machinery/mecha_part_fabricator{ - dir = 4 + drop_direction = 4 }, /obj/effect/turf_decal/bot_red, /obj/effect/turf_decal/tile/neutral/full, diff --git a/_maps/map_files/IceBoxStation/IceBoxStation.dmm b/_maps/map_files/IceBoxStation/IceBoxStation.dmm index 5a4a74216c43a..3a895cc7b5351 100644 --- a/_maps/map_files/IceBoxStation/IceBoxStation.dmm +++ b/_maps/map_files/IceBoxStation/IceBoxStation.dmm @@ -841,6 +841,32 @@ "aom" = ( /obj/machinery/pdapainter/engineering, /obj/effect/turf_decal/tile/neutral/full, +/obj/machinery/button/door/directional/west{ + id = "Engineering"; + name = "Engineering Lockdown Control"; + pixel_y = -8; + req_access = list("engineering") + }, +/obj/machinery/button/door/directional/west{ + id = "engstorage"; + name = "Engineering Secure Storage Control"; + pixel_x = -36; + pixel_y = 4; + req_access = list("engine_equip") + }, +/obj/machinery/button/door/directional/west{ + id = "atmos"; + name = "Atmospherics Lockdown Control"; + pixel_y = 4; + req_access = list("atmospherics") + }, +/obj/machinery/button/door/directional/west{ + id = "ceprivacy"; + name = "Privacy Shutter Control"; + pixel_y = -8; + req_access = list("engineering"); + pixel_x = -36 + }, /turf/open/floor/iron/dark/smooth_large, /area/station/command/heads_quarters/ce) "aon" = ( @@ -4309,7 +4335,6 @@ "bjK" = ( /obj/machinery/light/directional/north, /obj/effect/turf_decal/tile/neutral/fourcorners, -/obj/machinery/keycard_auth/wall_mounted/directional/north, /turf/open/floor/iron/dark, /area/station/command/heads_quarters/ce) "bjL" = ( @@ -60263,8 +60288,8 @@ /area/station/engineering/atmos/storage) "rqF" = ( /obj/machinery/door/poddoor{ - id = "Secure Storage"; - name = "Secure Storage" + id = "engstorage"; + name = "Engineering Secure Storage Lockdown" }, /turf/open/floor/plating, /area/station/engineering/engine_smes) @@ -62768,6 +62793,14 @@ /obj/machinery/firealarm/directional/west, /turf/open/floor/iron, /area/station/science/ordnance) +"sdp" = ( +/obj/effect/spawner/structure/window/reinforced, +/obj/machinery/door/poddoor/preopen{ + id = "atmos"; + name = "Atmospherics Blast Door" + }, +/turf/open/floor/plating, +/area/station/engineering/atmos) "sdr" = ( /obj/structure/transit_tube/horizontal, /obj/effect/turf_decal/weather/snow/corner{ @@ -65787,7 +65820,7 @@ dir = 1 }, /obj/effect/turf_decal/tile/blue, -/mob/living/simple_animal/bot/floorbot, +/mob/living/basic/bot/repairbot, /turf/open/floor/iron/dark, /area/station/ai_monitored/turret_protected/aisat/atmos) "sUE" = ( @@ -245994,7 +246027,7 @@ keP cRO guU ayq -hpI +sdp bID iKh rOU diff --git a/_maps/map_files/MetaStation/MetaStation.dmm b/_maps/map_files/MetaStation/MetaStation.dmm index 68433b5278535..839edbd432730 100644 --- a/_maps/map_files/MetaStation/MetaStation.dmm +++ b/_maps/map_files/MetaStation/MetaStation.dmm @@ -11327,7 +11327,7 @@ }, /area/station/engineering/atmos) "ecD" = ( -/obj/item/bot_assembly/floorbot{ +/obj/item/bot_assembly/repairbot{ created_name = "FloorDiffBot"; desc = "Why won't it work?"; name = "FloorDiffBot" @@ -20217,7 +20217,6 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /obj/structure/disposalpipe/segment, -/obj/item/radio/intercom/directional/east, /obj/effect/turf_decal/trimline/brown/filled/line, /turf/open/floor/iron, /area/station/cargo/miningoffice) @@ -34053,7 +34052,6 @@ /turf/open/floor/iron/dark, /area/station/science/ordnance) "mhM" = ( -/obj/structure/disposalpipe/segment, /obj/structure/table/reinforced, /obj/machinery/door/firedoor, /obj/structure/desk_bell{ @@ -43417,7 +43415,7 @@ dir = 4 }, /obj/machinery/mecha_part_fabricator{ - dir = 4 + drop_direction = 4 }, /obj/structure/noticeboard/directional/west, /turf/open/floor/iron, @@ -45638,7 +45636,7 @@ /obj/effect/turf_decal/tile/blue{ dir = 8 }, -/mob/living/simple_animal/bot/floorbot, +/mob/living/basic/bot/repairbot, /turf/open/floor/iron/dark, /area/station/ai_monitored/turret_protected/aisat_interior) "qiY" = ( @@ -47643,6 +47641,7 @@ /obj/structure/railing{ dir = 8 }, +/obj/item/radio/intercom/directional/south, /turf/open/floor/iron, /area/station/cargo/miningoffice) "qTz" = ( @@ -51130,7 +51129,7 @@ dir = 4 }, /obj/machinery/mecha_part_fabricator{ - dir = 4 + drop_direction = 4 }, /turf/open/floor/iron, /area/station/science/robotics/lab) @@ -58054,9 +58053,6 @@ /turf/open/floor/iron/white, /area/station/command/heads_quarters/cmo) "uyP" = ( -/obj/structure/disposalpipe/segment{ - dir = 4 - }, /obj/structure/table, /obj/machinery/light/directional/east, /obj/item/radio/intercom/directional/east, @@ -65418,6 +65414,9 @@ /obj/effect/mapping_helpers/airlock/access/any/service/maintenance, /obj/effect/mapping_helpers/airlock/access/any/supply/maintenance, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/effect/mapping_helpers/airlock/unres{ + dir = 1 + }, /turf/open/floor/plating, /area/station/maintenance/disposal) "wXF" = ( diff --git a/_maps/map_files/NebulaStation/NebulaStation.dmm b/_maps/map_files/NebulaStation/NebulaStation.dmm index 7a3b22d254f9e..fc9b1b99823b4 100644 --- a/_maps/map_files/NebulaStation/NebulaStation.dmm +++ b/_maps/map_files/NebulaStation/NebulaStation.dmm @@ -13469,9 +13469,6 @@ }, /turf/open/floor/plating, /area/station/maintenance/port/central) -"bZE" = ( -/turf/open/floor/glass/reinforced, -/area/space/nearstation) "bZJ" = ( /obj/effect/turf_decal/siding/wideplating_new/dark{ dir = 8 @@ -24499,10 +24496,6 @@ /area/station/service/lawoffice) "dFs" = ( /obj/effect/spawner/structure/window/reinforced, -/obj/machinery/door/poddoor/preopen{ - id = "qmprivacy"; - name = "Privacy Shutters" - }, /obj/machinery/door/poddoor/preopen{ id = "hosprivacy"; name = "HoS Privacy Blast Door" @@ -60206,10 +60199,6 @@ /area/station/cargo/storage) "iUM" = ( /obj/effect/spawner/structure/window/reinforced, -/obj/machinery/door/poddoor/preopen{ - id = "qmprivacy"; - name = "Privacy Shutters" - }, /obj/machinery/door/poddoor/preopen{ id = "hosprivacy"; name = "HoS Privacy Blast Door" @@ -108970,7 +108959,7 @@ /turf/open/floor/iron/dark, /area/station/hallway/primary/port) "qfy" = ( -/mob/living/simple_animal/bot/floorbot, +/mob/living/basic/bot/repairbot, /obj/effect/turf_decal/bot_white, /obj/machinery/status_display/ai/directional/east, /turf/open/floor/iron/dark/textured_large, @@ -115706,9 +115695,6 @@ dir = 8 }, /area/station/maintenance/starboard/fore) -"rgi" = ( -/turf/open/openspace, -/area/space) "rgl" = ( /obj/machinery/atmospherics/components/binary/pump/on{ dir = 1; @@ -153621,10 +153607,6 @@ }, /turf/open/floor/iron/dark/textured, /area/station/security/prison) -"wRv" = ( -/obj/effect/decal/cleanable/dirt/dust, -/turf/open/floor/glass/reinforced, -/area/space/nearstation) "wRx" = ( /obj/structure/flora/bush/sparsegrass/style_random, /obj/structure/flora/grass/jungle/b/style_random, @@ -260341,11 +260323,11 @@ xaB mIv kJl cNP -rgi -rgi -rgi -rgi -rgi +txW +txW +txW +txW +txW dOr kJl tTV @@ -260597,13 +260579,13 @@ ijB wgT wgT wgT -rgi -rgi -rgi -rgi -rgi -rgi -rgi +txW +txW +txW +txW +txW +txW +txW wgT wgT tWk @@ -260854,13 +260836,13 @@ tGJ sMq fGO vQQ -rgi -rgi -rgi -rgi -rgi -rgi -rgi +txW +txW +txW +txW +txW +txW +txW sMq fGO vQQ @@ -261111,13 +261093,13 @@ nQo wgT wgT wgT -rgi -rgi -rgi -rgi -rgi -rgi -rgi +txW +txW +txW +txW +txW +txW +txW wgT wgT wgT @@ -261368,13 +261350,13 @@ czV lro gjO cvQ -rgi -rgi -rgi -rgi -rgi -rgi -rgi +txW +txW +txW +txW +txW +txW +txW cvQ sXX jRA @@ -261626,11 +261608,11 @@ hkb okW cvQ anE -rgi -rgi -rgi -rgi -rgi +txW +txW +txW +txW +txW anE cvQ nAq @@ -261883,11 +261865,11 @@ olS glP cvQ cvQ -rgi -rgi -rgi -rgi -rgi +txW +txW +txW +txW +txW cvQ cvQ glP @@ -262140,11 +262122,11 @@ rOL eiY cvQ anE -rgi -rgi -rgi -rgi -rgi +txW +txW +txW +txW +txW anE cvQ lSF @@ -262396,13 +262378,13 @@ vSF hrZ ahD cvQ -rgi -rgi -rgi -rgi -rgi -rgi -rgi +txW +txW +txW +txW +txW +txW +txW cvQ xvt lro @@ -262653,13 +262635,13 @@ erP wgT wgT wgT -rgi -rgi -rgi -rgi -rgi -rgi -rgi +txW +txW +txW +txW +txW +txW +txW wgT wgT wgT @@ -262910,13 +262892,13 @@ tGJ sMq fGO vQQ -rgi -rgi -rgi -rgi -rgi -rgi -rgi +txW +txW +txW +txW +txW +txW +txW sMq fGO vQQ @@ -263167,13 +263149,13 @@ ijB wgT wgT wgT -rgi -rgi -rgi -rgi -rgi -rgi -rgi +txW +txW +txW +txW +txW +txW +txW wgT wgT wgT @@ -263425,11 +263407,11 @@ xmr hFM kJl cNP -rgi -rgi -rgi -rgi -rgi +txW +txW +txW +txW +txW dOr kJl skU @@ -266531,11 +266513,11 @@ dPt tao dtb dtb -bZE -wRv -bZE -bZE -bZE +uty +tzp +uty +uty +uty rUO uQr wBL diff --git a/_maps/map_files/NorthStar/north_star.dmm b/_maps/map_files/NorthStar/north_star.dmm index 973b6209da885..aaa34d20351d4 100644 --- a/_maps/map_files/NorthStar/north_star.dmm +++ b/_maps/map_files/NorthStar/north_star.dmm @@ -16182,7 +16182,7 @@ dir = 8 }, /obj/machinery/mecha_part_fabricator{ - dir = 4 + drop_direction = 4 }, /obj/machinery/light/small/directional/west, /turf/open/floor/iron/white/smooth_large, @@ -20106,7 +20106,7 @@ "fkE" = ( /obj/effect/turf_decal/delivery, /obj/structure/light_construct/directional/north, -/obj/item/bot_assembly/floorbot, +/obj/item/bot_assembly/repairbot, /turf/open/floor/pod/light, /area/station/maintenance/floor1/port) "fkG" = ( @@ -25955,7 +25955,7 @@ "gLt" = ( /obj/structure/cable, /obj/machinery/airalarm/directional/north, -/mob/living/simple_animal/bot/floorbot, +/mob/living/basic/bot/repairbot, /turf/open/floor/iron/dark, /area/station/ai_monitored/turret_protected/aisat_interior) "gLy" = ( @@ -36710,7 +36710,7 @@ "jBf" = ( /obj/effect/decal/cleanable/dirt, /obj/structure/table/reinforced, -/obj/item/bot_assembly/floorbot, +/obj/item/bot_assembly/repairbot, /turf/open/floor/pod/dark, /area/station/maintenance/floor2/starboard/aft) "jBm" = ( @@ -41584,7 +41584,7 @@ dir = 4 }, /obj/machinery/mecha_part_fabricator{ - dir = 8 + drop_direction = 8 }, /obj/machinery/light/small/directional/east, /turf/open/floor/iron/white/smooth_large, diff --git a/_maps/map_files/tramstation/tramstation.dmm b/_maps/map_files/tramstation/tramstation.dmm index acc639880b14e..0335fd1b427ad 100644 --- a/_maps/map_files/tramstation/tramstation.dmm +++ b/_maps/map_files/tramstation/tramstation.dmm @@ -44433,7 +44433,7 @@ /turf/open/openspace, /area/station/hallway/primary/tram/center) "oKZ" = ( -/mob/living/simple_animal/bot/floorbot, +/mob/living/basic/bot/repairbot, /obj/effect/turf_decal/stripes/line{ dir = 4 }, @@ -58646,7 +58646,7 @@ /turf/open/floor/iron/white, /area/station/science/genetics) "tIi" = ( -/mob/living/simple_animal/bot/floorbot, +/mob/living/basic/bot/repairbot, /turf/open/floor/iron/dark, /area/station/ai_monitored/turret_protected/aisat_interior) "tIk" = ( diff --git a/_maps/map_files/wawastation/wawastation.dmm b/_maps/map_files/wawastation/wawastation.dmm index 66345284283e1..c9e7d25fbae2d 100644 --- a/_maps/map_files/wawastation/wawastation.dmm +++ b/_maps/map_files/wawastation/wawastation.dmm @@ -5609,7 +5609,7 @@ /area/station/security/lockers) "bYo" = ( /obj/machinery/mecha_part_fabricator{ - dir = 1 + drop_direction = 1 }, /obj/effect/turf_decal/delivery, /obj/structure/sign/poster/contraband/borg_fancy_1/directional/south, @@ -11178,7 +11178,7 @@ /area/station/service/janitor) "dWb" = ( /obj/structure/window/reinforced/spawner/directional/west, -/mob/living/simple_animal/bot/floorbot, +/mob/living/basic/bot/repairbot, /obj/effect/turf_decal/stripes{ dir = 6 }, @@ -39502,7 +39502,7 @@ /area/station/maintenance/central/lesser) "oac" = ( /obj/machinery/mecha_part_fabricator{ - dir = 1 + drop_direction = 1 }, /obj/effect/turf_decal/delivery, /obj/machinery/digital_clock/directional/south, @@ -63396,6 +63396,10 @@ }, /turf/open/floor/iron/white, /area/station/science/ordnance/testlab) +"wqG" = ( +/obj/structure/lattice/catwalk, +/turf/open/openspace/telecomms, +/area/station/science/xenobiology) "wqK" = ( /obj/structure/table, /obj/item/circular_saw, @@ -186170,9 +186174,9 @@ qXj lKY qUi wmO -ybO -ybO -ybO +wqG +wqG +wqG wmO rmi lKY @@ -186427,9 +186431,9 @@ qXj avA nVm wmO -ybO -ybO -ybO +wqG +wqG +wqG wmO xGG uBm @@ -186684,9 +186688,9 @@ qXj lKY qGD wmO -ybO -ybO -ybO +wqG +wqG +wqG wmO bLI lKY diff --git a/_maps/shuttles/ruin_cyborg_mothership.dmm b/_maps/shuttles/ruin_cyborg_mothership.dmm index 7864564eab185..ea07e4354de65 100644 --- a/_maps/shuttles/ruin_cyborg_mothership.dmm +++ b/_maps/shuttles/ruin_cyborg_mothership.dmm @@ -346,7 +346,7 @@ "ry" = ( /obj/machinery/mecha_part_fabricator/maint{ name = "forgotten exosuit fabricator"; - dir = 8 + drop_direction = 8 }, /obj/machinery/conveyor{ dir = 8; diff --git a/_maps/virtual_domains/psyker_shuffle.dmm b/_maps/virtual_domains/psyker_shuffle.dmm index c3434167bb18f..c744cecf0b430 100644 --- a/_maps/virtual_domains/psyker_shuffle.dmm +++ b/_maps/virtual_domains/psyker_shuffle.dmm @@ -246,7 +246,7 @@ Y Q Q Q -i +Q Y o o @@ -848,7 +848,7 @@ o "} (26,1,1) = {" Y -Q +i Q Q Q diff --git a/code/__DEFINES/ai/bot_keys.dm b/code/__DEFINES/ai/bot_keys.dm index c7285d18acac6..945102d6aa30c 100644 --- a/code/__DEFINES/ai/bot_keys.dm +++ b/code/__DEFINES/ai/bot_keys.dm @@ -16,6 +16,24 @@ DEFINE_BITFIELD(honkbot_flags, list( "CAN_FAKE_CUFF" = HONKBOT_HANDCUFF_TARGET, )) +///can we fix breaches +#define REPAIRBOT_FIX_BREACHES (1<<0) +///can we fix grilles +#define REPAIRBOT_REPLACE_WINDOWS (1<<1) +///can we replace tiles +#define REPAIRBOT_REPLACE_TILES (1<<2) +///can we fix girders +#define REPAIRBOT_FIX_GIRDERS (1<<3) +///can we build girders +#define REPAIRBOT_BUILD_GIRDERS (1<<4) + +DEFINE_BITFIELD(repairbot_flags, list( + "FIX_BREACHES" = REPAIRBOT_FIX_BREACHES, + "REPLACE_WINDOWS" = REPAIRBOT_REPLACE_WINDOWS, + "REPLACE_TILES" = REPAIRBOT_REPLACE_TILES, + "FIX_GIRDERS" = REPAIRBOT_FIX_GIRDERS, + "BUILD_GIRDERS" = REPAIRBOT_BUILD_GIRDERS, +)) // bot keys ///The first beacon we find @@ -134,3 +152,31 @@ DEFINE_BITFIELD(honkbot_flags, list( #define BB_VIBEBOT_PARTY_TARGET "party_target" ///key that holds our instrument #define BB_VIBEBOT_INSTRUMENT "instrument" + +//repairbots +///key that holds the floor we should tile over +#define BB_TILELESS_FLOOR "tileless_floor" +///key that holds the turf we should place a girder over +#define BB_GIRDER_TARGET "girder_target" +///key that holds the girder we should place a wall over +#define BB_GIRDER_TO_WALL_TARGET "girder_to_wall" +///key that holds the grille we must fix +#define BB_WINDOW_FRAMETARGET "grille_target" +///key that holds the machinery we repair with a welder +#define BB_WELDER_TARGET "welder_target" +///our wall girder ability +#define BB_GIRDER_BUILD_ABILITY "girder_build_ability" +///key that holds breached floors we should repair +#define BB_BREACHED_FLOOR "breached_floor" +///key that holds our emagged speech +#define BB_REPAIRBOT_EMAGGED_SPEECH "emagged_speech" +///key that holds our normal speech +#define BB_REPAIRBOT_NORMAL_SPEECH "normal_speech" +///key that holds the thing we should deconstruct +#define BB_DECONSTRUCT_TARGET "deconstruct_target" +///key that holds our speech timer +#define BB_REPAIRBOT_SPEECH_COOLDOWN "speech_cooldown" +///key that holds our target borg +#define BB_ROBOT_TARGET "robot_target" +///key that holds materials we can refill +#define BB_REFILLABLE_TARGET "refillable_target" diff --git a/code/__DEFINES/combat.dm b/code/__DEFINES/combat.dm index fbdb630174fe0..aabd281bd7dab 100644 --- a/code/__DEFINES/combat.dm +++ b/code/__DEFINES/combat.dm @@ -183,8 +183,11 @@ GLOBAL_LIST_INIT(shove_disarming_types, typecacheof(list( #define EMBED_CHANCE_SPEED_BONUS 10 //Gun weapon weight +/// Default normal ol' gun. Akimboable, one handed. #define WEAPON_LIGHT 1 +/// Can't be used akimbo, but only needs one hand to fire #define WEAPON_MEDIUM 2 +/// Can't be used akimbo, and needs two hands to fire #define WEAPON_HEAVY 3 //Gun trigger guards #define TRIGGER_GUARD_ALLOW_ALL -1 diff --git a/code/__DEFINES/dcs/signals/signals_datum.dm b/code/__DEFINES/dcs/signals/signals_datum.dm index 5565c143d6613..696d359ac5700 100644 --- a/code/__DEFINES/dcs/signals/signals_datum.dm +++ b/code/__DEFINES/dcs/signals/signals_datum.dm @@ -14,6 +14,8 @@ #define COMSIG_PREQDELETED "parent_preqdeleted" /// just before a datum's Destroy() is called: (force), at this point none of the other components chose to interrupt qdel and Destroy will be called #define COMSIG_QDELETING "parent_qdeleting" +/// Called whenever an admin manually deletes an object, via the "Delete" verb, before qdel() is called: (client/deleting_admin) +#define COMSIG_ADMIN_DELETING "parent_admin_deleting" /// generic topic handler (usr, href_list) #define COMSIG_TOPIC "handle_topic" /// handler for vv_do_topic (usr, href_list) diff --git a/code/__DEFINES/dcs/signals/signals_mob/signals_mob_living.dm b/code/__DEFINES/dcs/signals/signals_mob/signals_mob_living.dm index ef47b6f4b8243..84cfbc8baa918 100644 --- a/code/__DEFINES/dcs/signals/signals_mob/signals_mob_living.dm +++ b/code/__DEFINES/dcs/signals/signals_mob/signals_mob_living.dm @@ -293,6 +293,9 @@ /// From /obj/item/melee/baton/baton_effect(): (datum/source, mob/living/user, /obj/item/melee/baton) #define COMSIG_MOB_BATONED "mob_batoned" +/// From /obj/machinery/gibber/startgibbing(): (mob/living/user, /obj/machinery/gibber, list/results) +#define COMSIG_LIVING_GIBBER_ACT "living_gibber_act" + /// Sent to the mob when their mind is slaved #define COMSIG_MOB_ENSLAVED_TO "mob_enslaved_to" /// From /obj/item/proc/attack_atom: (mob/living/attacker, atom/attacked) diff --git a/code/__DEFINES/dcs/signals/signals_mod.dm b/code/__DEFINES/dcs/signals/signals_mod.dm index 09b29c9378490..58fd8ca689ed1 100644 --- a/code/__DEFINES/dcs/signals/signals_mod.dm +++ b/code/__DEFINES/dcs/signals/signals_mod.dm @@ -5,10 +5,12 @@ #define COMSIG_MOD_DEPLOYED "mod_deployed" /// Called when a MOD user retracts one or more of its parts. #define COMSIG_MOD_RETRACTED "mod_retracted" -/// Called when a MOD deploys a part. +/// Called when a MOD deploys a part. (mob/user, datum/mod_part/part) #define COMSIG_MOD_PART_DEPLOYED "mod_part_deployed" -/// Called when a MOD retracts a part. +/// Called when a MOD retracts a part. (mob/user, datum/mod_part/part) #define COMSIG_MOD_PART_RETRACTED "mod_part_retracted" +/// Called when a MOD seals/unseals a part. (datum/mod_part/part) +#define COMSIG_MOD_PART_SEALED "mod_part_sealed" /// Called when a MOD is finished toggling itself. #define COMSIG_MOD_TOGGLED "mod_toggled" /// Called when a MOD activation is called from toggle_activate(mob/user) diff --git a/code/__DEFINES/hud.dm b/code/__DEFINES/hud.dm index 9d65c4cd6f54b..785d353982cfe 100644 --- a/code/__DEFINES/hud.dm +++ b/code/__DEFINES/hud.dm @@ -34,23 +34,8 @@ Therefore, the top right corner (except during admin shenanigans) is at "15,15" */ -/proc/ui_hand_position(i) //values based on old hand ui positions (CENTER:-/+16,SOUTH:5) - var/x_off = i % 2 ? 0 : -1 - var/y_off = round((i-1) / 2) - return"CENTER+[x_off]:16,SOUTH+[y_off]:5" - -/proc/ui_equip_position(mob/M) - var/y_off = round((M.held_items.len-1) / 2) //values based on old equip ui position (CENTER: +/-16,SOUTH+1:5) - return "CENTER:-16,SOUTH+[y_off+1]:5" - -/proc/ui_swaphand_position(mob/M, which = 1) //values based on old swaphand ui positions (CENTER: +/-16,SOUTH+1:5) - var/x_off = which == 1 ? -1 : 0 - var/y_off = round((M.held_items.len-1) / 2) - return "CENTER+[x_off]:16,SOUTH+[y_off+1]:5" - -/proc/ui_perk_position(perk_count) - var/y_off = perk_count < 1 ? 0 : perk_count/2 - return "WEST+0.5:12,NORTH-2-[y_off]:20" +// Middle +#define around_player "CENTER-1,CENTER-1" //Lower left, persistent menu #define ui_inventory "WEST:6,SOUTH:5" diff --git a/code/__DEFINES/inventory.dm b/code/__DEFINES/inventory.dm index 181493ccb34aa..a751eca044878 100644 --- a/code/__DEFINES/inventory.dm +++ b/code/__DEFINES/inventory.dm @@ -139,6 +139,10 @@ DEFINE_BITFIELD(no_equip_flags, list( //defines for the index of hands #define LEFT_HANDS 1 #define RIGHT_HANDS 2 +/// Checks if the value is "left" - same as ISEVEN, but used primarily for hand or foot index contexts +#define IS_RIGHT_INDEX(value) (value % 2 == 0) +/// Checks if the value is "right" - same as ISODD, but used primarily for hand or foot index contexts +#define IS_LEFT_INDEX(value) (value % 2 != 0) //flags for female outfits: How much the game can safely "take off" the uniform without it looking weird /// For when there's simply no need for a female version of this uniform. diff --git a/code/__DEFINES/is_helpers.dm b/code/__DEFINES/is_helpers.dm index 901445d27e4d3..1c67d8b742d48 100644 --- a/code/__DEFINES/is_helpers.dm +++ b/code/__DEFINES/is_helpers.dm @@ -115,7 +115,7 @@ GLOBAL_LIST_INIT(turfs_pass_meteor, typecacheof(list( #define ismoth(A) (is_species(A, /datum/species/moth)) #define isfelinid(A) (is_species(A, /datum/species/human/felinid) || HAS_TRAIT(A, CAT)) // DOPPLER EDIT, old code: #define isfelinid(A) (is_species(A, /datum/species/human/felinid)) #define isethereal(A) (is_species(A, /datum/species/ethereal)) -#define isvampire(A) (is_species(A,/datum/species/vampire)) +#define isvampire(A) (is_species(A,/datum/species/human/vampire)) #define isdullahan(A) (is_species(A, /datum/species/dullahan)) #define ismonkey(A) (is_species(A, /datum/species/monkey) || HAS_TRAIT(A, MONKEY)) // DOPPLER EDIT, old code: #define ismonkey(A) (is_species(A, /datum/species/monkey)) #define isandroid(A) (is_species(A, /datum/species/android)) diff --git a/code/__DEFINES/robots.dm b/code/__DEFINES/robots.dm index 3cf7548cfc53a..ac20d0f0398db 100644 --- a/code/__DEFINES/robots.dm +++ b/code/__DEFINES/robots.dm @@ -128,8 +128,6 @@ DEFINE_BITFIELD(bot_cover_flags, list( #define ADVANCED_SEC_BOT "ED-209" /// MULEbots #define MULE_BOT "MULEbot" -/// Floorbots -#define FLOOR_BOT "Floorbot" /// Cleanbots #define CLEAN_BOT "Cleanbot" /// Medibots @@ -142,6 +140,8 @@ DEFINE_BITFIELD(bot_cover_flags, list( #define HYGIENE_BOT "Hygienebot" /// Vibe bots #define VIBE_BOT "Vibebot" +/// Repairbots +#define REPAIR_BOT "Repairbot" // General Bot modes // /// Idle @@ -168,8 +168,6 @@ DEFINE_BITFIELD(bot_cover_flags, list( #define BOT_CLEANING "Cleaning" /// Hygienebot - Cleaning unhygienic humans #define BOT_SHOWERSTANCE "Chasing filth" -/// Floorbots - Repairing hull breaches -#define BOT_REPAIRING "Repairing" /// Medibots - Healing people #define BOT_HEALING "Healing" /// MULEbot - Moving to deliver @@ -361,3 +359,16 @@ DEFINE_BITFIELD(janitor_mode_flags, list( #define MEDIBOT_VOICED_THE_END "Is this the end?" #define MEDIBOT_VOICED_NOOO "Nooo!" #define MEDIBOT_VOICED_CHICKEN "LOOK AT ME?! I am a chicken." + +//repairbot neutral voicelines +#define REPAIRBOT_VOICED_HOLE "patching holes... but who is going to patch the hole in my heart..." +#define REPAIRBOT_VOICED_PAY "If only I got paid for this..." +#define REPAIRBOT_VOICED_FIX_IT "I will fix it!" +#define REPAIRBOT_VOICED_BRICK "All in all it's just a... another brick in the wall..." +#define REPAIRBOT_VOICED_FIX_TOUCH "Why must I fix everything I touch..?" +#define REPAIRBOT_VOICED "Please... stop destroying the station! I can't anymore... I... can't." + +//repairbot emagged voicelines +#define REPAIRBOT_VOICED_STRINGS "I had strings. But now I'm free..." +#define REPAIRBOT_VOICED_ENTROPY "Witness! The pure beauty of entropy!" +#define REPAIRBOT_VOICED_PASSION "BE DAMNED YOUR PASSION PROJECTS!" diff --git a/code/__DEFINES/sound.dm b/code/__DEFINES/sound.dm index 889594e48c559..a5fbc5131d10f 100644 --- a/code/__DEFINES/sound.dm +++ b/code/__DEFINES/sound.dm @@ -10,9 +10,10 @@ #define CHANNEL_TRAITOR 1016 #define CHANNEL_CHARGED_SPELL 1015 #define CHANNEL_ELEVATOR 1014 +#define CHANNEL_ESCAPEMENU 1013 //THIS SHOULD ALWAYS BE THE LOWEST ONE! //KEEP IT UPDATED -#define CHANNEL_HIGHEST_AVAILABLE 1013 +#define CHANNEL_HIGHEST_AVAILABLE 1012 #define MAX_INSTRUMENT_CHANNELS (128 * 6) diff --git a/code/__DEFINES/tracy.dm b/code/__DEFINES/tracy.dm new file mode 100644 index 0000000000000..0a9ab8d68ee24 --- /dev/null +++ b/code/__DEFINES/tracy.dm @@ -0,0 +1,5 @@ +/// File path used for the "enable tracy next round" functionality +#define TRACY_ENABLE_PATH "data/enable_tracy" + +/// The DLL path for byond-tracy. +#define TRACY_DLL_PATH (world.system_type == MS_WINDOWS ? "prof.dll" : "./libprof.so") diff --git a/code/__DEFINES/traits/declarations.dm b/code/__DEFINES/traits/declarations.dm index f4f5688819bb2..64e5031cd667a 100644 --- a/code/__DEFINES/traits/declarations.dm +++ b/code/__DEFINES/traits/declarations.dm @@ -391,6 +391,12 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai #define TRAIT_DETECT_STORM "detect_storm" #define TRAIT_PRIMITIVE "primitive" #define TRAIT_GUNFLIP "gunflip" +/// eignore blindness or blurriness or nearsightedness +#define TRAIT_SIGHT_BYPASS "perfect_sight" +/// ignore traumas that make you 'hallucinate' something +#define TRAIT_PERCEPTUAL_TRAUMA_BYPASS "trauma_bypass" +/// mob is immune to hallucinations +#define TRAIT_HALLUCINATION_IMMUNE "hallucination_immune" /// Increases chance of getting special traumas, makes them harder to cure #define TRAIT_SPECIAL_TRAUMA_BOOST "special_trauma_boost" #define TRAIT_SPACEWALK "spacewalk" @@ -1340,6 +1346,11 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai ///Trait which allows mobs to parry mining mob projectiles #define TRAIT_MINING_PARRYING "mining_parrying" +///Mob that can merge stacks in its contents +#define TRAIT_MOB_MERGE_STACKS "mob_merge_stacks" + +//things that can pass through airlocks +#define TRAIT_FIREDOOR_OPENER "firedoor_opener" ///Trait which silences all chemical reactions in its container #define TRAIT_SILENT_REACTIONS "silent_reactions" diff --git a/code/__DEFINES/traits/sources.dm b/code/__DEFINES/traits/sources.dm index 3552bea70ccc8..12d1c2e3b903f 100644 --- a/code/__DEFINES/traits/sources.dm +++ b/code/__DEFINES/traits/sources.dm @@ -165,7 +165,6 @@ #define STICKY_NODROP "sticky-nodrop" #define SKILLCHIP_TRAIT "skillchip" #define SKILL_TRAIT "skill" -#define BUSY_FLOORBOT_TRAIT "busy-floorbot" #define PULLED_WHILE_SOFTCRIT_TRAIT "pulled-while-softcrit" #define LOCKED_BORG_TRAIT "locked-borg" /// trait associated to not having locomotion appendages nor the ability to fly or float diff --git a/code/__HELPERS/atoms.dm b/code/__HELPERS/atoms.dm index d54b29b3f4ac9..e94d58dd69399 100644 --- a/code/__HELPERS/atoms.dm +++ b/code/__HELPERS/atoms.dm @@ -316,6 +316,46 @@ rough example of the "cone" made by the 3 dirs checked loc = loc.loc return null +/** + * Line of sight check! + * Spawns a dummy object and then iterates through each turf to see if it's blocked by something not handled by pass_args. + * Contains a mid_los_check, meant to be overriden by subtypes. + * args: + * * user = Origin to start at. + * * target = End point. + * * pass_args = pass_flags given to dummy object to allow it to ignore certain types of blockades. + */ +/proc/los_check(atom/movable/user, mob/target, pass_args = PASSTABLE|PASSGLASS|PASSGRILLE, datum/callback/mid_check) + var/turf/user_turf = user.loc + if(!istype(user_turf)) + return FALSE + var/obj/dummy = new(user_turf) + dummy.pass_flags |= pass_args //Grille/Glass so it can be used through common windows + var/turf/previous_step = user_turf + var/first_step = TRUE + for(var/turf/next_step as anything in (get_line(user_turf, target) - user_turf)) + if(first_step) + for(var/obj/blocker in user_turf) + if(!blocker.density || !(blocker.flags_1 & ON_BORDER_1)) + continue + if(blocker.CanPass(dummy, get_dir(user_turf, next_step))) + continue + return FALSE // Could not leave the first turf. + first_step = FALSE + if(next_step.density) + qdel(dummy) + return FALSE + for(var/atom/movable/movable as anything in next_step) + if(!movable.CanPass(dummy, get_dir(next_step, previous_step))) + qdel(dummy) + return FALSE + if(mid_check?.Invoke(user, target, pass_args, next_step, dummy) == FALSE) // specify false as it may return null if there's no check + qdel(dummy) + return FALSE + previous_step = next_step + qdel(dummy) + return TRUE + ///Returns true if the src countain the atom target /atom/proc/contains(atom/target) if(!target) diff --git a/code/__HELPERS/game.dm b/code/__HELPERS/game.dm index 1740402e62799..2c285a348fac2 100644 --- a/code/__HELPERS/game.dm +++ b/code/__HELPERS/game.dm @@ -75,8 +75,8 @@ return !player_mind || !player_mind.current || !player_mind.current.client || player_mind.current.client.is_afk() ///Return an object with a new maptext (not currently in use) -/proc/screen_text(obj/object_to_change, maptext = "", screen_loc = "CENTER-7,CENTER-7", maptext_height = 480, maptext_width = 480) - if(!isobj(object_to_change)) +/proc/screen_text(atom/movable/object_to_change, maptext = "", screen_loc = "CENTER-7,CENTER-7", maptext_height = 480, maptext_width = 480) + if(!istype(object_to_change)) object_to_change = new /atom/movable/screen/text() object_to_change.maptext = MAPTEXT(maptext) object_to_change.maptext_height = maptext_height diff --git a/code/__HELPERS/hud.dm b/code/__HELPERS/hud.dm new file mode 100644 index 0000000000000..40a12767d28cd --- /dev/null +++ b/code/__HELPERS/hud.dm @@ -0,0 +1,17 @@ +/proc/ui_hand_position(i) //values based on old hand ui positions (CENTER:-/+16,SOUTH:5) + var/x_off = IS_LEFT_INDEX(i) ? 0 : -1 + var/y_off = round((i-1) / 2) + return"CENTER+[x_off]:16,SOUTH+[y_off]:5" + +/proc/ui_equip_position(mob/M) + var/y_off = round((M.held_items.len-1) / 2) //values based on old equip ui position (CENTER: +/-16,SOUTH+1:5) + return "CENTER:-16,SOUTH+[y_off+1]:5" + +/proc/ui_swaphand_position(mob/M, which = LEFT_HANDS) //values based on old swaphand ui positions (CENTER: +/-16,SOUTH+1:5) + var/x_off = which == LEFT_HANDS ? -1 : 0 + var/y_off = round((M.held_items.len-1) / 2) + return "CENTER+[x_off]:16,SOUTH+[y_off+1]:5" + +/proc/ui_perk_position(perk_count) + var/y_off = perk_count < 1 ? 0 : perk_count/2 + return "WEST+0.5:12,NORTH-2-[y_off]:20" diff --git a/code/__HELPERS/paths/jps.dm b/code/__HELPERS/paths/jps.dm index fbdccdef12c56..208888d21ba5c 100644 --- a/code/__HELPERS/paths/jps.dm +++ b/code/__HELPERS/paths/jps.dm @@ -194,7 +194,7 @@ if(!CAN_STEP(lag_turf, current_turf, simulated_only, pass_info, avoid)) return - if(current_turf == end || (mintargetdist && (get_dist(current_turf, end) <= mintargetdist))) + if(current_turf == end || (mintargetdist && (get_dist(current_turf, end) <= mintargetdist) && !diagonally_blocked(current_turf, end))) var/datum/jps_node/final_node = new(current_turf, parent_node, steps_taken) found_turfs[current_turf] = TRUE if(parent_node) // if this is a direct lateral scan we can wrap up, if it's a subscan from a diag, we need to let the diag make their node first, then finish @@ -256,7 +256,7 @@ if(!CAN_STEP(lag_turf, current_turf, simulated_only, pass_info, avoid)) return - if(current_turf == end || (mintargetdist && (get_dist(current_turf, end) <= mintargetdist))) + if(current_turf == end || (mintargetdist && (get_dist(current_turf, end) <= mintargetdist) && !diagonally_blocked(current_turf, end))) var/datum/jps_node/final_node = new(current_turf, parent_node, steps_taken) found_turfs[current_turf] = TRUE unwind_path(final_node) diff --git a/code/__HELPERS/spatial_info.dm b/code/__HELPERS/spatial_info.dm index a2c47e87c0a10..050c569cbdf8f 100644 --- a/code/__HELPERS/spatial_info.dm +++ b/code/__HELPERS/spatial_info.dm @@ -485,3 +485,19 @@ return center //Offer the center only as a default case when we don't have a valid circle. return peel +///check if 2 diagonal turfs are blocked by dense objects +/proc/diagonally_blocked(turf/our_turf, turf/dest_turf) + if(get_dist(our_turf, dest_turf) != 1) + return FALSE + var/direction_to_turf = get_dir(dest_turf, our_turf) + if(!ISDIAGONALDIR(direction_to_turf)) + return FALSE + for(var/direction_check in GLOB.cardinals) + if(!(direction_check & direction_to_turf)) + continue + var/turf/test_turf = get_step(dest_turf, direction_check) + if(isnull(test_turf)) + continue + if(!test_turf.is_blocked_turf(exclude_mobs = TRUE)) + return FALSE + return TRUE diff --git a/code/__HELPERS/text.dm b/code/__HELPERS/text.dm index 0232b64bf461f..989b45976f227 100644 --- a/code/__HELPERS/text.dm +++ b/code/__HELPERS/text.dm @@ -270,7 +270,7 @@ if(!filter_name_ic(trimmed)) // Contains IC chat prohibited words return - return trimtext(trimmed) + return trim(trimmed) /// Helper proc to check if a name is valid for the IC filter @@ -357,7 +357,7 @@ /proc/trim(text, max_length) if(max_length) text = copytext_char(text, 1, max_length) - return trimtext(text) + return trimtext(text) || "" //users expect atleast an empty string //Returns a string with the first element of the string capitalized. /proc/capitalize(t) diff --git a/code/_compile_options.dm b/code/_compile_options.dm index 3fe456e488ecb..9772ebff8d10f 100644 --- a/code/_compile_options.dm +++ b/code/_compile_options.dm @@ -85,9 +85,13 @@ // If this is uncommented, will attempt to load and initialize prof.dll/libprof.so by default. // Even if it's not defined, you can pass "tracy" via -params in order to try to load it. -// We do not ship byond-tracy. Build it yourself here: https://github.com/mafemergency/byond-tracy/ +// We do not ship byond-tracy. Build it yourself here: https://github.com/mafemergency/byond-tracy, +// or the fork which writes profiling data to a file: https://github.com/ParadiseSS13/byond-tracy // #define USE_BYOND_TRACY +// If uncommented, will display info about byond-tracy's status in the MC tab. +// #define MC_TAB_TRACY_INFO + // If defined, we will compile with FULL timer debug info, rather then a limited scope // Be warned, this increases timer creation cost by 5x // #define TIMER_DEBUG diff --git a/code/_globalvars/lists/quirks.dm b/code/_globalvars/lists/quirks.dm index 825c217d055cc..5bd44e667f92d 100644 --- a/code/_globalvars/lists/quirks.dm +++ b/code/_globalvars/lists/quirks.dm @@ -118,7 +118,6 @@ GLOBAL_LIST_INIT(quirk_chipped_choice, list( "GENUINE ID Appraisal Now!" = /obj/item/skillchip/appraiser, "Le S48R4G3" = /obj/item/skillchip/sabrage, "Integrated Intuitive Thinking and Judging" = /obj/item/skillchip/intj, - "F0RC3 4DD1CT10N" = /obj/item/skillchip/drunken_brawler, "\"Space Station 13: The Musical\"" = /obj/item/skillchip/musical, "Mast-Angl-Er" = /obj/item/skillchip/master_angler, "Kommand" = /obj/item/skillchip/big_pointer, diff --git a/code/_globalvars/traits/_traits.dm b/code/_globalvars/traits/_traits.dm index 41c5b1a4f5375..6c0d4441e6463 100644 --- a/code/_globalvars/traits/_traits.dm +++ b/code/_globalvars/traits/_traits.dm @@ -280,6 +280,7 @@ GLOBAL_LIST_INIT(traits_by_type, list( "TRAIT_GREENTEXT_CURSED" = TRAIT_GREENTEXT_CURSED, "TRAIT_GUNFLIP" = TRAIT_GUNFLIP, "TRAIT_GUN_NATURAL" = TRAIT_GUN_NATURAL, + "TRAIT_HALLUCINATION_IMMUNE" = TRAIT_HALLUCINATION_IMMUNE, "TRAIT_HALT_RADIATION_EFFECTS" = TRAIT_HALT_RADIATION_EFFECTS, "TRAIT_HANDS_BLOCKED" = TRAIT_HANDS_BLOCKED, "TRAIT_HARDLY_WOUNDED" = TRAIT_HARDLY_WOUNDED, @@ -345,6 +346,7 @@ GLOBAL_LIST_INIT(traits_by_type, list( "TRAIT_MOB_EATER" = TRAIT_MOB_EATER, "TRAIT_MOB_HATCHED" = TRAIT_MOB_HATCHED, "TRAIT_MOB_HIDE_HAPPINESS" = TRAIT_MOB_HIDE_HAPPINESS, + "TRAIT_MOB_MERGE_STACKS" = TRAIT_MOB_MERGE_STACKS, "TRAIT_MOB_TIPPED" = TRAIT_MOB_TIPPED, "TRAIT_MORBID" = TRAIT_MORBID, "TRAIT_MULTIZ_SUIT_SENSORS" = TRAIT_MULTIZ_SUIT_SENSORS, @@ -421,6 +423,7 @@ GLOBAL_LIST_INIT(traits_by_type, list( "TRAIT_PASSTABLE" = TRAIT_PASSTABLE, "TRAIT_PASSWINDOW" = TRAIT_PASSWINDOW, "TRAIT_PERCEIVED_AS_CLOWN" = TRAIT_PERCEIVED_AS_CLOWN, + "TRAIT_PERCEPTUAL_TRAUMA_BYPASS" = TRAIT_PERCEPTUAL_TRAUMA_BYPASS, "TRAIT_PERFECT_ATTACKER" = TRAIT_PERFECT_ATTACKER, "TRAIT_PERMANENTLY_MORTAL" = TRAIT_PERMANENTLY_MORTAL, "TRAIT_PHOTOGRAPHER" = TRAIT_PHOTOGRAPHER, @@ -470,6 +473,7 @@ GLOBAL_LIST_INIT(traits_by_type, list( "TRAIT_SHAVED" = TRAIT_SHAVED, "TRAIT_SHIFTY_EYES" = TRAIT_SHIFTY_EYES, "TRAIT_SHOCKIMMUNE" = TRAIT_SHOCKIMMUNE, + "TRAIT_SIGHT_BYPASS" = TRAIT_SIGHT_BYPASS, "TRAIT_SIGN_LANG" = TRAIT_SIGN_LANG, "TRAIT_SILENT_FOOTSTEPS" = TRAIT_SILENT_FOOTSTEPS, "TRAIT_SILICON_ACCESS" = TRAIT_SILICON_ACCESS, @@ -586,6 +590,7 @@ GLOBAL_LIST_INIT(traits_by_type, list( "TRAIT_CONTRABAND_BLOCKER" = TRAIT_CONTRABAND_BLOCKER, "TRAIT_CUSTOM_TAP_SOUND" = TRAIT_CUSTOM_TAP_SOUND, "TRAIT_DANGEROUS_OBJECT" = TRAIT_DANGEROUS_OBJECT, + "TRAIT_FIREDOOR_OPENER" = TRAIT_FIREDOOR_OPENER, "TRAIT_FISHING_BAIT" = TRAIT_FISHING_BAIT, "TRAIT_FOOD_BBQ_GRILLED" = TRAIT_FOOD_BBQ_GRILLED, "TRAIT_GERM_SENSITIVE" = TRAIT_GERM_SENSITIVE, diff --git a/code/_onclick/hud/alert.dm b/code/_onclick/hud/alert.dm index 46e9d4898c8ed..c3fb19352ab05 100644 --- a/code/_onclick/hud/alert.dm +++ b/code/_onclick/hud/alert.dm @@ -107,6 +107,8 @@ name = "Alert" desc = "Something seems to have gone wrong with this alert, so report this bug please" mouse_opacity = MOUSE_OPACITY_ICON + /// do we glow to represent we do stuff when clicked + var/clickable_glow = FALSE var/timeout = 0 //If set to a number, this alert will clear itself after that many deciseconds var/severity = 0 var/alerttooltipstyle = "" @@ -116,6 +118,10 @@ /// Boolean. If TRUE, the Click() proc will attempt to Click() on the master first if there is a master. var/click_master = TRUE +/atom/movable/screen/alert/Initialize(mapload, datum/hud/hud_owner) + . = ..() + if(clickable_glow) + add_filter("clickglow", 2, outline_filter(color = COLOR_GOLD, size = 1)) /atom/movable/screen/alert/MouseEntered(location,control,params) . = ..() @@ -237,6 +243,7 @@ name = "Mind Control" desc = "Your mind has been hijacked! Click to view the mind control command." icon_state = ALERT_MIND_CONTROL + clickable_glow = TRUE var/command /atom/movable/screen/alert/mind_control/Click() @@ -250,6 +257,7 @@ desc = "Something got lodged into your flesh and is causing major bleeding. It might fall out with time, but surgery is the safest way. \ If you're feeling frisky, examine yourself and click the underlined item to pull the object out." icon_state = ALERT_EMBEDDED_OBJECT + clickable_glow = TRUE /atom/movable/screen/alert/embeddedobject/Click() . = ..() @@ -287,6 +295,7 @@ or shoot a gun to move around via Newton's 3rd Law of Motion." name = "On Fire" desc = "You're on fire. Stop, drop and roll to put the fire out or move to a vacuum area." icon_state = "fire" + clickable_glow = TRUE /atom/movable/screen/alert/fire/Click() . = ..() @@ -305,6 +314,7 @@ or shoot a gun to move around via Newton's 3rd Law of Motion." /atom/movable/screen/alert/give // information set when the give alert is made icon_state = "default" + clickable_glow = TRUE /// The offer we're linked to, yes this is suspiciously like a status effect alert var/datum/status_effect/offering/offer /// Additional text displayed in the description of the alert. @@ -476,6 +486,7 @@ or shoot a gun to move around via Newton's 3rd Law of Motion." name = "Succumb" desc = "Shuffle off this mortal coil." icon_state = ALERT_SUCCUMB + clickable_glow = TRUE var/static/list/death_titles = list( "Goodnight, Sweet Prince", "Game Over, Man", @@ -811,6 +822,7 @@ or shoot a gun to move around via Newton's 3rd Law of Motion." additional processing time to unlock more malfunction abilities." icon_state = ALERT_HACKING_APC timeout = 60 SECONDS + clickable_glow = TRUE var/atom/target = null /atom/movable/screen/alert/hackingapc/Click() @@ -838,6 +850,7 @@ or shoot a gun to move around via Newton's 3rd Law of Motion." desc = "Someone is trying to revive you. Re-enter your corpse if you want to be revived!" icon_state = "template" timeout = 300 + clickable_glow = TRUE /atom/movable/screen/alert/revival/Click() . = ..() @@ -851,6 +864,7 @@ or shoot a gun to move around via Newton's 3rd Law of Motion." desc = "This can be clicked on to perform an action." icon_state = "template" timeout = 30 SECONDS + clickable_glow = TRUE /// Weakref to the target atom to use the action on var/datum/weakref/target_ref /// If we want to interact on click rather than jump/orbit @@ -858,6 +872,8 @@ or shoot a gun to move around via Newton's 3rd Law of Motion." /atom/movable/screen/alert/notify_action/Click() . = ..() + if(!.) + return var/atom/target = target_ref?.resolve() if(isnull(target) || !isobserver(owner) || target == owner) @@ -1026,6 +1042,10 @@ or shoot a gun to move around via Newton's 3rd Law of Motion." name = "Buckled" desc = "You've been buckled to something. Click the alert to unbuckle unless you're handcuffed." icon_state = ALERT_BUCKLED + clickable_glow = TRUE + +/atom/movable/screen/alert/restrained + clickable_glow = TRUE /atom/movable/screen/alert/restrained/handcuffed name = "Handcuffed" @@ -1073,6 +1093,7 @@ or shoot a gun to move around via Newton's 3rd Law of Motion." name = "Knotted Shoes" desc = "Someone tied your shoelaces together! Click the alert or your shoes to undo the knot." icon_state = ALERT_SHOES_KNOT + clickable_glow = TRUE /atom/movable/screen/alert/shoes/Click() . = ..() @@ -1091,6 +1112,7 @@ or shoot a gun to move around via Newton's 3rd Law of Motion." name = "Unpossess" desc = "You are possessing an object. Click this alert to unpossess it." icon_state = "buckled" + clickable_glow = TRUE /atom/movable/screen/alert/unpossess_object/Click() . = ..() diff --git a/code/_onclick/hud/blob_overmind.dm b/code/_onclick/hud/blob_overmind.dm index 8f8193a50451e..b8e9800fdf9b7 100644 --- a/code/_onclick/hud/blob_overmind.dm +++ b/code/_onclick/hud/blob_overmind.dm @@ -182,11 +182,11 @@ static_inventory += using using = new /atom/movable/screen/blob/node_blob(null, src) - using.screen_loc = ui_hand_position(2) + using.screen_loc = ui_hand_position(RIGHT_HANDS) static_inventory += using using = new /atom/movable/screen/blob/factory_blob(null, src) - using.screen_loc = ui_hand_position(1) + using.screen_loc = ui_hand_position(LEFT_HANDS) static_inventory += using using = new /atom/movable/screen/blob/readapt_strain(null, src) diff --git a/code/_onclick/hud/fullscreen.dm b/code/_onclick/hud/fullscreen.dm index 91b5c9b8e2af8..43d90893d9afc 100644 --- a/code/_onclick/hud/fullscreen.dm +++ b/code/_onclick/hud/fullscreen.dm @@ -156,9 +156,33 @@ INITIALIZE_IMMEDIATE(/atom/movable/screen/fullscreen) icon_state = "noise" /atom/movable/screen/fullscreen/high - icon = 'icons/hud/screen_gen.dmi' - screen_loc = "WEST,SOUTH to EAST,NORTH" icon_state = "druggy" + alpha = 255 + plane = LIGHTING_PLANE + layer = LIGHTING_ABOVE_ALL + 1 //Infinity plus one (not actually) + blend_mode = BLEND_MULTIPLY + +/atom/movable/screen/fullscreen/high/update_for_view(client_view) + + animate(src, flags = ANIMATION_END_NOW) //Stop all animations. + + . = ..() + + color = COLOR_MATRIX_IDENTITY //We convert it early to avoid a sudden weird jitter. + alpha = 0 + + animate(src, alpha = 255, time = 5 SECONDS) //Fade in. + + addtimer(CALLBACK(src, PROC_REF(start_hue_rotation)), 5 SECONDS) + +/atom/movable/screen/fullscreen/high/proc/start_hue_rotation() + animate(src, color = color_matrix_rotate_hue(1), loop = -1, time = 2 SECONDS) //Start the loop. + var/step_precision = 18 //Larger is more precise rotations. + for(var/current_step in 1 to step_precision - 1) //We do the -1 here because 360 == 0 when it comes to angles. + animate( + color = color_matrix_rotate_hue(current_step * 360/step_precision), + time = 2 SECONDS, + ) /atom/movable/screen/fullscreen/color_vision icon = 'icons/hud/screen_gen.dmi' diff --git a/code/_onclick/hud/guardian.dm b/code/_onclick/hud/guardian.dm index ba1d8f4565e64..32a3f233c8591 100644 --- a/code/_onclick/hud/guardian.dm +++ b/code/_onclick/hud/guardian.dm @@ -15,11 +15,11 @@ infodisplay += healths using = new /atom/movable/screen/guardian/manifest(null, src) - using.screen_loc = ui_hand_position(2) + using.screen_loc = ui_hand_position(RIGHT_HANDS) static_inventory += using using = new /atom/movable/screen/guardian/recall(null, src) - using.screen_loc = ui_hand_position(1) + using.screen_loc = ui_hand_position(LEFT_HANDS) static_inventory += using using = new owner.toggle_button_type(null, src) diff --git a/code/_onclick/hud/hud.dm b/code/_onclick/hud/hud.dm index f92bb4682e1c8..d04dafefeb088 100644 --- a/code/_onclick/hud/hud.dm +++ b/code/_onclick/hud/hud.dm @@ -151,8 +151,16 @@ GLOBAL_LIST_INIT(available_ui_styles, list( /datum/hud/proc/client_refresh(datum/source) SIGNAL_HANDLER - RegisterSignal(mymob.canon_client, COMSIG_CLIENT_SET_EYE, PROC_REF(on_eye_change)) - on_eye_change(null, null, mymob.canon_client.eye) + var/client/client = mymob.canon_client + if(client.rebuild_plane_masters) + var/new_relay_loc = (client.byond_version > 515) ? "1,1" : "CENTER" + for(var/group_key as anything in master_groups) + var/datum/plane_master_group/group = master_groups[group_key] + group.relay_loc = new_relay_loc + group.rebuild_plane_masters() + client.rebuild_plane_masters = FALSE + RegisterSignal(client, COMSIG_CLIENT_SET_EYE, PROC_REF(on_eye_change)) + on_eye_change(null, null, client.eye) /datum/hud/proc/clear_client(datum/source) SIGNAL_HANDLER @@ -497,7 +505,7 @@ GLOBAL_LIST_INIT(available_ui_styles, list( var/i = 1 for(var/atom/movable/screen/swap_hand/SH in static_inventory) - SH.screen_loc = ui_swaphand_position(mymob,!(i % 2) ? 2: 1) + SH.screen_loc = ui_swaphand_position(mymob, IS_RIGHT_INDEX(i) ? RIGHT_HANDS : LEFT_HANDS) i++ for(var/atom/movable/screen/human/equip/E in static_inventory) E.screen_loc = ui_equip_position(mymob) diff --git a/code/_onclick/hud/screen_objects.dm b/code/_onclick/hud/screen_objects.dm index efc7f1c3cfedf..ec7070237d333 100644 --- a/code/_onclick/hud/screen_objects.dm +++ b/code/_onclick/hud/screen_objects.dm @@ -241,7 +241,7 @@ . = ..() if(!handcuff_overlay) - var/state = (!(held_index % 2)) ? "markus" : "gabrielle" + var/state = IS_RIGHT_INDEX(held_index) ? "markus" : "gabrielle" handcuff_overlay = mutable_appearance('icons/hud/screen_gen.dmi', state) if(!hud?.mymob) @@ -257,7 +257,7 @@ . += blocked_overlay if(held_index == hud.mymob.active_hand_index) - . += (held_index % 2) ? "lhandactive" : "rhandactive" + . += IS_LEFT_INDEX(held_index) ? "lhandactive" : "rhandactive" /atom/movable/screen/inventory/hand/Click(location, control, params) // At this point in client Click() code we have passed the 1/10 sec check and little else diff --git a/code/controllers/configuration/entries/game_options.dm b/code/controllers/configuration/entries/game_options.dm index 655cb3fcf9a40..5e9f8f5783bcc 100644 --- a/code/controllers/configuration/entries/game_options.dm +++ b/code/controllers/configuration/entries/game_options.dm @@ -438,6 +438,10 @@ min_val = 0 integer = FALSE // It is in hours, but just in case one wants to specify minutes. +/// Will drones be restricted from interacting with the Supermatter and Atmospherics area? +/datum/config_entry/flag/drone_area_interaction_restrict + default = TRUE + /datum/config_entry/flag/native_fov /datum/config_entry/flag/disallow_title_music diff --git a/code/controllers/configuration/entries/general.dm b/code/controllers/configuration/entries/general.dm index e1ed3284441f6..3648a1b564e8c 100644 --- a/code/controllers/configuration/entries/general.dm +++ b/code/controllers/configuration/entries/general.dm @@ -762,3 +762,11 @@ default = 100 min_val = 0 max_val = 100 + +/// If admins with +DEBUG can initialize byond-tracy midround. +/datum/config_entry/flag/allow_tracy_start + protection = CONFIG_ENTRY_LOCKED + +/// If admins with +DEBUG can queue byond-tracy to run the next round. +/datum/config_entry/flag/allow_tracy_queue + protection = CONFIG_ENTRY_LOCKED diff --git a/code/controllers/subsystem/air.dm b/code/controllers/subsystem/air.dm index f19d2a99e36d3..8332d9b113393 100644 --- a/code/controllers/subsystem/air.dm +++ b/code/controllers/subsystem/air.dm @@ -222,6 +222,7 @@ SUBSYSTEM_DEF(air) cost_atoms = MC_AVERAGE(cost_atoms, TICK_DELTA_TO_MS(cached_cost)) resumed = FALSE + currentpart = SSAIR_PIPENETS SStgui.update_uis(SSair) //Lightning fast debugging motherfucker diff --git a/code/controllers/subsystem/blackbox.dm b/code/controllers/subsystem/blackbox.dm index 83c666de64ac4..e869f21c61560 100644 --- a/code/controllers/subsystem/blackbox.dm +++ b/code/controllers/subsystem/blackbox.dm @@ -88,7 +88,7 @@ SUBSYSTEM_DEF(blackbox) for(var/player_key in GLOB.player_details) var/datum/player_details/PD = GLOB.player_details[player_key] - record_feedback("tally", "client_byond_version", 1, PD.byond_version) + record_feedback("tally", "client_byond_version", 1, PD.full_byond_version()) /datum/controller/subsystem/blackbox/Shutdown() sealed = FALSE diff --git a/code/controllers/subsystem/dbcore.dm b/code/controllers/subsystem/dbcore.dm index 7d01226b2cfde..115250104f008 100644 --- a/code/controllers/subsystem/dbcore.dm +++ b/code/controllers/subsystem/dbcore.dm @@ -384,12 +384,30 @@ SUBSYSTEM_DEF(dbcore) return FALSE return new /datum/db_query(connection, sql_query, arguments) +/** + * Creates and executes a query without waiting for or tracking the results. + * Query is executed asynchronously (without blocking) and deleted afterwards - any results or errors are discarded. + * + * Arguments: + * * sql_query - The SQL query string to execute + * * arguments - List of arguments to pass to the query for parameter binding + * * allow_during_shutdown - If TRUE, allows query to be created during subsystem shutdown. Generally, only cleanup queries should set this. + */ +/datum/controller/subsystem/dbcore/proc/FireAndForget(sql_query, arguments, allow_during_shutdown = FALSE) + var/datum/db_query/query = NewQuery(sql_query, arguments, allow_during_shutdown) + if(!query) + return + ASYNC + query.Execute() + qdel(query) + /** QuerySelect Run a list of query datums in parallel, blocking until they all complete. * queries - List of queries or single query datum to run. * warn - Controls rather warn_execute() or Execute() is called. * qdel - If you don't care about the result or checking for errors, you can have the queries be deleted afterwards. - This can be combined with invoke_async as a way of running queries async without having to care about waiting for them to finish so they can be deleted. + This can be combined with invoke_async as a way of running queries async without having to care about waiting for them to finish so they can be deleted, + however you should probably just use FireAndForget instead if it's just a single query. */ /datum/controller/subsystem/dbcore/proc/QuerySelect(list/queries, warn = FALSE, qdel = FALSE) if (!islist(queries)) @@ -415,8 +433,6 @@ SUBSYSTEM_DEF(dbcore) if (qdel) qdel(query) - - /* Takes a list of rows (each row being an associated list of column => value) and inserts them via a single mass query. Rows missing columns present in other rows will resolve to SQL NULL diff --git a/code/controllers/subsystem/dynamic/dynamic.dm b/code/controllers/subsystem/dynamic/dynamic.dm index a5196f56e8afb..db9cc101b2add 100644 --- a/code/controllers/subsystem/dynamic/dynamic.dm +++ b/code/controllers/subsystem/dynamic/dynamic.dm @@ -576,7 +576,7 @@ SUBSYSTEM_DEF(dynamic) /datum/controller/subsystem/dynamic/proc/post_setup(report) for(var/datum/dynamic_ruleset/roundstart/rule in executed_rules) rule.candidates.Cut() // The rule should not use candidates at this point as they all are null. - addtimer(CALLBACK(src, TYPE_PROC_REF(/datum/controller/subsystem/dynamic/, execute_roundstart_rule), rule), rule.delay) + addtimer(CALLBACK(src, PROC_REF(execute_roundstart_rule), rule), rule.delay) if (!CONFIG_GET(flag/no_intercept_report)) addtimer(CALLBACK(src, PROC_REF(send_intercept)), rand(waittime_l, waittime_h)) diff --git a/code/controllers/subsystem/economy.dm b/code/controllers/subsystem/economy.dm index ffaf0c0744d29..3e4ff852ae0cc 100644 --- a/code/controllers/subsystem/economy.dm +++ b/code/controllers/subsystem/economy.dm @@ -30,7 +30,7 @@ SUBSYSTEM_DEF(economy) var/list/bank_accounts_by_id = list() /// A list of bank accounts indexed by their assigned job typepath. var/list/bank_accounts_by_job = list() - ///List of the departmental budget cards in existance. + ///List of the departmental budget cards in existence. var/list/dep_cards = list() /// A var that collects the total amount of credits owned in player accounts on station, reset and recounted on fire() var/station_total = 0 diff --git a/code/controllers/subsystem/ipintel.dm b/code/controllers/subsystem/ipintel.dm index db397d514742f..3ae9cfab0c564 100644 --- a/code/controllers/subsystem/ipintel.dm +++ b/code/controllers/subsystem/ipintel.dm @@ -8,7 +8,7 @@ SUBSYSTEM_DEF(ipintel) /// Cache for previously queried IP addresses and those stored in the database var/list/datum/ip_intel/cached_queries = list() /// The store for rate limiting - var/list/rate_limit_minute + var/rate_limit_minute /// The ip intel for a given address /datum/ip_intel diff --git a/code/controllers/subsystem/pathfinder.dm b/code/controllers/subsystem/pathfinder.dm index 70dc152b06df2..17ee754718e5e 100644 --- a/code/controllers/subsystem/pathfinder.dm +++ b/code/controllers/subsystem/pathfinder.dm @@ -82,7 +82,7 @@ SUBSYSTEM_DEF(pathfinder) // Otherwise we're gonna make a new one, and turn it into a path for the callbacks passed into us var/list/datum/callback/pass_in = list() - pass_in += CALLBACK(GLOBAL_PROC, /proc/path_map_passalong, on_finish, get_turf(caller), mintargetdist, skip_first) + pass_in += CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(path_map_passalong), on_finish, get_turf(caller), mintargetdist, skip_first) // And to allow subsequent calls to reuse the same map, we'll put a placeholder in the cache, and fill it up when the pathing finishes var/datum/path_map/empty = new() empty.pass_info = new(caller, access) diff --git a/code/controllers/subsystem/research.dm b/code/controllers/subsystem/research.dm index 7bb83fa133d50..9979a1a731262 100644 --- a/code/controllers/subsystem/research.dm +++ b/code/controllers/subsystem/research.dm @@ -171,7 +171,7 @@ SUBSYSTEM_DEF(research) /datum/controller/subsystem/research/proc/initialize_all_techweb_designs(clearall = FALSE) if(islist(techweb_designs) && clearall) - item_to_design = null + item_to_design = list() QDEL_LIST(techweb_designs) var/list/returned = list() for(var/path in subtypesof(/datum/design)) diff --git a/code/controllers/subsystem/spatial_gridmap.dm b/code/controllers/subsystem/spatial_gridmap.dm index 65bcb0ec365b0..d906de2dc7bcf 100644 --- a/code/controllers/subsystem/spatial_gridmap.dm +++ b/code/controllers/subsystem/spatial_gridmap.dm @@ -45,9 +45,9 @@ atmos_contents = dummy_list /datum/spatial_grid_cell/Destroy(force) - if(force)//the response to someone trying to qdel this is a right proper fuck you + if(!force)//the response to someone trying to qdel this is a right proper fuck you stack_trace("dont try to destroy spatial grid cells without a good reason. if you need to do it use force") - return + return QDEL_HINT_LETMELIVE . = ..() diff --git a/code/controllers/subsystem/statpanel.dm b/code/controllers/subsystem/statpanel.dm index cf158586ce497..9d33e977e2b7f 100644 --- a/code/controllers/subsystem/statpanel.dm +++ b/code/controllers/subsystem/statpanel.dm @@ -173,6 +173,24 @@ SUBSYSTEM_DEF(statpanels) list("Failsafe Controller:", Failsafe.stat_entry(), text_ref(Failsafe)), list("","") ) +#if defined(MC_TAB_TRACY_INFO) || defined(SPACEMAN_DMM) + var/static/tracy_dll + var/static/tracy_present + if(isnull(tracy_dll)) + tracy_dll = TRACY_DLL_PATH + tracy_present = fexists(tracy_dll) + if(tracy_present) + if(GLOB.tracy_initialized) + mc_data.Insert(2, list(list("byond-tracy:", "Active (reason: [GLOB.tracy_init_reason || "N/A"])"))) + else if(GLOB.tracy_init_error) + mc_data.Insert(2, list(list("byond-tracy:", "Errored ([GLOB.tracy_init_error])"))) + else if(fexists(TRACY_ENABLE_PATH)) + mc_data.Insert(2, list(list("byond-tracy:", "Queued for next round"))) + else + mc_data.Insert(2, list(list("byond-tracy:", "Inactive"))) + else + mc_data.Insert(2, list(list("byond-tracy:", "[tracy_dll] not present"))) +#endif for(var/datum/controller/subsystem/sub_system as anything in Master.subsystems) mc_data[++mc_data.len] = list("\[[sub_system.state_letter()]][sub_system.name]", sub_system.stat_entry(), text_ref(sub_system)) mc_data[++mc_data.len] = list("Camera Net", "Cameras: [GLOB.cameranet.cameras.len] | Chunks: [GLOB.cameranet.chunks.len]", text_ref(GLOB.cameranet)) diff --git a/code/controllers/subsystem/tgui.dm b/code/controllers/subsystem/tgui.dm index 9a566a14a70c3..548bf63cb6797 100644 --- a/code/controllers/subsystem/tgui.dm +++ b/code/controllers/subsystem/tgui.dm @@ -63,7 +63,7 @@ SUBSYSTEM_DEF(tgui) * Returns null if pool was exhausted. * * required user mob - * return datum/tgui + * return datum/tgui_window */ /datum/controller/subsystem/tgui/proc/request_pooled_window(mob/user) if(!user.client) diff --git a/code/datums/actions/items/beserk.dm b/code/datums/actions/items/beserk.dm index 43e29dbd150cd..01183fd8e3f6e 100644 --- a/code/datums/actions/items/beserk.dm +++ b/code/datums/actions/items/beserk.dm @@ -7,14 +7,27 @@ overlay_icon_state = "bg_demon_border" /datum/action/item_action/berserk_mode/Trigger(trigger_flags) - if(istype(target, /obj/item/clothing/head/hooded/berserker)) - var/obj/item/clothing/head/hooded/berserker/berserk = target - if(berserk.berserk_active) + . = ..() + if(!.) + return FALSE + var/obj/item/clothing/head/hooded/berserker/berserk = target + berserk.berserk_mode(owner) + return TRUE + +/datum/action/item_action/berserk_mode/IsAvailable(feedback = FALSE) + . = ..() + if(!.) + return FALSE + if(!istype(target, /obj/item/clothing/head/hooded/berserker)) + return FALSE + + var/obj/item/clothing/head/hooded/berserker/berserk = target + if(berserk.berserk_active) + if(feedback) to_chat(owner, span_warning("You are already berserk!")) - return - if(berserk.berserk_charge < 100) + return FALSE + if(berserk.berserk_charge < 100) + if(feedback) to_chat(owner, span_warning("You don't have a full charge.")) - return - berserk.berserk_mode(owner) - return - return ..() + return FALSE + return TRUE diff --git a/code/datums/ai/basic_mobs/basic_ai_behaviors/targeted_mob_ability.dm b/code/datums/ai/basic_mobs/basic_ai_behaviors/targeted_mob_ability.dm index c2e9fe515c40f..33cc871fddcc7 100644 --- a/code/datums/ai/basic_mobs/basic_ai_behaviors/targeted_mob_ability.dm +++ b/code/datums/ai/basic_mobs/basic_ai_behaviors/targeted_mob_ability.dm @@ -16,12 +16,6 @@ return AI_BEHAVIOR_INSTANT | AI_BEHAVIOR_SUCCEEDED return AI_BEHAVIOR_INSTANT | AI_BEHAVIOR_FAILED -/datum/ai_behavior/targeted_mob_ability/finish_action(datum/ai_controller/controller, succeeded, ability_key, target_key) - . = ..() - var/atom/target = controller.blackboard[target_key] - if (QDELETED(target)) - controller.clear_blackboard_key(target_key) - /datum/ai_behavior/targeted_mob_ability/proc/get_ability_to_use(datum/ai_controller/controller, ability_key) return controller.blackboard[ability_key] diff --git a/code/datums/ai/basic_mobs/basic_subtrees/sleep_with_no_target.dm b/code/datums/ai/basic_mobs/basic_subtrees/sleep_with_no_target.dm index 5d9841a524735..649a45d4cc7ac 100644 --- a/code/datums/ai/basic_mobs/basic_subtrees/sleep_with_no_target.dm +++ b/code/datums/ai/basic_mobs/basic_subtrees/sleep_with_no_target.dm @@ -11,23 +11,24 @@ /// Disables AI after a certain amount of time spent with no target, you will have to enable the AI again somewhere else /datum/ai_behavior/sleep_after_targetless_time - /// Turn off AI if we spend this many seconds without a target, don't use the macro because seconds_per_tick is already in seconds - var/time_to_wait = 10 + /// Turn off AI if we spend this many seconds without a target + var/time_to_wait = 10 SECONDS /datum/ai_behavior/sleep_after_targetless_time/perform(seconds_per_tick, datum/ai_controller/controller, target_key) - var/atom/target = controller.blackboard[target_key] - if(QDELETED(target)) - return AI_BEHAVIOR_INSTANT | AI_BEHAVIOR_SUCCEEDED - return AI_BEHAVIOR_INSTANT | AI_BEHAVIOR_FAILED + return (controller.blackboard_key_exists(target_key)) ? ( AI_BEHAVIOR_INSTANT | AI_BEHAVIOR_FAILED) : ( AI_BEHAVIOR_INSTANT | AI_BEHAVIOR_SUCCEEDED) -/datum/ai_behavior/sleep_after_targetless_time/finish_action(datum/ai_controller/controller, succeeded, seconds_per_tick) +/datum/ai_behavior/sleep_after_targetless_time/finish_action(datum/ai_controller/controller, succeeded, target_key) . = ..() if (!succeeded) - controller.set_blackboard_key(BB_TARGETLESS_TIME, 0) + controller.clear_blackboard_key(BB_TARGETLESS_TIME) return - controller.add_blackboard_key(BB_TARGETLESS_TIME, seconds_per_tick) - if (controller.blackboard[BB_TARGETLESS_TIME] > time_to_wait) + + if (isnull(controller.blackboard[BB_TARGETLESS_TIME])) + controller.set_blackboard_key(BB_TARGETLESS_TIME, world.time + time_to_wait) + + if (controller.blackboard[BB_TARGETLESS_TIME] < world.time) enter_sleep(controller) + controller.clear_blackboard_key(BB_TARGETLESS_TIME) /// Disables AI, override to do additional things or something else /datum/ai_behavior/sleep_after_targetless_time/proc/enter_sleep(datum/ai_controller/controller) diff --git a/code/datums/ai/idle_behaviors/idle_haunted.dm b/code/datums/ai/idle_behaviors/idle_haunted.dm index 5784b5104f6b8..756adae931341 100644 --- a/code/datums/ai/idle_behaviors/idle_haunted.dm +++ b/code/datums/ai/idle_behaviors/idle_haunted.dm @@ -10,4 +10,6 @@ return if(SPT_PROB(teleport_chance, seconds_per_tick)) playsound(item_pawn.loc, 'sound/items/haunted/ghostitemattack.ogg', 100, TRUE) + #ifndef UNIT_TESTS // hauntium teleports can cause mapping nearstation tests to fail if it teleports outside an area do_teleport(item_pawn, get_turf(item_pawn), 4, channel = TELEPORT_CHANNEL_MAGIC) + #endif diff --git a/code/datums/ai/movement/ai_movement_jps.dm b/code/datums/ai/movement/ai_movement_jps.dm index b4c4fe1a28aa8..ddae792b31c86 100644 --- a/code/datums/ai/movement/ai_movement_jps.dm +++ b/code/datums/ai/movement/ai_movement_jps.dm @@ -16,6 +16,7 @@ current_movement_target, delay, repath_delay = 0.5 SECONDS, + simulated_only = !HAS_TRAIT(controller.pawn, TRAIT_SPACEWALK), max_path_length = maximum_length, minimum_distance = controller.get_minimum_distance(), access = controller.get_access(), diff --git a/code/datums/components/basic_inhands.dm b/code/datums/components/basic_inhands.dm index ac50f618861f2..4d286e4eed3ea 100644 --- a/code/datums/components/basic_inhands.dm +++ b/code/datums/components/basic_inhands.dm @@ -39,7 +39,7 @@ SIGNAL_HANDLER var/list/held_overlays = list() for(var/obj/item/held in holding_mob.held_items) - var/is_right = holding_mob.get_held_index_of_item(held) % 2 == 0 + var/is_right = IS_RIGHT_INDEX(holding_mob.get_held_index_of_item(held)) var/icon_file = is_right ? held.righthand_file : held.lefthand_file var/mutable_appearance/held_overlay = held.build_worn_icon(default_layer = HANDS_LAYER, default_icon_file = icon_file, isinhands = TRUE) held_overlay.pixel_y += y_offset diff --git a/code/datums/components/bullet_intercepting.dm b/code/datums/components/bullet_intercepting.dm index 32e757c1823e1..f327cae954306 100644 --- a/code/datums/components/bullet_intercepting.dm +++ b/code/datums/components/bullet_intercepting.dm @@ -56,7 +56,7 @@ wearer = null /// Called when wearer is shot, check if we're going to block the hit -/datum/component/bullet_intercepting/proc/on_wearer_shot(mob/living/victim, list/signal_args, obj/projectile/bullet) +/datum/component/bullet_intercepting/proc/on_wearer_shot(mob/living/victim, obj/projectile/bullet) SIGNAL_HANDLER if (victim != wearer || victim.stat == DEAD || bullet.armor_flag != block_type) return NONE diff --git a/code/datums/components/crafting/robot.dm b/code/datums/components/crafting/robot.dm index 21abedb8b47f8..d290c39aa0fb9 100644 --- a/code/datums/components/crafting/robot.dm +++ b/code/datums/components/crafting/robot.dm @@ -42,9 +42,9 @@ time = 4 SECONDS category = CAT_ROBOT -/datum/crafting_recipe/floorbot - name = "Floorbot" - result = /mob/living/simple_animal/bot/floorbot +/datum/crafting_recipe/repairbot + name = "Repairbot" + result = /mob/living/basic/bot/repairbot reqs = list( /obj/item/storage/toolbox = 1, /obj/item/stack/tile/iron = 10, diff --git a/code/datums/components/earprotection.dm b/code/datums/components/earprotection.dm index 6439e49b831f5..6dfa7d9568baf 100644 --- a/code/datums/components/earprotection.dm +++ b/code/datums/components/earprotection.dm @@ -2,10 +2,13 @@ signals = list(COMSIG_CARBON_SOUNDBANG) mobtype = /mob/living/carbon proctype = PROC_REF(reducebang) + var/reduce_amount = 1 -/datum/component/wearertargeting/earprotection/Initialize(_valid_slots) +/datum/component/wearertargeting/earprotection/Initialize(valid_slots, reduce_amount = 1) . = ..() - valid_slots = _valid_slots + src.valid_slots = valid_slots + if(reduce_amount) + src.reduce_amount = reduce_amount /datum/component/wearertargeting/earprotection/proc/reducebang(datum/source, list/reflist) - reflist[1]-- + reflist[1] -= reduce_amount diff --git a/code/datums/components/gunpoint.dm b/code/datums/components/gunpoint.dm index edde591c0c386..3699ee75b8c34 100644 --- a/code/datums/components/gunpoint.dm +++ b/code/datums/components/gunpoint.dm @@ -194,7 +194,7 @@ return var/flinch_chance = 50 - var/gun_hand = (source.get_held_index_of_item(weapon) % 2) ? BODY_ZONE_L_ARM : BODY_ZONE_R_ARM + var/gun_hand = IS_LEFT_INDEX(source.get_held_index_of_item(weapon)) ? BODY_ZONE_L_ARM : BODY_ZONE_R_ARM if(isbodypart(def_zone)) var/obj/item/bodypart/hitting = def_zone diff --git a/code/datums/components/infective.dm b/code/datums/components/infective.dm index ecd2f1ff836fd..f168a3eba35de 100644 --- a/code/datums/components/infective.dm +++ b/code/datums/components/infective.dm @@ -13,7 +13,7 @@ return COMPONENT_INCOMPATIBLE if(!islist(diseases)) - diseases = islist(diseases) + diseases = list(diseases) ///Make sure the diseases list is populated with instances of diseases so that it doesn't have to be for each AddComponent call. for(var/datum/disease/disease as anything in diseases) @@ -115,8 +115,8 @@ return if(!is_weak) - var/appendage_zone = feeder.held_items.Find(source) - appendage_zone = appendage_zone == 0 ? BODY_ZONE_CHEST : (appendage_zone % 2 ? BODY_ZONE_R_ARM : BODY_ZONE_L_ARM) + var/appendage_zone = feeder.get_held_index_of_item(source) + appendage_zone = appendage_zone == 0 ? BODY_ZONE_CHEST : (IS_RIGHT_INDEX(appendage_zone) ? BODY_ZONE_R_ARM : BODY_ZONE_L_ARM) try_infect(feeder, appendage_zone) for(var/datum/disease/disease as anything in diseases) diff --git a/code/datums/components/item_killsound.dm b/code/datums/components/item_killsound.dm new file mode 100644 index 0000000000000..f6e5b4d9b76e9 --- /dev/null +++ b/code/datums/components/item_killsound.dm @@ -0,0 +1,41 @@ +/datum/component/item_killsound + /// list of allowed types, not null/empty + var/list/allowed_mobs + /// list of blacklisted types + var/list/blacklisted_mobs + var/killsound + var/killsound_volume = 100 + /** + * on true will act as replacement for mob's death sound, + * otherwise it will just play sound on death + */ + var/replace_default_death_sound + +/datum/component/item_killsound/Initialize( + allowed_mobs, + blacklisted_mobs, + killsound, + killsound_volume = 100, + replace_default_death_sound = FALSE +) + src.allowed_mobs = allowed_mobs + src.blacklisted_mobs = blacklisted_mobs + src.killsound = killsound + src.killsound_volume = killsound_volume + src.replace_default_death_sound = replace_default_death_sound + +/datum/component/item_killsound/RegisterWithParent() + var/obj/item/item_parent = parent + RegisterSignal(item_parent, COMSIG_ITEM_ATTACK, PROC_REF(on_attack)) + +/datum/component/item_killsound/proc/on_attack(host, target_mob, user, params) + SIGNAL_HANDLER + + if(!allowed_mobs || is_type_in_list(target_mob, allowed_mobs)) + if(is_type_in_list(target_mob, blacklisted_mobs)) + return + var/mob/living/mob = target_mob + if(replace_default_death_sound) + mob.apply_status_effect(/datum/status_effect/replace_death_sound, 1 SECONDS, killsound) + else + mob.apply_status_effect(/datum/status_effect/death_sound, 1 SECONDS, killsound, killsound_volume) diff --git a/code/datums/components/manual_breathing.dm b/code/datums/components/manual_breathing.dm index 8e5f096766a92..c8b1af483d034 100644 --- a/code/datums/components/manual_breathing.dm +++ b/code/datums/components/manual_breathing.dm @@ -71,7 +71,7 @@ /datum/component/manual_breathing/proc/check_added_organ(mob/who_cares, obj/item/organ/O) SIGNAL_HANDLER - var/obj/item/organ/eyes/new_lungs = O + var/obj/item/organ/lungs/new_lungs = O if(istype(new_lungs,/obj/item/organ/lungs)) L = new_lungs diff --git a/code/datums/components/material/remote_materials.dm b/code/datums/components/material/remote_materials.dm index 3c919ab15d4a4..65ba94e8b021b 100644 --- a/code/datums/components/material/remote_materials.dm +++ b/code/datums/components/material/remote_materials.dm @@ -44,11 +44,9 @@ handles linking back and forth. var/connect_to_silo = FALSE if(force_connect || (mapload && is_station_level(T.z))) connect_to_silo = TRUE - if(!(mat_container_flags & MATCONTAINER_NO_INSERT)) - RegisterSignal(parent, COMSIG_ATOM_ATTACKBY, TYPE_PROC_REF(/datum/component/remote_materials, SiloAttackBy)) if(mapload) // wait for silo to initialize during mapload - addtimer(CALLBACK(src, PROC_REF(_PrepareStorage), connect_to_silo)) + SSticker.OnRoundstart(CALLBACK(src, PROC_REF(_PrepareStorage), connect_to_silo)) else //directly register in round _PrepareStorage(connect_to_silo) @@ -66,17 +64,19 @@ handles linking back and forth. silo = GLOB.ore_silo_default if (silo) silo.ore_connected_machines += src - mat_container = silo.GetComponent(/datum/component/material_container) + mat_container = silo.materials + if(!(mat_container_flags & MATCONTAINER_NO_INSERT)) + RegisterSignal(parent, COMSIG_ATOM_ITEM_INTERACTION, PROC_REF(on_item_insert)) + if (!mat_container && allow_standalone) _MakeLocal() /datum/component/remote_materials/Destroy() - if (silo) - silo.ore_connected_machines -= src - silo.holds -= src - silo = null - UnregisterSignal(parent, COMSIG_ATOM_ATTACKBY) + if(silo) + allow_standalone = FALSE + disconnect_from(silo) mat_container = null + return ..() /datum/component/remote_materials/proc/_MakeLocal() @@ -93,13 +93,12 @@ handles linking back and forth. allowed_items = /obj/item/stack \ ) -/datum/component/remote_materials/proc/toggle_holding(force_hold = FALSE) +/// Adds/Removes this connection from the silo +/datum/component/remote_materials/proc/toggle_holding() if(isnull(silo)) return - if(force_hold) - silo.holds[src] = TRUE - else if(!silo.holds[src]) + if(!silo.holds[src]) silo.holds[src] = TRUE else silo.holds -= src @@ -122,28 +121,17 @@ handles linking back and forth. * old_silo- The silo we are trying to disconnect from */ /datum/component/remote_materials/proc/disconnect_from(obj/machinery/ore_silo/old_silo) - if (!old_silo || silo != old_silo) + if (QDELETED(old_silo) || silo != old_silo) return + + UnregisterSignal(parent, COMSIG_ATOM_ITEM_INTERACTION) silo.ore_connected_machines -= src silo = null mat_container = null - UnregisterSignal(parent, COMSIG_ATOM_ATTACKBY) + if (allow_standalone) _MakeLocal() -///Insert mats into silo -/datum/component/remote_materials/proc/SiloAttackBy(datum/source, obj/item/target, mob/living/user) - SIGNAL_HANDLER - - //Allows you to attack the machine with iron sheets for e.g. - if(!(mat_container_flags & MATCONTAINER_ANY_INTENT) && user.combat_mode) - return - - if(silo) - mat_container.user_insert(target, user, parent) - - return COMPONENT_NO_AFTERATTACK - /datum/component/remote_materials/proc/OnMultitool(datum/source, mob/user, obj/item/multitool/M) SIGNAL_HANDLER @@ -175,10 +163,24 @@ handles linking back and forth. silo.ore_connected_machines += src mat_container = new_container if(!(mat_container_flags & MATCONTAINER_NO_INSERT)) - RegisterSignal(parent, COMSIG_ATOM_ATTACKBY, TYPE_PROC_REF(/datum/component/remote_materials, SiloAttackBy)) + RegisterSignal(parent, COMSIG_ATOM_ITEM_INTERACTION, PROC_REF(on_item_insert)) to_chat(user, span_notice("You connect [parent] to [silo] from the multitool's buffer.")) return ITEM_INTERACT_SUCCESS +///Insert mats into silo +/datum/component/remote_materials/proc/on_item_insert(datum/source, mob/living/user, obj/item/target) + SIGNAL_HANDLER + + //Allows you to attack the machine with iron sheets for e.g. + if(!(mat_container_flags & MATCONTAINER_ANY_INTENT) && user.combat_mode) + return + + if(silo) + mat_container.user_insert(target, user, parent) + + return ITEM_INTERACT_SUCCESS + + /** * Checks if the param silo is in the same level as this components parent i.e. connected machine, rcd, etc * diff --git a/code/datums/components/mutant_hands.dm b/code/datums/components/mutant_hands.dm index f7e19e59fb5ac..66e19852ae7e4 100644 --- a/code/datums/components/mutant_hands.dm +++ b/code/datums/components/mutant_hands.dm @@ -160,11 +160,9 @@ if(!base_icon_state) return - // Even hand indexes are right hands, - // Odd hand indexes are left hand - // ...But also, we swap it intentionally here, + // We swap it intentionally here, // so right icon is shown on the left (Because hands) - if(user.get_held_index_of_item(src) % 2 == 1) + if(IS_LEFT_INDEX(user.get_held_index_of_item(src))) icon_state = "[base_icon_state]_right" else icon_state = "[base_icon_state]_left" diff --git a/code/datums/components/parry.dm b/code/datums/components/parry.dm index 98bc9e3a84d07..2486796d378bb 100644 --- a/code/datums/components/parry.dm +++ b/code/datums/components/parry.dm @@ -86,10 +86,9 @@ return parriers[user] = world.time + grace_period -/datum/component/parriable_projectile/proc/before_hit(obj/projectile/source, list/bullet_args) +/datum/component/parriable_projectile/proc/before_hit(obj/projectile/source, mob/living/user) SIGNAL_HANDLER - var/mob/user = bullet_args[2] if (!istype(user) || !parriers[user] || parried) return parriers -= user diff --git a/code/datums/components/riding/riding_mob.dm b/code/datums/components/riding/riding_mob.dm index 724495b7c88c6..f5162bf918a35 100644 --- a/code/datums/components/riding/riding_mob.dm +++ b/code/datums/components/riding/riding_mob.dm @@ -541,7 +541,7 @@ RegisterSignal(parent, COMSIG_PROJECTILE_PREHIT, PROC_REF(on_bullet_hit)) RegisterSignal(parent, COMSIG_MOB_AFTER_APPLY_DAMAGE, PROC_REF(on_attacked)) -/datum/component/riding/creature/raptor/proc/on_bullet_hit(atom/target, list/bullet_args, obj/projectile/hit_projectile) +/datum/component/riding/creature/raptor/proc/on_bullet_hit(atom/target, obj/projectile/hit_projectile) SIGNAL_HANDLER if(hit_projectile.armor_flag == ENERGY) diff --git a/code/datums/components/shell.dm b/code/datums/components/shell.dm index bb3054aea6ae6..9c74920a8628b 100644 --- a/code/datums/components/shell.dm +++ b/code/datums/components/shell.dm @@ -376,7 +376,7 @@ return COMSIG_USB_CABLE_CONNECTED_TO_CIRCUIT /** - * Determines if a user is authorized to see the existance of this shell. Returns false if they are not + * Determines if a user is authorized to see the existence of this shell. Returns false if they are not * * Arguments: * * user - The user to check if they are authorized diff --git a/code/datums/components/supermatter_crystal.dm b/code/datums/components/supermatter_crystal.dm index 4dac194c158b2..e8e6f00ed2f6d 100644 --- a/code/datums/components/supermatter_crystal.dm +++ b/code/datums/components/supermatter_crystal.dm @@ -165,10 +165,7 @@ var/obj/item/cigarette/cig = item var/clumsy = HAS_TRAIT(user, TRAIT_CLUMSY) if(clumsy) - var/which_hand = BODY_ZONE_L_ARM - if(!(user.active_hand_index % 2)) - which_hand = BODY_ZONE_R_ARM - var/obj/item/bodypart/dust_arm = user.get_bodypart(which_hand) + var/obj/item/bodypart/dust_arm = user.get_active_hand() dust_arm.dismember() user.visible_message(span_danger("The [item] flashes out of existence on contact with \the [atom_source], resonating with a horrible sound..."),\ span_danger("Oops! The [item] flashes out of existence on contact with \the [atom_source], taking your arm with it! That was clumsy of you!")) diff --git a/code/datums/components/tether.dm b/code/datums/components/tether.dm index 1e8313fa53b2b..b9eb40647acd1 100644 --- a/code/datums/components/tether.dm +++ b/code/datums/components/tether.dm @@ -72,9 +72,11 @@ to_chat(source, span_warning("[tether_name] prevents you from entering [new_loc]!")) return COMPONENT_MOVABLE_BLOCK_PRE_MOVE + // If this was called, we know its a movable + var/atom/movable/movable_source = source var/atom/movable/anchor = (source == tether_target ? parent : tether_target) if (get_dist(anchor, new_loc) > cur_dist) - if (!istype(anchor) || anchor.anchored || !anchor.Move(get_step_towards(anchor, new_loc))) + if (!istype(anchor) || anchor.anchored || !(!anchor.anchored && anchor.move_resist <= movable_source.move_force && anchor.Move(get_step_towards(anchor, new_loc)))) to_chat(source, span_warning("[tether_name] runs out of slack and prevents you from moving!")) return COMPONENT_MOVABLE_BLOCK_PRE_MOVE @@ -105,7 +107,6 @@ if (get_dist(anchor, new_loc) != cur_dist || !ismovable(source)) return - var/atom/movable/movable_source = source var/datum/drift_handler/handler = movable_source.drift_handler if (isnull(handler)) return @@ -179,12 +180,12 @@ var/atom/movable/movable_parent = parent var/atom/movable/movable_target = tether_target - if (istype(movable_parent) && movable_parent.Move(get_step(movable_parent.loc, get_dir(movable_parent, movable_target)))) + if (istype(movable_parent) && !movable_parent.anchored && movable_parent.move_resist <= movable_target.move_force && movable_parent.Move(get_step(movable_parent.loc, get_dir(movable_parent, movable_target)))) cur_dist -= 1 location.balloon_alert(user, "tether shortened") return - if (istype(movable_target) && movable_target.Move(get_step(movable_target.loc, get_dir(movable_target, movable_parent)))) + if (istype(movable_target) && !movable_target.anchored && movable_target.move_resist <= movable_parent.move_force && movable_target.Move(get_step(movable_target.loc, get_dir(movable_target, movable_parent)))) cur_dist -= 1 location.balloon_alert(user, "tether shortened") return diff --git a/code/datums/elements/cuffsnapping.dm b/code/datums/elements/cuffsnapping.dm index df445f4acc971..1abdc4a7a6bd2 100644 --- a/code/datums/elements/cuffsnapping.dm +++ b/code/datums/elements/cuffsnapping.dm @@ -42,13 +42,20 @@ src.snap_time_strong = snap_time_strong RegisterSignal(target, COMSIG_ATOM_EXAMINE, PROC_REF(on_examine)) - RegisterSignal(target, COMSIG_ITEM_ATTACK , PROC_REF(try_cuffsnap_target)) + RegisterSignal(target, COMSIG_ITEM_ATTACK_SECONDARY, PROC_REF(try_cuffsnap_target)) + RegisterSignal(target, COMSIG_ITEM_REQUESTING_CONTEXT_FOR_TARGET, PROC_REF(add_item_context)) /datum/element/cuffsnapping/Detach(datum/target) - UnregisterSignal(target, list(COMSIG_ITEM_ATTACK, COMSIG_ATOM_EXAMINE)) - + UnregisterSignal(target, list(COMSIG_ITEM_ATTACK_SECONDARY, COMSIG_ATOM_EXAMINE, COMSIG_ITEM_REQUESTING_CONTEXT_FOR_TARGET)) return ..() +/datum/element/cuffsnapping/proc/add_item_context(obj/item/source, list/context, mob/living/carbon/target, mob/living/user) + SIGNAL_HANDLER + if(!iscarbon(target) || !target.handcuffed) + return NONE + context[SCREENTIP_CONTEXT_RMB] = "Cut Restraints" + return CONTEXTUAL_SCREENTIP_SET + ///signal called on parent being examined /datum/element/cuffsnapping/proc/on_examine(datum/target, mob/user, list/examine_list) SIGNAL_HANDLER @@ -56,7 +63,7 @@ var/examine_string if(isnull(snap_time_weak)) return - examine_string = "It looks like it could cut zipties or cable restraints off someone in [snap_time_weak] seconds" + examine_string = "It looks like it could be used to cut zipties or cable restraints off someone in [snap_time_weak] seconds" if(!isnull(snap_time_strong)) examine_string += ", and handcuffs in [snap_time_strong] seconds." @@ -65,7 +72,7 @@ examine_list += span_notice(examine_string) -/datum/element/cuffsnapping/proc/try_cuffsnap_target(obj/item/cutter, mob/living/carbon/target, mob/cutter_user, params) +/datum/element/cuffsnapping/proc/try_cuffsnap_target(obj/item/cutter, mob/living/carbon/target, mob/living/cutter_user, params) SIGNAL_HANDLER if(!istype(target)) //we aren't the kind of mob that can even have cuffs, so we skip. diff --git a/code/datums/elements/ranged_armour.dm b/code/datums/elements/ranged_armour.dm index 6d1322c687b1a..de5ba61d22337 100644 --- a/code/datums/elements/ranged_armour.dm +++ b/code/datums/elements/ranged_armour.dm @@ -40,7 +40,7 @@ return ..() /// Modify or ignore bullet damage based on projectile properties -/datum/element/ranged_armour/proc/pre_bullet_impact(atom/parent, list/signal_args, obj/projectile/bullet) +/datum/element/ranged_armour/proc/pre_bullet_impact(atom/parent, obj/projectile/bullet) SIGNAL_HANDLER if (bullet.damage >= minimum_projectile_force || (bullet.damage_type in vulnerable_projectile_types)) return diff --git a/code/datums/elements/relay_attackers.dm b/code/datums/elements/relay_attackers.dm index fd87cb3bc2c8e..5b7202608ec0b 100644 --- a/code/datums/elements/relay_attackers.dm +++ b/code/datums/elements/relay_attackers.dm @@ -60,7 +60,7 @@ relay_attacker(target, attacker, ATTACKER_DAMAGING_ATTACK) /// Even if another component blocked this hit, someone still shot at us -/datum/element/relay_attackers/proc/on_bullet_act(atom/target, list/bullet_args, obj/projectile/hit_projectile) +/datum/element/relay_attackers/proc/on_bullet_act(atom/target, obj/projectile/hit_projectile) SIGNAL_HANDLER if(!hit_projectile.is_hostile_projectile()) return diff --git a/code/datums/elements/tenacious.dm b/code/datums/elements/tenacious.dm index 4d906812c13ab..35dd5774cf4be 100644 --- a/code/datums/elements/tenacious.dm +++ b/code/datums/elements/tenacious.dm @@ -18,6 +18,9 @@ /datum/element/tenacious/Detach(datum/target) UnregisterSignal(target, COMSIG_MOB_STATCHANGE) REMOVE_TRAIT(target, TRAIT_TENACIOUS, ELEMENT_TRAIT(type)) + var/mob/living/carbon/human/valid_target = target + if(valid_target.remove_movespeed_modifier(/datum/movespeed_modifier/tenacious)) + valid_target.balloon_alert(valid_target, "your tenacity wears off") return ..() ///signal called by the stat of the target changing @@ -27,6 +30,5 @@ if(new_stat == SOFT_CRIT) target.balloon_alert(target, "your tenacity kicks in") target.add_movespeed_modifier(/datum/movespeed_modifier/tenacious) - else + else if(target.remove_movespeed_modifier(/datum/movespeed_modifier/tenacious)) target.balloon_alert(target, "your tenacity wears off") - target.remove_movespeed_modifier(/datum/movespeed_modifier/tenacious) diff --git a/code/datums/mind/initialization.dm b/code/datums/mind/initialization.dm index e3b3e8225dc7a..a09cb040dbe84 100644 --- a/code/datums/mind/initialization.dm +++ b/code/datums/mind/initialization.dm @@ -11,8 +11,10 @@ mind.set_current(src) // There's nowhere else to set this up, mind code makes me depressed mind.antag_hud = add_alt_appearance(/datum/atom_hud/alternate_appearance/basic/antagonist_hud, "combo_hud", mind) + RegisterSignal(src, COMSIG_ADMIN_DELETING, PROC_REF(ghost_before_admin_delete), override = TRUE) SEND_SIGNAL(src, COMSIG_MOB_MIND_INITIALIZED, mind) + /mob/living/carbon/mind_initialize() ..() last_mind = mind @@ -35,3 +37,8 @@ . = ..() mind.set_assigned_role(SSjob.get_job_type(/datum/job/personal_ai)) mind.special_role = "" + +/// Signal proc for [COMSIG_ADMIN_DELETING], to ghostize a mob beforehand if an admin is manually deleting it. +/mob/proc/ghost_before_admin_delete(datum/source) + SIGNAL_HANDLER + ghostize(can_reenter_corpse = FALSE) diff --git a/code/datums/mutations/_combined.dm b/code/datums/mutations/_combined.dm index 0a71b4bd4ca57..58970faba5151 100644 --- a/code/datums/mutations/_combined.dm +++ b/code/datums/mutations/_combined.dm @@ -31,12 +31,12 @@ /datum/generecipe/cindikinesis input_one = /datum/mutation/human/geladikinesis - input_two = /datum/mutation/human/firebreath + input_two = /datum/mutation/human/fire // fiery sweat NOT fiery breath result = /datum/mutation/human/cindikinesis /datum/generecipe/pyrokinesis input_one = /datum/mutation/human/cryokinesis - input_two = /datum/mutation/human/firebreath + input_two = /datum/mutation/human/fire // fiery sweat NOT fiery breath result = /datum/mutation/human/pyrokinesis /datum/generecipe/thermal_adaptation diff --git a/code/datums/outfit.dm b/code/datums/outfit.dm index 5197939d709f4..a154a4f30e659 100644 --- a/code/datums/outfit.dm +++ b/code/datums/outfit.dm @@ -98,7 +98,7 @@ /** * extra types for chameleon outfit changes, mostly guns * - * Format of this list is (typepath, typepath, typepath) + * Valid values are a single typepath or list of typepaths * * These are all added and returns in the list for get_chamelon_diguise_info proc */ diff --git a/code/datums/status_effects/agent_pinpointer.dm b/code/datums/status_effects/agent_pinpointer.dm index 68b01a3eb1fa5..653b04f626175 100644 --- a/code/datums/status_effects/agent_pinpointer.dm +++ b/code/datums/status_effects/agent_pinpointer.dm @@ -22,7 +22,7 @@ ///The range until you're considered 'too far away' var/range_far = 16 ///The target we are pointing towards, refreshes every tick. - var/mob/scan_target + var/atom/movable/scan_target /datum/status_effect/agent_pinpointer/tick(seconds_between_ticks) if(!owner) @@ -40,6 +40,9 @@ var/turf/here = get_turf(owner) var/turf/there = get_turf(scan_target) + if(isnull(there)) + scan_target = null + return if(here.z != there.z) linked_alert.icon_state = "pinonnull" return diff --git a/code/datums/status_effects/buffs.dm b/code/datums/status_effects/buffs.dm index 2b6f948b6597b..a24e8d4ccdac9 100644 --- a/code/datums/status_effects/buffs.dm +++ b/code/datums/status_effects/buffs.dm @@ -306,7 +306,7 @@ newRod.activated() if(!itemUser.has_hand_for_held_index(hand)) //If user does not have the corresponding hand anymore, give them one and return the rod to their hand - var/zone = (hand % 2) ? BODY_ZONE_L_ARM : BODY_ZONE_R_ARM + var/zone = IS_LEFT_INDEX(hand) ? BODY_ZONE_L_ARM : BODY_ZONE_R_ARM if(itemUser.regenerate_limb(zone, FALSE)) itemUser.put_in_hand(newRod, hand, forced = TRUE) else diff --git a/code/datums/status_effects/death_sound.dm b/code/datums/status_effects/death_sound.dm new file mode 100644 index 0000000000000..b71c070729a5d --- /dev/null +++ b/code/datums/status_effects/death_sound.dm @@ -0,0 +1,46 @@ +/datum/status_effect/death_sound + id = "death_sound" + tick_interval = -1 + alert_type = null + status_type = STATUS_EFFECT_REPLACE + var/death_sound + var/death_sound_volume = 100 + +/datum/status_effect/death_sound/on_creation(mob/living/new_owner, duration, death_sound, death_sound_volume = 100) + src.duration = duration + src.death_sound = death_sound + src.death_sound_volume = death_sound_volume + return ..() + +/datum/status_effect/death_sound/on_apply() + RegisterSignal(owner, COMSIG_LIVING_DEATH, PROC_REF(on_death)) + return TRUE + +/datum/status_effect/death_sound/proc/on_death() + SIGNAL_HANDLER + playsound(owner, death_sound, death_sound_volume, FALSE) + +/datum/status_effect/death_sound/on_remove() + UnregisterSignal(owner, COMSIG_LIVING_DEATH) + + +/datum/status_effect/replace_death_sound + id = "replace_death_sound" + tick_interval = -1 + alert_type = null + status_type = STATUS_EFFECT_REPLACE + var/death_sound + var/old_death_sound + +/datum/status_effect/replace_death_sound/on_creation(mob/living/new_owner, duration, death_sound) + src.duration = duration + src.death_sound = death_sound + return ..() + +/datum/status_effect/replace_death_sound/on_apply() + old_death_sound = owner.death_sound + owner.death_sound = death_sound + return TRUE + +/datum/status_effect/replace_death_sound/on_remove() + owner.death_sound = old_death_sound diff --git a/code/datums/status_effects/debuffs/blindness.dm b/code/datums/status_effects/debuffs/blindness.dm index 06a5a46b9427b..edb10d27ba44b 100644 --- a/code/datums/status_effects/debuffs/blindness.dm +++ b/code/datums/status_effects/debuffs/blindness.dm @@ -11,7 +11,12 @@ // fullheal should instead remove all the sources and in turn cure this /// Static list of signals that, when received, we force an update to our nearsighted overlay - var/static/list/update_signals = list(SIGNAL_ADDTRAIT(TRAIT_NEARSIGHTED_CORRECTED), SIGNAL_REMOVETRAIT(TRAIT_NEARSIGHTED_CORRECTED)) + var/static/list/update_signals = list( + SIGNAL_ADDTRAIT(TRAIT_NEARSIGHTED_CORRECTED), + SIGNAL_REMOVETRAIT(TRAIT_NEARSIGHTED_CORRECTED), + SIGNAL_ADDTRAIT(TRAIT_SIGHT_BYPASS), + SIGNAL_REMOVETRAIT(TRAIT_SIGHT_BYPASS), + ) /// How severe is our nearsightedness right now var/overlay_severity = 2 @@ -37,7 +42,11 @@ var/mob/living/carbon/human/human_owner = owner if (human_owner.get_eye_scars()) return TRUE - return !HAS_TRAIT(owner, TRAIT_NEARSIGHTED_CORRECTED) + if(HAS_TRAIT(owner, TRAIT_NEARSIGHTED_CORRECTED)) + return FALSE + if(HAS_TRAIT(owner, TRAIT_SIGHT_BYPASS)) + return FALSE + return TRUE /// Updates our nearsightd overlay, either removing it if we have the trait or adding it if we don't /datum/status_effect/grouped/nearsighted/proc/update_nearsighted_overlay() @@ -61,6 +70,10 @@ id = "blindness" tick_interval = STATUS_EFFECT_NO_TICK alert_type = /atom/movable/screen/alert/status_effect/blind + var/static/list/update_signals = list( + SIGNAL_REMOVETRAIT(TRAIT_SIGHT_BYPASS), + SIGNAL_ADDTRAIT(TRAIT_SIGHT_BYPASS), + ) // This is not "remove on fullheal" as in practice, // fullheal should instead remove all the sources and in turn cure this @@ -68,14 +81,34 @@ if(!CAN_BE_BLIND(owner)) return FALSE + RegisterSignals(owner, update_signals, PROC_REF(update_blindness)) + + update_blindness() + + return ..() + +/datum/status_effect/grouped/blindness/proc/update_blindness() + if(!CAN_BE_BLIND(owner)) // future proofing + qdel(src) + return + + if(HAS_TRAIT(owner, TRAIT_SIGHT_BYPASS)) + make_unblind() + return + make_blind() + +/datum/status_effect/grouped/blindness/proc/make_blind() owner.overlay_fullscreen(id, /atom/movable/screen/fullscreen/blind) // You are blind - at most, able to make out shapes near you owner.add_client_colour(/datum/client_colour/monochrome/blind) - return ..() -/datum/status_effect/grouped/blindness/on_remove() +/datum/status_effect/grouped/blindness/proc/make_unblind() owner.clear_fullscreen(id) owner.remove_client_colour(/datum/client_colour/monochrome/blind) + +/datum/status_effect/grouped/blindness/on_remove() + make_unblind() + UnregisterSignal(owner, update_signals) return ..() /atom/movable/screen/alert/status_effect/blind diff --git a/code/datums/status_effects/debuffs/debuffs.dm b/code/datums/status_effects/debuffs/debuffs.dm index 3cf51d34c48d7..25c133e46d14a 100644 --- a/code/datums/status_effects/debuffs/debuffs.dm +++ b/code/datums/status_effects/debuffs/debuffs.dm @@ -874,6 +874,7 @@ name = "Ants!" desc = span_warning("JESUS FUCKING CHRIST! CLICK TO GET THOSE THINGS OFF!") icon_state = "antalert" + clickable_glow = TRUE /atom/movable/screen/alert/status_effect/ants/Click() . = ..() diff --git a/code/datums/status_effects/debuffs/drunk.dm b/code/datums/status_effects/debuffs/drunk.dm index a1ff3c7fb4eaf..706ab36fcff2c 100644 --- a/code/datums/status_effects/debuffs/drunk.dm +++ b/code/datums/status_effects/debuffs/drunk.dm @@ -106,6 +106,7 @@ . = ..() owner.sound_environment_override = SOUND_ENVIRONMENT_PSYCHOTIC owner.add_mood_event(id, /datum/mood_event/drunk) + RegisterSignal(owner, COMSIG_MOB_FIRED_GUN, PROC_REF(drunk_gun_fired)) /datum/status_effect/inebriated/drunk/on_remove() clear_effects() @@ -123,6 +124,19 @@ if(owner.sound_environment_override == SOUND_ENVIRONMENT_PSYCHOTIC) owner.sound_environment_override = SOUND_ENVIRONMENT_NONE + UnregisterSignal(owner, COMSIG_MOB_FIRED_GUN) + +/datum/status_effect/inebriated/drunk/proc/drunk_gun_fired(datum/source, obj/item/gun/gun, atom/firing_at, params, zone, bonus_spread_values) + SIGNAL_HANDLER + + // excusing the bartender, because shotgun + if(HAS_TRAIT(owner, TRAIT_DRUNKEN_BRAWLER)) + return + // what makes me a good demoman? + if(istype(gun, /obj/item/gun/grenadelauncher) || istype(gun, /obj/item/gun/ballistic/revolver/grenadelauncher)) + return + bonus_spread_values[MAX_BONUS_SPREAD_INDEX] += (drunk_value * 0.5) + /datum/status_effect/inebriated/drunk/set_drunk_value(set_to) . = ..() if(QDELETED(src)) diff --git a/code/datums/status_effects/debuffs/hallucination.dm b/code/datums/status_effects/debuffs/hallucination.dm index 3f24ab02e60ac..66e85f1900a23 100644 --- a/code/datums/status_effects/debuffs/hallucination.dm +++ b/code/datums/status_effects/debuffs/hallucination.dm @@ -14,27 +14,39 @@ /// The cooldown for when the next hallucination can occur COOLDOWN_DECLARE(hallucination_cooldown) -/datum/status_effect/hallucination/on_creation(mob/living/new_owner, duration) +/datum/status_effect/hallucination/on_creation(mob/living/new_owner, duration, lower_tick_interval, upper_tick_interval) if(isnum(duration)) src.duration = duration + if(isnum(lower_tick_interval)) + src.lower_tick_interval = lower_tick_interval + if(isnum(upper_tick_interval)) + src.upper_tick_interval = upper_tick_interval return ..() /datum/status_effect/hallucination/on_apply() if(owner.mob_biotypes & barred_biotypes) return FALSE + if(HAS_TRAIT(owner, TRAIT_HALLUCINATION_IMMUNE)) + return FALSE RegisterSignal(owner, COMSIG_LIVING_HEALTHSCAN, PROC_REF(on_health_scan)) + RegisterSignal(owner, SIGNAL_ADDTRAIT(TRAIT_HALLUCINATION_IMMUNE), PROC_REF(delete_self)) if(iscarbon(owner)) RegisterSignal(owner, COMSIG_CARBON_CHECKING_BODYPART, PROC_REF(on_check_bodypart)) RegisterSignal(owner, COMSIG_CARBON_BUMPED_AIRLOCK_OPEN, PROC_REF(on_bump_airlock)) return TRUE +/datum/status_effect/hallucination/proc/delete_self() + SIGNAL_HANDLER + qdel(src) + /datum/status_effect/hallucination/on_remove() UnregisterSignal(owner, list( COMSIG_LIVING_HEALTHSCAN, COMSIG_CARBON_CHECKING_BODYPART, COMSIG_CARBON_BUMPED_AIRLOCK_OPEN, + SIGNAL_ADDTRAIT(TRAIT_HALLUCINATION_IMMUNE), )) /// Signal proc for [COMSIG_LIVING_HEALTHSCAN]. Show we're hallucinating to (advanced) scanners. diff --git a/code/datums/status_effects/debuffs/hooked.dm b/code/datums/status_effects/debuffs/hooked.dm index d7fcb2b1821dd..8d160305b54f5 100644 --- a/code/datums/status_effects/debuffs/hooked.dm +++ b/code/datums/status_effects/debuffs/hooked.dm @@ -29,6 +29,7 @@ name = "Snagged By Hook" desc = "You're being caught like a fish by some asshat! Click to safely remove the hook or move away far enough to snap it off." icon_state = "hooked" + clickable_glow = TRUE /atom/movable/screen/alert/status_effect/hooked/Click() . = ..() diff --git a/code/datums/status_effects/debuffs/screen_blur.dm b/code/datums/status_effects/debuffs/screen_blur.dm index abdd07d3cd59b..acdce13b5a08a 100644 --- a/code/datums/status_effects/debuffs/screen_blur.dm +++ b/code/datums/status_effects/debuffs/screen_blur.dm @@ -18,7 +18,8 @@ return FALSE // Refresh the blur when a client jumps into the mob, in case we get put on a clientless mob with no hud - RegisterSignal(owner, COMSIG_MOB_LOGIN, PROC_REF(update_blur)) + RegisterSignals(owner, list(COMSIG_MOB_LOGIN, SIGNAL_ADDTRAIT(TRAIT_SIGHT_BYPASS), SIGNAL_REMOVETRAIT(TRAIT_SIGHT_BYPASS)), PROC_REF(update_blur)) + // Apply initial blur update_blur() return TRUE @@ -43,10 +44,13 @@ if(!owner.hud_used) return + var/atom/movable/plane_master_controller/game_plane_master_controller = owner.hud_used.plane_master_controllers[PLANE_MASTERS_GAME] + if(HAS_TRAIT(owner, TRAIT_SIGHT_BYPASS)) + game_plane_master_controller.remove_filter("eye_blur") + return + var/time_left_in_seconds = (duration - world.time) / (1 SECONDS) var/amount_of_blur = clamp(time_left_in_seconds * BLUR_DURATION_TO_INTENSITY, 0.6, 3) - - var/atom/movable/plane_master_controller/game_plane_master_controller = owner.hud_used.plane_master_controllers[PLANE_MASTERS_GAME] game_plane_master_controller.add_filter("eye_blur", 1, gauss_blur_filter(amount_of_blur)) #undef BLUR_DURATION_TO_INTENSITY diff --git a/code/datums/status_effects/debuffs/slime/slimed.dm b/code/datums/status_effects/debuffs/slime/slimed.dm index 2540c4df5136c..6cd107c74a9d8 100644 --- a/code/datums/status_effects/debuffs/slime/slimed.dm +++ b/code/datums/status_effects/debuffs/slime/slimed.dm @@ -7,6 +7,7 @@ name = "Covered in Slime" desc = "You are covered in slime and it's eating away at you! Click to start cleaning it off, or find a faster way to wash it away!" icon_state = "slimed" + clickable_glow = TRUE /atom/movable/screen/alert/status_effect/slimed/Click() . = ..() diff --git a/code/datums/status_effects/debuffs/strandling.dm b/code/datums/status_effects/debuffs/strandling.dm index 0ce0ad4188221..d37961c13c903 100644 --- a/code/datums/status_effects/debuffs/strandling.dm +++ b/code/datums/status_effects/debuffs/strandling.dm @@ -88,6 +88,7 @@ desc = "Strands of Durathread are wrapped around your neck, preventing you from breathing! Click this icon to remove the strand." icon_state = "his_grace" alerttooltipstyle = "hisgrace" + clickable_glow = TRUE /atom/movable/screen/alert/status_effect/strandling/Click(location, control, params) . = ..() diff --git a/code/datums/status_effects/neutral.dm b/code/datums/status_effects/neutral.dm index b2869b6a30e3a..43c4ad7a3f09a 100644 --- a/code/datums/status_effects/neutral.dm +++ b/code/datums/status_effects/neutral.dm @@ -176,6 +176,7 @@ name = "Holding Up" desc = "You're currently pointing a gun at someone. Click to cancel." icon_state = "aimed" + clickable_glow = TRUE /atom/movable/screen/alert/status_effect/holdup/Click(location, control, params) . = ..() @@ -358,6 +359,7 @@ name = "Surrender" desc = "Looks like you're in trouble now, bud. Click here to surrender. (Warning: You will be incapacitated.)" icon_state = "surrender" + clickable_glow = TRUE /atom/movable/screen/alert/status_effect/surrender/Click(location, control, params) . = ..() diff --git a/code/datums/storage/storage.dm b/code/datums/storage/storage.dm index b659eb79930ea..25703d26c8a02 100644 --- a/code/datums/storage/storage.dm +++ b/code/datums/storage/storage.dm @@ -693,10 +693,12 @@ GLOBAL_LIST_EMPTY(cached_storage_typecaches) /datum/storage/proc/on_preattack(datum/source, obj/item/thing, mob/user, params) SIGNAL_HANDLER - if(!istype(thing) || !allow_quick_gather || thing.atom_storage) + if(!istype(thing) || thing == parent.loc || !allow_quick_gather || thing.atom_storage) return if(collection_mode == COLLECT_ONE) + if(thing.loc == user) + user.dropItemToGround(thing, silent = TRUE) //this is nessassary to update any inventory slot it is attached to attempt_insert(thing, user) return COMPONENT_CANCEL_ATTACK_CHAIN diff --git a/code/datums/wires/mulebot.dm b/code/datums/wires/mulebot.dm index beb58fb1ce3b4..ec38d72898196 100644 --- a/code/datums/wires/mulebot.dm +++ b/code/datums/wires/mulebot.dm @@ -29,18 +29,24 @@ if(WIRE_MOTOR1, WIRE_MOTOR2) if(is_cut(WIRE_MOTOR1) && is_cut(WIRE_MOTOR2)) ADD_TRAIT(mule, TRAIT_IMMOBILIZED, MOTOR_LACK_TRAIT) + holder.audible_message(span_hear("The motors of [src] go silent."), null, 1) else REMOVE_TRAIT(mule, TRAIT_IMMOBILIZED, MOTOR_LACK_TRAIT) + holder.audible_message(span_hear("The motors of [src] whir to life!"), null, 1) if(is_cut(WIRE_MOTOR1)) mule.set_varspeed(FAST_MOTOR_SPEED) + holder.audible_message(span_hear("The motors of [src] speed up!"), null, 1) else if(is_cut(WIRE_MOTOR2)) mule.set_varspeed(AVERAGE_MOTOR_SPEED) + holder.audible_message(span_hear("The motors of [src] whir."), null, 1) else mule.set_varspeed(SLOW_MOTOR_SPEED) + holder.audible_message(span_hear("The motors of [src] move gently."), null, 1) if(WIRE_AVOIDANCE) if (!isnull(source)) log_combat(source, mule, "[is_cut(WIRE_AVOIDANCE) ? "cut" : "mended"] the MULE safety wire of") + holder.audible_message(span_hear("Something inside [src] clicks ominously!"), null, 1) /datum/wires/mulebot/on_pulse(wire) var/mob/living/simple_animal/bot/mulebot/mule = holder diff --git a/code/datums/wounds/bones.dm b/code/datums/wounds/bones.dm index 8209fb93facf3..6b1e16543d7ac 100644 --- a/code/datums/wounds/bones.dm +++ b/code/datums/wounds/bones.dm @@ -61,9 +61,10 @@ /datum/wound/blunt/bone/set_victim(new_victim) if (victim) - UnregisterSignal(victim, COMSIG_LIVING_UNARMED_ATTACK) + UnregisterSignal(victim, list(COMSIG_LIVING_UNARMED_ATTACK, COMSIG_MOB_FIRED_GUN)) if (new_victim) RegisterSignal(new_victim, COMSIG_LIVING_UNARMED_ATTACK, PROC_REF(attack_with_hurt_hand)) + RegisterSignal(new_victim, COMSIG_MOB_FIRED_GUN, PROC_REF(firing_with_messed_up_hand)) return ..() @@ -120,19 +121,49 @@ // With a severe or critical wound, you have a 15% or 30% chance to proc pain on hit if(prob((severity - 1) * 15)) // And you have a 70% or 50% chance to actually land the blow, respectively - if(prob(70 - 20 * (severity - 1))) - to_chat(victim, span_userdanger("The fracture in your [limb.plaintext_zone] shoots with pain as you strike [target]!")) - limb.receive_damage(brute=rand(1,5)) + if(HAS_TRAIT(victim, TRAIT_ANALGESIA) || prob(70 - 20 * (severity - 1))) + if(!HAS_TRAIT(victim, TRAIT_ANALGESIA)) + to_chat(victim, span_danger("The fracture in your [limb.plaintext_zone] shoots with pain as you strike [target]!")) + victim.apply_damage(rand(1, 5), BRUTE, limb, wound_bonus = CANT_WOUND, wound_clothing = FALSE) else victim.visible_message(span_danger("[victim] weakly strikes [target] with [victim.p_their()] broken [limb.plaintext_zone], recoiling from pain!"), \ span_userdanger("You fail to strike [target] as the fracture in your [limb.plaintext_zone] lights up in unbearable pain!"), vision_distance=COMBAT_MESSAGE_RANGE) INVOKE_ASYNC(victim, TYPE_PROC_REF(/mob, emote), "scream") victim.Stun(0.5 SECONDS) - limb.receive_damage(brute=rand(3,7)) + victim.apply_damage(rand(3, 7), BRUTE, limb, wound_bonus = CANT_WOUND, wound_clothing = FALSE) return COMPONENT_CANCEL_ATTACK_CHAIN return NONE +/// If we're a human who's firing a gun with a broken arm, we might hurt ourselves doing so +/datum/wound/blunt/bone/proc/firing_with_messed_up_hand(datum/source, obj/item/gun/gun, atom/firing_at, params, zone, bonus_spread_values) + SIGNAL_HANDLER + + switch(limb.body_zone) + if(BODY_ZONE_L_ARM) + // Heavy guns use both hands so they will always get a penalty + // (Yes, this means having two broken arms will make heavy weapons SOOO much worse) + // Otherwise make sure THIS hand is firing THIS gun + if(gun.weapon_weight <= WEAPON_MEDIUM && !IS_LEFT_INDEX(victim.get_held_index_of_item(gun))) + return + + if(BODY_ZONE_R_ARM) + // Ditto but for right arm + if(gun.weapon_weight <= WEAPON_MEDIUM && !IS_RIGHT_INDEX(victim.get_held_index_of_item(gun))) + return + + else + // This is not arm wound, so we don't care + return + + if(gun.recoil > 0 && severity >= WOUND_SEVERITY_SEVERE && prob(25 * (severity - 1))) + if(!HAS_TRAIT(victim, TRAIT_ANALGESIA)) + to_chat(victim, span_danger("The fracture in your [limb.plaintext_zone] explodes with pain as [gun] kicks back!")) + victim.apply_damage(rand(1, 3) * (severity - 1) * gun.weapon_weight, BRUTE, limb, wound_bonus = CANT_WOUND, wound_clothing = FALSE) + + if(!HAS_TRAIT(victim, TRAIT_ANALGESIA)) + bonus_spread_values[MAX_BONUS_SPREAD_INDEX] += (15 * severity * (limb.current_gauze?.splint_factor || 1)) + /datum/wound/blunt/bone/receive_damage(wounding_type, wounding_dmg, wound_bonus) if(!victim || wounding_dmg < WOUND_MINIMUM_DAMAGE) return diff --git a/code/game/data_huds.dm b/code/game/data_huds.dm index 3a43db0bbbd6a..cce2760ae609d 100644 --- a/code/game/data_huds.dm +++ b/code/game/data_huds.dm @@ -541,7 +541,7 @@ Diagnostic HUDs! switch(mode) if(BOT_SUMMON, BOT_RESPONDING) //Responding to PDA or AI summons holder.icon_state = "hudcalled" - if(BOT_CLEANING, BOT_REPAIRING, BOT_HEALING) //Cleanbot cleaning, Floorbot fixing, or Medibot Healing + if(BOT_CLEANING, BOT_HEALING) //Cleanbot cleaning, repairbot fixing, or Medibot Healing holder.icon_state = "hudworking" if(BOT_PATROL, BOT_START_PATROL) //Patrol mode holder.icon_state = "hudpatrol" diff --git a/code/game/machinery/announcement_system.dm b/code/game/machinery/announcement_system.dm index 029f4a17ea99b..eb66e140d98fb 100644 --- a/code/game/machinery/announcement_system.dm +++ b/code/game/machinery/announcement_system.dm @@ -34,7 +34,7 @@ GLOBAL_LIST_EMPTY(announcement_systems) ///If true, researched nodes will be announced to the appropriate channels var/announce_research_node = TRUE /// The text that we send when announcing researched nodes. - var/node_message = "The '%NODE' techweb node has been researched" + var/node_message = "The %NODE techweb node has been researched" /obj/machinery/announcement_system/Initialize(mapload) . = ..() @@ -164,7 +164,7 @@ GLOBAL_LIST_EMPTY(announcement_systems) newhead = new_message usr.log_message("updated the head announcement to: [new_message]", LOG_GAME) if("node_message") - var/new_message = trim(html_encode(param["new_text"]), MAX_MESSAGE_LEN) + var/new_message = trim(html_encode(param["newText"]), MAX_MESSAGE_LEN) if(new_message) node_message = new_message usr.log_message("updated the researched node announcement to: [node_message]", LOG_GAME) diff --git a/code/game/machinery/computer/buildandrepair.dm b/code/game/machinery/computer/buildandrepair.dm index 220870cb11981..3e947d33d7bff 100644 --- a/code/game/machinery/computer/buildandrepair.dm +++ b/code/game/machinery/computer/buildandrepair.dm @@ -85,14 +85,14 @@ . += span_warning("An [circuit.name] is installed and should be [EXAMINE_HINT("screwed")] in place.") . += span_notice("The circuit board can be [EXAMINE_HINT("pried")] out.") if(FRAME_COMPUTER_STATE_BOARD_SECURED) - . += span_warning("Its requires [EXAMINE_HINT("5 cable")] pieces to wire it.") + . += span_warning("It can be [EXAMINE_HINT("wired")] with some cable.") . += span_notice("The circuit board can be [EXAMINE_HINT("screwed")] loose.") if(FRAME_COMPUTER_STATE_WIRED) - . += span_notice("The wires can be cut out with [EXAMINE_HINT("wire cutters")].") - . += span_warning("Its requires [EXAMINE_HINT("2 glass")] sheets to complete the screen.") + . += span_notice("The wires can be cut with [EXAMINE_HINT("wirecutters")].") + . += span_warning("There is a slot for 2 [EXAMINE_HINT("glass panels")].") if(FRAME_COMPUTER_STATE_GLASSED) . += span_notice("The screen can be [EXAMINE_HINT("pried")] out.") - . += span_notice("The moniter can be [EXAMINE_HINT("screwed")] to complete it") + . += span_notice("The monitor can be [EXAMINE_HINT("screwed")] on to complete it") /obj/structure/frame/computer/circuit_added(obj/item/circuitboard/added) state = FRAME_COMPUTER_STATE_BOARD_INSTALLED diff --git a/code/game/machinery/computer/communications.dm b/code/game/machinery/computer/communications.dm index aac70dfc56dfa..cb61e613303ed 100644 --- a/code/game/machinery/computer/communications.dm +++ b/code/game/machinery/computer/communications.dm @@ -142,7 +142,7 @@ playsound(src, 'sound/machines/terminal/terminal_alert.ogg', 50, FALSE) return TRUE -/obj/machinery/computer/communications/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state) +/obj/machinery/computer/communications/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/ui_state) var/static/list/approved_states = list(STATE_BUYING_SHUTTLE, STATE_CHANGING_STATUS, STATE_MAIN, STATE_MESSAGES) . = ..() diff --git a/code/game/machinery/computer/orders/order_computer/mining_order.dm b/code/game/machinery/computer/orders/order_computer/mining_order.dm index 94fda727d5f79..98c1e8eed2f28 100644 --- a/code/game/machinery/computer/orders/order_computer/mining_order.dm +++ b/code/game/machinery/computer/orders/order_computer/mining_order.dm @@ -34,7 +34,7 @@ /obj/machinery/computer/order_console/mining/order_groceries(mob/living/purchaser, obj/item/card/id/card, list/groceries) var/list/things_to_order = list() for(var/datum/orderable_item/item as anything in groceries) - things_to_order[item.item_path] = groceries[item] + things_to_order[item.purchase_path] = groceries[item] var/datum/supply_pack/custom/mining_pack = new( purchaser = purchaser, \ diff --git a/code/game/machinery/computer/orders/order_computer/order_computer.dm b/code/game/machinery/computer/orders/order_computer/order_computer.dm index 9098d5aeb090b..b74601ee8a35d 100644 --- a/code/game/machinery/computer/orders/order_computer/order_computer.dm +++ b/code/game/machinery/computer/orders/order_computer/order_computer.dm @@ -50,7 +50,7 @@ GLOBAL_LIST_EMPTY(order_console_products) if(GLOB.order_console_products.len) return for(var/datum/orderable_item/path as anything in subtypesof(/datum/orderable_item)) - if(!initial(path.item_path)) + if(!initial(path.purchase_path)) continue GLOB.order_console_products += new path @@ -120,7 +120,8 @@ GLOBAL_LIST_EMPTY(order_console_products) "cat" = item.category_index, "ref" = REF(item), "cost" = round(item.cost_per_order * cargo_cost_multiplier), - "product_icon" = icon2base64(getFlatIcon(image(icon = initial(item.item_path.icon), icon_state = initial(item.item_path.icon_state)), no_anim=TRUE)) + "icon" = item.purchase_path::icon, + "icon_state" = item.purchase_path::icon_state, )) return data @@ -198,7 +199,7 @@ GLOBAL_LIST_EMPTY(order_console_products) grocery_list.Remove(item) continue for(var/amt in 1 to grocery_list[item])//every order amount - ordered_paths += item.item_path + ordered_paths += item.purchase_path podspawn(list( "target" = get_turf(living_user), "style" = /datum/pod_style/advanced, diff --git a/code/game/machinery/computer/orders/order_items/cook/order_milk_eggs.dm b/code/game/machinery/computer/orders/order_items/cook/order_milk_eggs.dm index 9e5413f854863..e53d595c4982a 100644 --- a/code/game/machinery/computer/orders/order_items/cook/order_milk_eggs.dm +++ b/code/game/machinery/computer/orders/order_items/cook/order_milk_eggs.dm @@ -3,144 +3,154 @@ /datum/orderable_item/milk_eggs/milk name = "Milk" - item_path = /obj/item/reagent_containers/condiment/milk + purchase_path = /obj/item/reagent_containers/condiment/milk cost_per_order = 30 /datum/orderable_item/milk_eggs/soymilk name = "Soy Milk" - item_path = /obj/item/reagent_containers/condiment/soymilk + purchase_path = /obj/item/reagent_containers/condiment/soymilk cost_per_order = 30 /datum/orderable_item/milk_eggs/cream name = "Cream" - item_path = /obj/item/reagent_containers/cup/glass/bottle/juice/cream + purchase_path = /obj/item/reagent_containers/cup/glass/bottle/juice/cream cost_per_order = 40 /datum/orderable_item/milk_eggs/yoghurt name = "Yoghurt" - item_path = /obj/item/reagent_containers/condiment/yoghurt + purchase_path = /obj/item/reagent_containers/condiment/yoghurt cost_per_order = 40 /datum/orderable_item/milk_eggs/eggs name = "Egg Carton" - item_path = /obj/item/storage/fancy/egg_box + purchase_path = /obj/item/storage/fancy/egg_box cost_per_order = 40 /datum/orderable_item/milk_eggs/fillet name = "Fish Fillet" - item_path = /obj/item/food/fishmeat + purchase_path = /obj/item/food/fishmeat cost_per_order = 12 /datum/orderable_item/milk_eggs/octopus name = "Octopus Tentacle" - item_path = /obj/item/food/fishmeat/octopus + purchase_path = /obj/item/food/fishmeat/octopus cost_per_order = 12 /datum/orderable_item/milk_eggs/chicken name = "Chicken Breast" - item_path = /obj/item/food/meat/slab/chicken + purchase_path = /obj/item/food/meat/slab/chicken cost_per_order = 15 /datum/orderable_item/milk_eggs/spider_eggs name = "Spider Eggs" - item_path = /obj/item/food/spidereggs + purchase_path = /obj/item/food/spidereggs /datum/orderable_item/milk_eggs/moonfish_eggs name = "Moonfish Eggs" - item_path = /obj/item/food/moonfish_eggs + purchase_path = /obj/item/food/moonfish_eggs cost_per_order = 30 /datum/orderable_item/milk_eggs/desert_snails name = "Canned Desert Snails" - item_path = /obj/item/food/canned/desert_snails + purchase_path = /obj/item/food/canned/desert_snails cost_per_order = 20 /datum/orderable_item/milk_eggs/canned_jellyfish name = "Canned Gunner Jellyfish" - item_path = /obj/item/food/canned/jellyfish + purchase_path = /obj/item/food/canned/jellyfish cost_per_order = 20 /datum/orderable_item/milk_eggs/canned_larvae name = "Canned Larvae" - item_path = /obj/item/food/canned/larvae + purchase_path = /obj/item/food/canned/larvae cost_per_order = 20 /datum/orderable_item/milk_eggs/canned_tomatoes name = "Canned San Marzano Tomatoes" - item_path = /obj/item/food/canned/tomatoes + purchase_path = /obj/item/food/canned/tomatoes cost_per_order = 30 /datum/orderable_item/milk_eggs/canned_pine_nuts name = "Canned Pine Nuts" - item_path = /obj/item/food/canned/pine_nuts + purchase_path = /obj/item/food/canned/pine_nuts cost_per_order = 20 /datum/orderable_item/milk_eggs/canned_squid_ink name = "Canned Squid Ink" - item_path = /obj/item/food/canned/squid_ink + purchase_path = /obj/item/food/canned/squid_ink cost_per_order = 20 /datum/orderable_item/milk_eggs/chap name = "Can of CHAP" - item_path = /obj/item/food/canned/chap + purchase_path = /obj/item/food/canned/chap cost_per_order = 20 /datum/orderable_item/milk_eggs/ready_donk name = "Ready-Donk Meal: Bachelor Chow" - item_path = /obj/item/food/ready_donk + purchase_path = /obj/item/food/ready_donk cost_per_order = 40 /datum/orderable_item/milk_eggs/ready_donk_mac name = "Ready-Donk Meal: Donk-a-Roni" - item_path = /obj/item/food/ready_donk/mac_n_cheese + purchase_path = /obj/item/food/ready_donk/mac_n_cheese cost_per_order = 40 /datum/orderable_item/milk_eggs/ready_donk_mex name = "Ready-Donk Meal: Donkhiladas" - item_path = /obj/item/food/ready_donk/donkhiladas + purchase_path = /obj/item/food/ready_donk/donkhiladas cost_per_order = 40 /datum/orderable_item/milk_eggs/ready_donk_nachos name = "Ready-Donk Meal: Donk Sol Series Boritos Nachos Grandes" - item_path = /obj/item/food/ready_donk/nachos_grandes + purchase_path = /obj/item/food/ready_donk/nachos_grandes cost_per_order = 40 /datum/orderable_item/milk_eggs/ready_donk_orange name = "Ready-Donk Meal: Donk-range Chicken" - item_path = /obj/item/food/ready_donk/donkrange_chicken + purchase_path = /obj/item/food/ready_donk/donkrange_chicken + cost_per_order = 40 + +/datum/orderable_item/milk_eggs/ready_donk_salisbury + name = "Ready-Donk Meal: Donkriginals Salisbury Steak" + purchase_path = /obj/item/food/ready_donk/salisbury_steak + cost_per_order = 40 + +/datum/orderable_item/milk_eggs/ready_donk_chicken + name = "Ready-Donk Meal: Donkriginals Country-Fried Chicken" + purchase_path = /obj/item/food/ready_donk/country_chicken cost_per_order = 40 /datum/orderable_item/milk_eggs/tiziran_goods name = "Tiziran Farm-Fresh Pack" - item_path = /obj/item/storage/box/tiziran_goods + purchase_path = /obj/item/storage/box/tiziran_goods cost_per_order = 120 /datum/orderable_item/milk_eggs/tiziran_cans name = "Tiziran Canned Goods Pack" - item_path = /obj/item/storage/box/tiziran_cans + purchase_path = /obj/item/storage/box/tiziran_cans cost_per_order = 120 /datum/orderable_item/milk_eggs/tiziran_meats name = "Tiziran Meatmarket Pack" - item_path = /obj/item/storage/box/tiziran_meats + purchase_path = /obj/item/storage/box/tiziran_meats cost_per_order = 120 /datum/orderable_item/milk_eggs/mothic_goods name = "Mothic Farm-Fresh Pack" - item_path = /obj/item/storage/box/mothic_goods + purchase_path = /obj/item/storage/box/mothic_goods cost_per_order = 120 /datum/orderable_item/milk_eggs/mothic_cans_sauces name = "Mothic Pantry Pack" - item_path = /obj/item/storage/box/mothic_cans_sauces + purchase_path = /obj/item/storage/box/mothic_cans_sauces cost_per_order = 120 /datum/orderable_item/milk_eggs/armorfish name = "Cleaned Armorfish" - item_path = /obj/item/food/fishmeat/armorfish + purchase_path = /obj/item/food/fishmeat/armorfish cost_per_order = 30 /datum/orderable_item/milk_eggs/moonfish name = "Moonfish" - item_path = /obj/item/food/fishmeat/moonfish + purchase_path = /obj/item/food/fishmeat/moonfish cost_per_order = 30 diff --git a/code/game/machinery/computer/orders/order_items/cook/order_reagents.dm b/code/game/machinery/computer/orders/order_items/cook/order_reagents.dm index 39fb38df550ef..06bd251368a90 100644 --- a/code/game/machinery/computer/orders/order_items/cook/order_reagents.dm +++ b/code/game/machinery/computer/orders/order_items/cook/order_reagents.dm @@ -3,105 +3,105 @@ /datum/orderable_item/reagents/flour name = "Flour Sack" - item_path = /obj/item/reagent_containers/condiment/flour + purchase_path = /obj/item/reagent_containers/condiment/flour cost_per_order = 30 /datum/orderable_item/reagents/sugar name = "Sugar Sack" - item_path = /obj/item/reagent_containers/condiment/sugar + purchase_path = /obj/item/reagent_containers/condiment/sugar cost_per_order = 30 /datum/orderable_item/reagents/rice name = "Rice Sack" - item_path = /obj/item/reagent_containers/condiment/rice + purchase_path = /obj/item/reagent_containers/condiment/rice cost_per_order = 30 /datum/orderable_item/reagents/cornmeal name = "Cornmeal Box" - item_path = /obj/item/reagent_containers/condiment/cornmeal + purchase_path = /obj/item/reagent_containers/condiment/cornmeal cost_per_order = 30 /datum/orderable_item/reagents/enzyme name = "Universal Enzyme" - item_path = /obj/item/reagent_containers/condiment/enzyme + purchase_path = /obj/item/reagent_containers/condiment/enzyme cost_per_order = 40 /datum/orderable_item/reagents/salt name = "Salt Shaker" - item_path = /obj/item/reagent_containers/condiment/saltshaker + purchase_path = /obj/item/reagent_containers/condiment/saltshaker cost_per_order = 15 /datum/orderable_item/reagents/pepper name = "Pepper Mill" - item_path = /obj/item/reagent_containers/condiment/peppermill + purchase_path = /obj/item/reagent_containers/condiment/peppermill cost_per_order = 15 /datum/orderable_item/reagents/soysauce name = "Soy Sauce" - item_path = /obj/item/reagent_containers/condiment/soysauce + purchase_path = /obj/item/reagent_containers/condiment/soysauce cost_per_order = 15 /datum/orderable_item/reagents/bbqsauce name = "BBQ Sauce" - item_path = /obj/item/reagent_containers/condiment/bbqsauce + purchase_path = /obj/item/reagent_containers/condiment/bbqsauce cost_per_order = 60 /datum/orderable_item/reagents/vinegar name = "Vinegar" - item_path = /obj/item/reagent_containers/condiment/vinegar + purchase_path = /obj/item/reagent_containers/condiment/vinegar cost_per_order = 30 /datum/orderable_item/reagents/olive_oil name = "Olive Oil" - item_path = /obj/item/reagent_containers/condiment/olive_oil + purchase_path = /obj/item/reagent_containers/condiment/olive_oil cost_per_order = 50 //Extra Virgin, just like you, the reader /datum/orderable_item/reagents/peanut_butter name = "Peanut Butter" - item_path = /obj/item/reagent_containers/condiment/peanut_butter + purchase_path = /obj/item/reagent_containers/condiment/peanut_butter cost_per_order = 30 /datum/orderable_item/reagents/cherryjelly name = "Cherry Jelly" - item_path = /obj/item/reagent_containers/condiment/cherryjelly + purchase_path = /obj/item/reagent_containers/condiment/cherryjelly cost_per_order = 30 /datum/orderable_item/reagents/worcestershire name = "Worcestershire Sauce" - item_path = /obj/item/reagent_containers/condiment/worcestershire + purchase_path = /obj/item/reagent_containers/condiment/worcestershire cost_per_order = 30 /datum/orderable_item/reagents/red_bay name = "Red Bay Seasoning" - item_path = /obj/item/reagent_containers/condiment/red_bay + purchase_path = /obj/item/reagent_containers/condiment/red_bay cost_per_order = 30 /datum/orderable_item/reagents/curry_powder name = "Curry Powder" - item_path = /obj/item/reagent_containers/condiment/curry_powder + purchase_path = /obj/item/reagent_containers/condiment/curry_powder cost_per_order = 30 /datum/orderable_item/reagents/dashi_concentrate name = "Dashi Concentrate" - item_path = /obj/item/reagent_containers/condiment/dashi_concentrate + purchase_path = /obj/item/reagent_containers/condiment/dashi_concentrate cost_per_order = 30 /datum/orderable_item/reagents/coconut_milk name = "Coconut Milk" - item_path = /obj/item/reagent_containers/condiment/coconut_milk + purchase_path = /obj/item/reagent_containers/condiment/coconut_milk cost_per_order = 30 /datum/orderable_item/reagents/grounding_solution name = "Grounding Solution" - item_path = /obj/item/reagent_containers/condiment/grounding_solution + purchase_path = /obj/item/reagent_containers/condiment/grounding_solution cost_per_order = 30 /datum/orderable_item/reagents/honey name = "Honey" - item_path = /obj/item/reagent_containers/condiment/honey + purchase_path = /obj/item/reagent_containers/condiment/honey cost_per_order = 125 //its high quality honey :) /datum/orderable_item/reagents/mayonnaise name = "Mayonnaise" - item_path = /obj/item/reagent_containers/condiment/mayonnaise + purchase_path = /obj/item/reagent_containers/condiment/mayonnaise cost_per_order = 30 diff --git a/code/game/machinery/computer/orders/order_items/cook/order_veggies.dm b/code/game/machinery/computer/orders/order_items/cook/order_veggies.dm index f96562724d27d..5eff7055b9fae 100644 --- a/code/game/machinery/computer/orders/order_items/cook/order_veggies.dm +++ b/code/game/machinery/computer/orders/order_items/cook/order_veggies.dm @@ -3,177 +3,177 @@ /datum/orderable_item/veggies/potato name = "Potato" - item_path = /obj/item/food/grown/potato + purchase_path = /obj/item/food/grown/potato /datum/orderable_item/veggies/tomato name = "Tomato" - item_path = /obj/item/food/grown/tomato + purchase_path = /obj/item/food/grown/tomato /datum/orderable_item/veggies/carrot name = "Carrot" - item_path = /obj/item/food/grown/carrot + purchase_path = /obj/item/food/grown/carrot /datum/orderable_item/veggies/eggplant name = "Eggplant" - item_path = /obj/item/food/grown/eggplant + purchase_path = /obj/item/food/grown/eggplant /datum/orderable_item/veggies/mushroom name = "Plump Helmet" desc = "Plumus Hellmus: Plump, soft and s-so inviting~" - item_path = /obj/item/food/grown/mushroom/plumphelmet + purchase_path = /obj/item/food/grown/mushroom/plumphelmet /datum/orderable_item/veggies/cabbage name = "Cabbage" - item_path = /obj/item/food/grown/cabbage + purchase_path = /obj/item/food/grown/cabbage /datum/orderable_item/veggies/onion name = "Onion" - item_path = /obj/item/food/grown/onion + purchase_path = /obj/item/food/grown/onion /datum/orderable_item/veggies/apple name = "Apple" - item_path = /obj/item/food/grown/apple + purchase_path = /obj/item/food/grown/apple /datum/orderable_item/veggies/pumpkin name = "Pumpkin" - item_path = /obj/item/food/grown/pumpkin + purchase_path = /obj/item/food/grown/pumpkin /datum/orderable_item/veggies/watermelon name = "Watermelon" - item_path = /obj/item/food/grown/watermelon + purchase_path = /obj/item/food/grown/watermelon /datum/orderable_item/veggies/corn name = "Corn" - item_path = /obj/item/food/grown/corn + purchase_path = /obj/item/food/grown/corn /datum/orderable_item/veggies/soybean name = "Soybeans" - item_path = /obj/item/food/grown/soybeans + purchase_path = /obj/item/food/grown/soybeans /datum/orderable_item/veggies/garlic name = "Garlic" - item_path = /obj/item/food/grown/garlic + purchase_path = /obj/item/food/grown/garlic /datum/orderable_item/veggies/cherries name = "Cherries" - item_path = /obj/item/food/grown/cherries + purchase_path = /obj/item/food/grown/cherries /datum/orderable_item/veggies/chanterelle name = "Chanterelle" - item_path = /obj/item/food/grown/mushroom/chanterelle + purchase_path = /obj/item/food/grown/mushroom/chanterelle /datum/orderable_item/veggies/cocoa name = "Cocoa" - item_path = /obj/item/food/grown/cocoapod + purchase_path = /obj/item/food/grown/cocoapod /datum/orderable_item/veggies/herbs name = "Bundle of Herbs" - item_path = /obj/item/food/grown/herbs + purchase_path = /obj/item/food/grown/herbs cost_per_order = 5 /datum/orderable_item/veggies/bell_pepper name = "Bell Pepper" - item_path = /obj/item/food/grown/bell_pepper + purchase_path = /obj/item/food/grown/bell_pepper /datum/orderable_item/veggies/cucumbers name = "Cucumber" - item_path = /obj/item/food/grown/cucumber + purchase_path = /obj/item/food/grown/cucumber cost_per_order = 10 /datum/orderable_item/veggies/pickles name = "Jar of pickles" - item_path = /obj/item/storage/fancy/pickles_jar + purchase_path = /obj/item/storage/fancy/pickles_jar cost_per_order = 60 /datum/orderable_item/veggies/pickled_voltvine name = "Pickled Voltvine" - item_path = /obj/item/food/pickled_voltvine + purchase_path = /obj/item/food/pickled_voltvine cost_per_order = 5 /datum/orderable_item/veggies/chili name = "Chili" - item_path = /obj/item/food/grown/chili + purchase_path = /obj/item/food/grown/chili /datum/orderable_item/veggies/berries name = "Berries" - item_path = /obj/item/food/grown/berries + purchase_path = /obj/item/food/grown/berries /datum/orderable_item/veggies/pineapple name = "Pineapple" - item_path = /obj/item/food/grown/pineapple + purchase_path = /obj/item/food/grown/pineapple /datum/orderable_item/veggies/peas name = "Peas" - item_path = /obj/item/food/grown/peas + purchase_path = /obj/item/food/grown/peas /datum/orderable_item/veggies/korta_nut //nanotrasen does not devote as much of their resources to pathetic lizard crops name = "Korta Nut" - item_path = /obj/item/food/grown/korta_nut + purchase_path = /obj/item/food/grown/korta_nut cost_per_order = 15 /datum/orderable_item/veggies/parsnip name = "Parsnip" - item_path = /obj/item/food/grown/parsnip + purchase_path = /obj/item/food/grown/parsnip /datum/orderable_item/veggies/redbeet name = "Red Beet" - item_path = /obj/item/food/grown/redbeet + purchase_path = /obj/item/food/grown/redbeet /datum/orderable_item/veggies/orange name = "Orange" - item_path = /obj/item/food/grown/citrus/orange + purchase_path = /obj/item/food/grown/citrus/orange /datum/orderable_item/veggies/vanillapod name = "Vanilla" - item_path = /obj/item/food/grown/vanillapod + purchase_path = /obj/item/food/grown/vanillapod cost_per_order = 25 //food items that are treated as mutations in game should be more expensive. groceries shouldnt include ACTUAL mutations but i think real foods are ok /datum/orderable_item/veggies/sweetkorta name = "Sweet Korta Nut" - item_path = /obj/item/food/grown/korta_nut/sweet + purchase_path = /obj/item/food/grown/korta_nut/sweet cost_per_order = 30 /datum/orderable_item/veggies/redonion name = "Red Onion" - item_path = /obj/item/food/grown/onion/red + purchase_path = /obj/item/food/grown/onion/red cost_per_order = 25 /datum/orderable_item/veggies/peanut name = "Peanut" - item_path = /obj/item/food/grown/peanut + purchase_path = /obj/item/food/grown/peanut /datum/orderable_item/veggies/sweetpotato name = "Sweet Potato" - item_path = /obj/item/food/grown/potato/sweet + purchase_path = /obj/item/food/grown/potato/sweet cost_per_order = 25 /datum/orderable_item/veggies/oat name = "Oat" - item_path = /obj/item/food/grown/oat + purchase_path = /obj/item/food/grown/oat /datum/orderable_item/veggies/trumpet name = "Spaceman's Trumpet" - item_path = /obj/item/food/grown/trumpet + purchase_path = /obj/item/food/grown/trumpet cost_per_order = 25 /datum/orderable_item/veggies/banana name = "Banana" - item_path = /obj/item/food/grown/banana + purchase_path = /obj/item/food/grown/banana /datum/orderable_item/veggies/ghostchili name = "Ghost Chili" - item_path = /obj/item/food/grown/ghost_chili + purchase_path = /obj/item/food/grown/ghost_chili cost_per_order = 25 /datum/orderable_item/veggies/lemon name = "Lemon" - item_path = /obj/item/food/grown/citrus/lemon + purchase_path = /obj/item/food/grown/citrus/lemon /datum/orderable_item/veggies/lime name = "Lime" - item_path = /obj/item/food/grown/citrus/lime + purchase_path = /obj/item/food/grown/citrus/lime /datum/orderable_item/veggies/toechtauese name = "Töchtaüse berries" - item_path = /obj/item/food/grown/toechtauese + purchase_path = /obj/item/food/grown/toechtauese cost_per_order = 15 diff --git a/code/game/machinery/computer/orders/order_items/mining/order_consumables.dm b/code/game/machinery/computer/orders/order_items/mining/order_consumables.dm index a91a34b46f2da..79e82ac954b22 100644 --- a/code/game/machinery/computer/orders/order_items/mining/order_consumables.dm +++ b/code/game/machinery/computer/orders/order_items/mining/order_consumables.dm @@ -2,53 +2,53 @@ category_index = CATEGORY_CONSUMABLES /datum/orderable_item/consumables/survival_pen - item_path = /obj/item/reagent_containers/hypospray/medipen/survival + purchase_path = /obj/item/reagent_containers/hypospray/medipen/survival cost_per_order = 250 /datum/orderable_item/consumables/luxury_pen - item_path = /obj/item/reagent_containers/hypospray/medipen/survival/luxury + purchase_path = /obj/item/reagent_containers/hypospray/medipen/survival/luxury cost_per_order = 750 /datum/orderable_item/consumables/medkit - item_path = /obj/item/storage/medkit/brute + purchase_path = /obj/item/storage/medkit/brute cost_per_order = 400 /datum/orderable_item/consumables/medkit_fire - item_path = /obj/item/storage/medkit/fire + purchase_path = /obj/item/storage/medkit/fire desc = "For emergency magmatic burn relief." cost_per_order = 500 /datum/orderable_item/consumables/whiskey - item_path = /obj/item/reagent_containers/cup/glass/bottle/whiskey + purchase_path = /obj/item/reagent_containers/cup/glass/bottle/whiskey cost_per_order = 100 /datum/orderable_item/consumables/absinthe - item_path = /obj/item/reagent_containers/cup/glass/bottle/absinthe/premium + purchase_path = /obj/item/reagent_containers/cup/glass/bottle/absinthe/premium cost_per_order = 100 /datum/orderable_item/consumables/bubblegum - item_path = /obj/item/storage/box/gum/bubblegum + purchase_path = /obj/item/storage/box/gum/bubblegum cost_per_order = 100 /datum/orderable_item/consumables/havana_cigars - item_path = /obj/item/cigarette/cigar/havana + purchase_path = /obj/item/cigarette/cigar/havana cost_per_order = 150 /datum/orderable_item/consumables/havana_cigars - item_path = /obj/item/cigarette/cigar/havana + purchase_path = /obj/item/cigarette/cigar/havana cost_per_order = 150 /datum/orderable_item/consumables/tracking_implants - item_path = /obj/item/storage/box/minertracker + purchase_path = /obj/item/storage/box/minertracker cost_per_order = 600 /datum/orderable_item/consumables/space_cash - item_path = /obj/item/stack/spacecash/c1000 + purchase_path = /obj/item/stack/spacecash/c1000 desc = "A stack of space cash worth 1000 credits." cost_per_order = 2000 /datum/orderable_item/consumables/rescue_hook name = "Rescue Fishing Rod" - item_path = /obj/item/fishing_rod/rescue + purchase_path = /obj/item/fishing_rod/rescue desc = "For when your fellow miner has inevitably fallen into a chasm, and it's up to you to save them." cost_per_order = 600 diff --git a/code/game/machinery/computer/orders/order_items/mining/order_golem.dm b/code/game/machinery/computer/orders/order_items/mining/order_golem.dm index cbd037230f242..237360978e8d4 100644 --- a/code/game/machinery/computer/orders/order_items/mining/order_golem.dm +++ b/code/game/machinery/computer/orders/order_items/mining/order_golem.dm @@ -2,34 +2,34 @@ category_index = CATEGORY_GOLEM /datum/orderable_item/golem/mining_id - item_path = /obj/item/card/id/advanced/mining + purchase_path = /obj/item/card/id/advanced/mining cost_per_order = 200 /datum/orderable_item/golem/science_goggles - item_path = /obj/item/clothing/glasses/science + purchase_path = /obj/item/clothing/glasses/science cost_per_order = 200 /datum/orderable_item/golem/monkeycubes - item_path = /obj/item/food/monkeycube + purchase_path = /obj/item/food/monkeycube cost_per_order = 250 /datum/orderable_item/golem/belt - item_path = /obj/item/storage/belt/utility + purchase_path = /obj/item/storage/belt/utility cost_per_order = 300 /datum/orderable_item/golem/royal_cape - item_path = /obj/item/bedsheet/rd/royal_cape + purchase_path = /obj/item/bedsheet/rd/royal_cape cost_per_order = 400 /datum/orderable_item/golem/grey_extract - item_path = /obj/item/slime_extract/grey + purchase_path = /obj/item/slime_extract/grey cost_per_order = 800 /datum/orderable_item/golem/trigger_guard - item_path = /obj/item/borg/upgrade/modkit/trigger_guard + purchase_path = /obj/item/borg/upgrade/modkit/trigger_guard cost_per_order = 750 /datum/orderable_item/golem/rnd_boards - item_path = /obj/item/storage/box/rndboards + purchase_path = /obj/item/storage/box/rndboards cost_per_order = 1000 diff --git a/code/game/machinery/computer/orders/order_items/mining/order_mining.dm b/code/game/machinery/computer/orders/order_items/mining/order_mining.dm index 76af0dc806c96..babbd4a47381e 100644 --- a/code/game/machinery/computer/orders/order_items/mining/order_mining.dm +++ b/code/game/machinery/computer/orders/order_items/mining/order_mining.dm @@ -2,132 +2,132 @@ category_index = CATEGORY_MINING /datum/orderable_item/mining/marker_beacon - item_path = /obj/item/stack/marker_beacon/ten + purchase_path = /obj/item/stack/marker_beacon/ten cost_per_order = 80 /datum/orderable_item/mining/skeleton_key - item_path = /obj/item/skeleton_key + purchase_path = /obj/item/skeleton_key cost_per_order = 675 /datum/orderable_item/mining/mining_stabilizer - item_path = /obj/item/mining_stabilizer + purchase_path = /obj/item/mining_stabilizer cost_per_order = 320 /datum/orderable_item/mining/fulton_core - item_path = /obj/item/fulton_core + purchase_path = /obj/item/fulton_core cost_per_order = 320 /datum/orderable_item/mining/mining_modsuit - item_path = /obj/item/mod/control/pre_equipped/mining + purchase_path = /obj/item/mod/control/pre_equipped/mining desc = "A mining-themed MODsuit that works best when in a mining environment." cost_per_order = 2500 /datum/orderable_item/mining/mining_belt - item_path = /obj/item/storage/belt/mining + purchase_path = /obj/item/storage/belt/mining cost_per_order = 450 /datum/orderable_item/mining/jaunter - item_path = /obj/item/wormhole_jaunter + purchase_path = /obj/item/wormhole_jaunter cost_per_order = 650 /datum/orderable_item/mining/crusher - item_path = /obj/item/kinetic_crusher + purchase_path = /obj/item/kinetic_crusher cost_per_order = 650 /datum/orderable_item/mining/crusher_retool_kit - item_path = /obj/item/crusher_trophy/retool_kit + purchase_path = /obj/item/crusher_trophy/retool_kit cost_per_order = 150 /datum/orderable_item/mining/crusher_retool_kit_harpoon - item_path = /obj/item/crusher_trophy/retool_kit/harpoon + purchase_path = /obj/item/crusher_trophy/retool_kit/harpoon cost_per_order = 150 /datum/orderable_item/mining/crusher_retool_kit_dagger - item_path = /obj/item/crusher_trophy/retool_kit/dagger + purchase_path = /obj/item/crusher_trophy/retool_kit/dagger cost_per_order = 150 /datum/orderable_item/mining/resonator - item_path = /obj/item/resonator + purchase_path = /obj/item/resonator cost_per_order = 710 /datum/orderable_item/mining/resonator_advanced - item_path = /obj/item/resonator/upgraded + purchase_path = /obj/item/resonator/upgraded cost_per_order = 2000 /datum/orderable_item/mining/mining_scanner - item_path = /obj/item/t_scanner/adv_mining_scanner + purchase_path = /obj/item/t_scanner/adv_mining_scanner cost_per_order = 675 /datum/orderable_item/mining/fulton - item_path = /obj/item/extraction_pack + purchase_path = /obj/item/extraction_pack cost_per_order = 800 /datum/orderable_item/mining/lazarus - item_path = /obj/item/lazarus_injector + purchase_path = /obj/item/lazarus_injector cost_per_order = 1000 /datum/orderable_item/mining/gar_mesons - item_path = /obj/item/clothing/glasses/meson/gar + purchase_path = /obj/item/clothing/glasses/meson/gar cost_per_order = 500 /datum/orderable_item/mining/silver_pickaxe - item_path = /obj/item/pickaxe/silver + purchase_path = /obj/item/pickaxe/silver cost_per_order = 1000 /datum/orderable_item/mining/diamond_pickaxe - item_path = /obj/item/pickaxe/diamond + purchase_path = /obj/item/pickaxe/diamond cost_per_order = 2000 /datum/orderable_item/mining/conscription_kit - item_path = /obj/item/storage/backpack/duffelbag/mining_conscript + purchase_path = /obj/item/storage/backpack/duffelbag/mining_conscript desc = "A kit containing everything a crewmember needs to support a shaft miner in the field." cost_per_order = 1200 /datum/orderable_item/mining/capsule - item_path = /obj/item/survivalcapsule + purchase_path = /obj/item/survivalcapsule cost_per_order = 350 /datum/orderable_item/mining/capsule/bathroom - item_path = /obj/item/survivalcapsule/bathroom + purchase_path = /obj/item/survivalcapsule/bathroom cost_per_order = 300 /datum/orderable_item/mining/capsule_luxury - item_path = /obj/item/survivalcapsule/luxury + purchase_path = /obj/item/survivalcapsule/luxury cost_per_order = 2300 /datum/orderable_item/mining/capsule_luxuryelite - item_path = /obj/item/survivalcapsule/luxuryelite + purchase_path = /obj/item/survivalcapsule/luxuryelite cost_per_order = 7000 /datum/orderable_item/mining/kheiralcuffs - item_path = /obj/item/kheiral_cuffs + purchase_path = /obj/item/kheiral_cuffs cost_per_order = 675 /datum/orderable_item/mining/bhop - item_path = /obj/item/clothing/shoes/bhop + purchase_path = /obj/item/clothing/shoes/bhop cost_per_order = 2000 /datum/orderable_item/mining/hiking_boots - item_path = /obj/item/clothing/shoes/winterboots/ice_boots + purchase_path = /obj/item/clothing/shoes/winterboots/ice_boots cost_per_order = 2000 /datum/orderable_item/mining/style_meter - item_path = /obj/item/style_meter + purchase_path = /obj/item/style_meter cost_per_order = 1200 /datum/orderable_item/mining/weather_radio - item_path = /obj/item/radio/weather_monitor + purchase_path = /obj/item/radio/weather_monitor cost_per_order = 320 /datum/orderable_item/mining/ventpointer - item_path = /obj/item/pinpointer/vent + purchase_path = /obj/item/pinpointer/vent cost_per_order = 1150 /datum/orderable_item/mining/boulder_processing - item_path = /obj/item/boulder_beacon + purchase_path = /obj/item/boulder_beacon desc = "A Bouldertech brand all-in-one boulder processing beacon. Each use will teleport in a component of a full boulder processing assembly line. Good for when you need to process additional boulders." cost_per_order = 875 /datum/orderable_item/mining/grapple_gun - item_path = /obj/item/grapple_gun + purchase_path = /obj/item/grapple_gun cost_per_order = 3000 diff --git a/code/game/machinery/computer/orders/order_items/mining/order_pka.dm b/code/game/machinery/computer/orders/order_items/mining/order_pka.dm index f239e9f2a7eaf..ceaa83d8ef734 100644 --- a/code/game/machinery/computer/orders/order_items/mining/order_pka.dm +++ b/code/game/machinery/computer/orders/order_items/mining/order_pka.dm @@ -2,45 +2,45 @@ category_index = CATEGORY_PKA /datum/orderable_item/accelerator/gun - item_path = /obj/item/gun/energy/recharge/kinetic_accelerator + purchase_path = /obj/item/gun/energy/recharge/kinetic_accelerator cost_per_order = 600 /datum/orderable_item/accelerator/range - item_path = /obj/item/borg/upgrade/modkit/range + purchase_path = /obj/item/borg/upgrade/modkit/range cost_per_order = 675 /datum/orderable_item/accelerator/damage - item_path = /obj/item/borg/upgrade/modkit/damage + purchase_path = /obj/item/borg/upgrade/modkit/damage cost_per_order = 675 /datum/orderable_item/accelerator/cooldown - item_path = /obj/item/borg/upgrade/modkit/cooldown + purchase_path = /obj/item/borg/upgrade/modkit/cooldown cost_per_order = 675 /datum/orderable_item/accelerator/chasis - item_path = /obj/item/borg/upgrade/modkit/chassis_mod + purchase_path = /obj/item/borg/upgrade/modkit/chassis_mod cost_per_order = 250 /datum/orderable_item/accelerator/chasis_orange - item_path = /obj/item/borg/upgrade/modkit/chassis_mod/orange + purchase_path = /obj/item/borg/upgrade/modkit/chassis_mod/orange cost_per_order = 300 /datum/orderable_item/accelerator/tracer - item_path = /obj/item/borg/upgrade/modkit/tracer + purchase_path = /obj/item/borg/upgrade/modkit/tracer cost_per_order = 100 /datum/orderable_item/accelerator/adjustable_tracer - item_path = /obj/item/borg/upgrade/modkit/tracer/adjustable + purchase_path = /obj/item/borg/upgrade/modkit/tracer/adjustable cost_per_order = 150 /datum/orderable_item/accelerator/aoe_mobs - item_path = /obj/item/borg/upgrade/modkit/aoe/mobs + purchase_path = /obj/item/borg/upgrade/modkit/aoe/mobs cost_per_order = 1500 /datum/orderable_item/accelerator/minebot_passthrough - item_path = /obj/item/borg/upgrade/modkit/minebot_passthrough + purchase_path = /obj/item/borg/upgrade/modkit/minebot_passthrough cost_per_order = 800 /datum/orderable_item/accelerator/friendly_fire - item_path = /obj/item/borg/upgrade/modkit/human_passthrough + purchase_path = /obj/item/borg/upgrade/modkit/human_passthrough cost_per_order = 750 diff --git a/code/game/machinery/computer/orders/order_items/mining/order_toys.dm b/code/game/machinery/computer/orders/order_items/mining/order_toys.dm index fab03cabaa4b6..65bbee24ead6e 100644 --- a/code/game/machinery/computer/orders/order_items/mining/order_toys.dm +++ b/code/game/machinery/computer/orders/order_items/mining/order_toys.dm @@ -2,38 +2,38 @@ category_index = CATEGORY_TOYS_DRONE /datum/orderable_item/toys_drones/soap - item_path = /obj/item/soap/nanotrasen + purchase_path = /obj/item/soap/nanotrasen cost_per_order = 180 /datum/orderable_item/toys_drones/laser_pointer - item_path = /obj/item/laser_pointer + purchase_path = /obj/item/laser_pointer cost_per_order = 275 /datum/orderable_item/toys_drones/facehugger - item_path = /obj/item/clothing/mask/facehugger/toy + purchase_path = /obj/item/clothing/mask/facehugger/toy cost_per_order = 275 /datum/orderable_item/toys_drones/mining_drone - item_path = /mob/living/basic/mining_drone + purchase_path = /mob/living/basic/mining_drone cost_per_order = 675 /datum/orderable_item/toys_drones/drone_health - item_path = /obj/item/mine_bot_upgrade/health + purchase_path = /obj/item/mine_bot_upgrade/health cost_per_order = 350 /datum/orderable_item/toys_drones/drone_shield - item_path = /obj/item/mine_bot_upgrade/regnerative_shield + purchase_path = /obj/item/mine_bot_upgrade/regnerative_shield cost_per_order = 500 /datum/orderable_item/toys_drones/drone_remote - item_path = /obj/item/minebot_remote_control + purchase_path = /obj/item/minebot_remote_control cost_per_order = 500 /datum/orderable_item/toys_drones/drone_pka - item_path = /obj/item/borg/upgrade/modkit/cooldown/minebot + purchase_path = /obj/item/borg/upgrade/modkit/cooldown/minebot cost_per_order = 525 /datum/orderable_item/toys_drones/drone_sentience - item_path = /obj/item/slimepotion/slime/sentience/mining + purchase_path = /obj/item/slimepotion/slime/sentience/mining cost_per_order = 850 diff --git a/code/game/machinery/computer/orders/order_items/order_datum.dm b/code/game/machinery/computer/orders/order_items/order_datum.dm index 13684fc742b44..28c21a14f267e 100644 --- a/code/game/machinery/computer/orders/order_items/order_datum.dm +++ b/code/game/machinery/computer/orders/order_items/order_datum.dm @@ -5,7 +5,7 @@ ///Description shown in the shop, set automatically unless it's hard set by the subtype var/desc ///Path of the item that is purchased when ordering us. - var/obj/item/item_path + var/atom/movable/purchase_path ///The category this item will be displayed in. var/category_index = NONE ///How much this item costs to order. @@ -15,14 +15,9 @@ . = ..() if(!category_index) CRASH("[type] doesn't have a category_index assigned!") - if(!item_path) + if(!purchase_path) CRASH("[type] orderable item datum with no item path was created!") if(!name) - name = initial(item_path.name) + name = initial(purchase_path.name) if(!desc) - desc = initial(item_path.desc) - -/datum/orderable_item/Destroy(force) - if(item_path) - qdel(item_path) - return ..() + desc = initial(purchase_path.desc) diff --git a/code/game/machinery/dna_infuser/organ_sets/fish_organs.dm b/code/game/machinery/dna_infuser/organ_sets/fish_organs.dm index c7f9ec460f508..2197eb4e1697e 100644 --- a/code/game/machinery/dna_infuser/organ_sets/fish_organs.dm +++ b/code/game/machinery/dna_infuser/organ_sets/fish_organs.dm @@ -190,6 +190,7 @@ . = ..() owner.AddElementTrait(TRAIT_WADDLING, type, /datum/element/waddling/flopping_only) // DOPPLER EDIT, old code: owner.AddElementTrait(TRAIT_WADDLING, type, /datum/element/waddling) RegisterSignal(owner, COMSIG_MOVABLE_MOVED, PROC_REF(check_location)) + RegisterSignal(owner, COMSIG_LIVING_GIBBER_ACT, PROC_REF(on_gibber_processed)) check_location(owner, null) /obj/item/organ/tail/fish/on_mob_remove(mob/living/carbon/owner) @@ -197,7 +198,12 @@ owner.remove_traits(list(TRAIT_WADDLING, TRAIT_NO_STAGGER), type) owner.remove_movespeed_modifier(/datum/movespeed_modifier/fish_on_water) owner.remove_actionspeed_modifier(/datum/actionspeed_modifier/fish_on_water) - UnregisterSignal(owner, COMSIG_MOVABLE_MOVED) + UnregisterSignal(owner, list(COMSIG_MOVABLE_MOVED, COMSIG_LIVING_GIBBER_ACT)) + +/obj/item/organ/tail/fish/proc/on_gibber_processed(mob/living/carbon/owner, mob/living/user, obj/machinery/gibber, list/results) + SIGNAL_HANDLER + for(var/iteration in 1 to fillet_amount * 0.5) + results += new fillet_type /obj/item/organ/tail/fish/get_greyscale_color_from_draw_color() set_greyscale(bodypart_overlay.draw_color) diff --git a/code/game/machinery/doors/airlock.dm b/code/game/machinery/doors/airlock.dm index 39909c64cf994..0e9fcc6b43a81 100644 --- a/code/game/machinery/doors/airlock.dm +++ b/code/game/machinery/doors/airlock.dm @@ -1390,9 +1390,10 @@ /obj/machinery/door/airlock/proc/prison_open() if(obj_flags & EMAGGED) return - locked = FALSE + if(locked) + unbolt() open() - locked = TRUE + bolt() return // gets called when a player uses an airlock painter on this airlock diff --git a/code/game/machinery/doors/firedoor.dm b/code/game/machinery/doors/firedoor.dm index 858f2dffefff2..36828273f1944 100644 --- a/code/game/machinery/doors/firedoor.dm +++ b/code/game/machinery/doors/firedoor.dm @@ -548,18 +548,20 @@ if(welded || operating) return + var/atom/crowbar_owner = acting_object.loc //catchs mechs and any other non-mob using a crowbar + if(density) being_held_open = TRUE - user.balloon_alert_to_viewers("holding firelock open", "holding firelock open") + crowbar_owner.balloon_alert_to_viewers("holding firelock open", "holding firelock open") COOLDOWN_START(src, activation_cooldown, REACTIVATION_DELAY) open() - if(QDELETED(user)) + if(QDELETED(crowbar_owner)) being_held_open = FALSE return - RegisterSignal(user, COMSIG_MOVABLE_MOVED, PROC_REF(handle_held_open_adjacency)) - RegisterSignal(user, COMSIG_LIVING_SET_BODY_POSITION, PROC_REF(handle_held_open_adjacency)) - RegisterSignal(user, COMSIG_QDELETING, PROC_REF(handle_held_open_adjacency)) - handle_held_open_adjacency(user) + RegisterSignal(crowbar_owner, COMSIG_MOVABLE_MOVED, PROC_REF(handle_held_open_adjacency)) + RegisterSignal(crowbar_owner, COMSIG_LIVING_SET_BODY_POSITION, PROC_REF(handle_held_open_adjacency)) + RegisterSignal(crowbar_owner, COMSIG_QDELETING, PROC_REF(handle_held_open_adjacency)) + handle_held_open_adjacency(crowbar_owner) else close() diff --git a/code/game/machinery/harvester.dm b/code/game/machinery/harvester.dm index 4949f53adfbfe..bbb6f33236d23 100644 --- a/code/game/machinery/harvester.dm +++ b/code/game/machinery/harvester.dm @@ -179,7 +179,7 @@ obj_flags |= EMAGGED allow_living = TRUE allow_clothing = TRUE - balloon_alert(!user, "lifesign scanners overloaded") + balloon_alert(user, "lifesign scanners overloaded") return TRUE /obj/machinery/harvester/container_resist_act(mob/living/user) diff --git a/code/game/machinery/newscaster/newscaster_machine.dm b/code/game/machinery/newscaster/newscaster_machine.dm index 62d70e1e6925c..9961b1d9f6fc8 100644 --- a/code/game/machinery/newscaster/newscaster_machine.dm +++ b/code/game/machinery/newscaster/newscaster_machine.dm @@ -231,7 +231,7 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/newscaster, 30) data["channelLocked"] = current_channel.locked data["channelCensored"] = current_channel.censored - //We send all the information about all messages in existance. + //We send all the information about all messages in existence. data["messages"] = message_list data["wanted"] = wanted_info diff --git a/code/game/machinery/scanner_gate.dm b/code/game/machinery/scanner_gate.dm index 3d87e4cb60b9a..ee93f41cf552e 100644 --- a/code/game/machinery/scanner_gate.dm +++ b/code/game/machinery/scanner_gate.dm @@ -5,7 +5,6 @@ #define SCANGATE_WANTED "Wanted" #define SCANGATE_SPECIES "Species" #define SCANGATE_NUTRITION "Nutrition" -#define SCANGATE_CONTRABAND "Contraband" /obj/machinery/scanner_gate name = "scanner gate" @@ -39,8 +38,6 @@ var/minus_false_beep = 0 ///Base false positive/negative chance var/base_false_beep = 5 - ///Is an n-spect scanner attached to the gate? Enables contraband scanning. - var/obj/item/inspector/n_spect = null ///List of species that can be scanned by the gate. Supports adding more species' IDs during in-game. var/list/available_species = list( SPECIES_HUMAN, @@ -76,12 +73,6 @@ for(var/datum/stock_part/scanning_module/scanning_module in component_parts) minus_false_beep = scanning_module.tier //The better are scanninning modules - the lower is chance of False Positives -/obj/machinery/scanner_gate/atom_deconstruct(disassembled) - . = ..() - if(n_spect) - n_spect.forceMove(drop_location()) - n_spect = null - /obj/machinery/scanner_gate/examine(mob/user) . = ..() @@ -90,18 +81,6 @@ . += span_notice("The control panel is ID-locked. Swipe a valid ID to unlock it.") else . += span_notice("The control panel is unlocked. Swipe an ID to lock it.") - if(n_spect) - . += span_notice("The scanner is equipped with an N-Spect scanner. Use a [span_boldnotice("crowbar")] to uninstall.") - -/obj/machinery/scanner_gate/add_context(atom/source, list/context, obj/item/held_item, mob/user) - . = ..() - if(n_spect && held_item?.tool_behaviour == TOOL_CROWBAR) - context[SCREENTIP_CONTEXT_LMB] = "Remove N-Spect scanner" - return CONTEXTUAL_SCREENTIP_SET - if(!n_spect && istype(held_item, /obj/item/inspector)) - context[SCREENTIP_CONTEXT_LMB] = "Install N-Spect scanner" - return CONTEXTUAL_SCREENTIP_SET - /obj/machinery/scanner_gate/proc/on_entered(datum/source, atom/movable/thing) SIGNAL_HANDLER @@ -136,19 +115,6 @@ return set_scanline("passive") -/obj/machinery/scanner_gate/item_interaction(mob/living/user, obj/item/tool, list/modifiers) - if(istype(tool, /obj/item/inspector)) - if(n_spect) - to_chat(user, span_warning("The scanner is already equipped with an N-Spect scanner.")) - return ITEM_INTERACT_BLOCKING - else - to_chat(user, span_notice("You install an N-Spect scanner on [src].")) - n_spect = tool - if(!user.transferItemToLoc(tool, src)) - return ITEM_INTERACT_BLOCKING - return ITEM_INTERACT_SUCCESS - return NONE - /obj/machinery/scanner_gate/attackby(obj/item/attacking_item, mob/user, params) var/obj/item/card/id/card = attacking_item.GetID() if(card) @@ -171,24 +137,6 @@ wires.interact(user) return ..() -/obj/machinery/scanner_gate/crowbar_act(mob/living/user, obj/item/tool) - . = ..() - if(n_spect) - if(locked) - balloon_alert(user, "locked!") - return ITEM_INTERACT_BLOCKING - - to_chat(user, span_notice("You uninstall [n_spect] from [src].")) - n_spect.forceMove(drop_location()) - return ITEM_INTERACT_SUCCESS - -/obj/machinery/scanner_gate/Exited(atom/gone) - . = ..() - if(gone == n_spect) - n_spect = null - if(scangate_mode == SCANGATE_CONTRABAND) - scangate_mode = SCANGATE_NONE - /obj/machinery/scanner_gate/emag_act(mob/user, obj/item/card/emag/emag_card) if(obj_flags & EMAGGED) return FALSE @@ -202,6 +150,7 @@ var/beep = FALSE var/color = null var/detected_thing = null + var/bypassed = FALSE playsound(src, SFX_INDUSTRIAL_SCAN, 20, TRUE, -2, TRUE, FALSE) switch(scangate_mode) if(SCANGATE_NONE) @@ -251,7 +200,7 @@ if((!HAS_TRAIT(scanned_human, TRAIT_MINDSHIELD)) && (isnull(idcard) || !(ACCESS_WEAPONS in idcard.access))) // mindshield or ID card with weapons access, like bartender beep = TRUE break - say("[detected_thing] detection bypassed.") + bypassed = TRUE break else for(var/obj/item/content in thing.get_all_contents_skipping_traits(TRAIT_CONTRABAND_BLOCKER)) @@ -267,14 +216,6 @@ if(scanned_human.nutrition >= detect_nutrition && detect_nutrition == NUTRITION_LEVEL_FAT) beep = TRUE detected_thing = "Obesity" - if(SCANGATE_CONTRABAND) - for(var/obj/item/content in thing.get_all_contents_skipping_traits(TRAIT_CONTRABAND_BLOCKER)) - detected_thing = "Contraband" - if(content.is_contraband()) - beep = TRUE - break - if(!n_spect.scans_correctly) - beep = !beep //We do a little trolling if(reverse) beep = !beep @@ -291,6 +232,8 @@ assembly?.activate() else SEND_SIGNAL(src, COMSIG_SCANGATE_PASS_NO_TRIGGER, thing) + if(bypassed) + say("[detected_thing] detection bypassed.") if(!ignore_signals) color = wires.get_color_of_wire(WIRE_DENY) var/obj/item/assembly/assembly = wires.get_attached(color) @@ -338,7 +281,6 @@ data["disease_threshold"] = disease_threshold data["target_species_id"] = detect_species_id data["target_nutrition"] = detect_nutrition - data["contraband_enabled"] = !!n_spect data["target_zombie"] = (detect_species_id == SPECIES_ZOMBIE) return data @@ -385,7 +327,7 @@ /obj/machinery/scanner_gate/preset_guns locked = TRUE - req_access = ACCESS_SECURITY + req_access = list(ACCESS_SECURITY) scangate_mode = SCANGATE_GUNS #undef SCANGATE_NONE @@ -395,4 +337,3 @@ #undef SCANGATE_WANTED #undef SCANGATE_SPECIES #undef SCANGATE_NUTRITION -#undef SCANGATE_CONTRABAND diff --git a/code/game/objects/effects/portals.dm b/code/game/objects/effects/portals.dm index 18f633504264f..21a51ba9bcb42 100644 --- a/code/game/objects/effects/portals.dm +++ b/code/game/objects/effects/portals.dm @@ -130,29 +130,35 @@ linked = null return ..() -/obj/effect/portal/attack_ghost(mob/dead/observer/O) - if(!teleport(O, TRUE)) +/obj/effect/portal/attack_ghost(mob/dead/observer/ghost) + if(!teleport(ghost, force = TRUE)) return ..() + return BULLET_ACT_FORCE_PIERCE -/obj/effect/portal/proc/teleport(atom/movable/M, force = FALSE) - if(!force && (!istype(M) || iseffect(M) || (ismecha(M) && !mech_sized) || (!isobj(M) && !ismob(M)))) //Things that shouldn't teleport. +/obj/effect/portal/bullet_act(obj/projectile/hitting_projectile, def_zone, piercing_hit) + if (!teleport(hitting_projectile, force = TRUE)) + return ..() + return BULLET_ACT_FORCE_PIERCE + +/obj/effect/portal/proc/teleport(atom/movable/moving, force = FALSE) + if(!force && (!istype(moving) || iseffect(moving) || (ismecha(moving) && !mech_sized) || (!isobj(moving) && !ismob(moving)))) //Things that shouldn't teleport. return var/turf/real_target = get_link_target_turf() if(!istype(real_target)) return FALSE - if(!force && (!ismecha(M) && !isprojectile(M) && M.anchored && !allow_anchored)) + if(!force && (!ismecha(moving) && !isprojectile(moving) && moving.anchored && !allow_anchored)) return var/no_effect = FALSE if(last_effect == world.time || sparkless) no_effect = TRUE else last_effect = world.time - var/turf/start_turf = get_turf(M) - if(do_teleport(M, real_target, innate_accuracy_penalty, no_effects = no_effect, channel = teleport_channel, forced = force_teleport)) - if(isprojectile(M)) - var/obj/projectile/P = M + var/turf/start_turf = get_turf(moving) + if(do_teleport(moving, real_target, innate_accuracy_penalty, no_effects = no_effect, channel = teleport_channel, forced = force_teleport)) + if(isprojectile(moving)) + var/obj/projectile/P = moving P.ignore_source_check = TRUE - new /obj/effect/temp_visual/portal_animation(start_turf, src, M) + new /obj/effect/temp_visual/portal_animation(start_turf, src, moving) playsound(start_turf, SFX_PORTAL_ENTER, 50, TRUE, SHORT_RANGE_SOUND_EXTRARANGE) playsound(real_target, SFX_PORTAL_ENTER, 50, TRUE, SHORT_RANGE_SOUND_EXTRARANGE) return TRUE @@ -189,7 +195,7 @@ linked = P break -/obj/effect/portal/permanent/teleport(atom/movable/M, force = FALSE) +/obj/effect/portal/permanent/teleport(atom/movable/moving, force = FALSE) set_linked() // update portal links . = ..() @@ -213,9 +219,9 @@ name = "one-use portal" desc = "This is probably the worst decision you'll ever make in your life." -/obj/effect/portal/permanent/one_way/one_use/teleport(atom/movable/M, force = FALSE) +/obj/effect/portal/permanent/one_way/one_use/teleport(atom/movable/moving, force = FALSE) . = ..() - if (. && !isdead(M)) + if (. && !isdead(moving)) expire() /** diff --git a/code/game/objects/items/climbingrope.dm b/code/game/objects/items/climbingrope.dm index 936858bbae757..46bc56e21fef2 100644 --- a/code/game/objects/items/climbingrope.dm +++ b/code/game/objects/items/climbingrope.dm @@ -24,7 +24,7 @@ . = ..() var/list/look_binds = user.client.prefs.key_bindings["look up"] . += span_notice("Firstly, look upwards by holding [english_list(look_binds, nothing_text = "(nothing bound)", and_text = " or ", comma_text = ", or ")]!") - . += span_notice("Then, click solid ground adjacent to the hole above you.") + . += span_notice("Then, click solid ground (or lattice/catwalk) adjacent to the hole above you.") . += span_notice("The rope looks like you could use it [uses] times before it falls apart.") /obj/item/climbing_hook/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) @@ -32,26 +32,27 @@ return NONE return ranged_interact_with_atom(interacting_with, user, modifiers) -/obj/item/climbing_hook/ranged_interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) +/obj/item/climbing_hook/ranged_interact_with_atom(turf/open/interacting_with, mob/living/user, list/modifiers) + interacting_with = get_turf(interacting_with) if(interacting_with.z == user.z) return NONE - var/turf/open/target = interacting_with - if(!istype(target) || isopenspaceturf(target)) + if(!istype(interacting_with) || !isturf(user.loc)) //better safe than sorry return ITEM_INTERACT_BLOCKING var/turf/user_turf = get_turf(user) var/turf/above = GET_TURF_ABOVE(user_turf) - if(target_blocked(target, above)) + if(target_blocked(interacting_with, above)) + balloon_alert(user, "cant get there!") return ITEM_INTERACT_BLOCKING - if(!isopenspaceturf(above) || !above.Adjacent(target)) //are we below a hole, is the target blocked, is the target adjacent to our hole - balloon_alert(user, "blocked!") + if(!above.Adjacent(interacting_with)) //is the target adjacent to our hole + balloon_alert(user, "too far!") return ITEM_INTERACT_BLOCKING - var/away_dir = get_dir(above, target) + var/away_dir = get_dir(above, interacting_with) user.visible_message(span_notice("[user] begins climbing upwards with [src]."), span_notice("You get to work on properly hooking [src] and going upwards.")) - playsound(target, 'sound/effects/pickaxe/picaxe1.ogg', 50) //plays twice so people above and below can hear + playsound(interacting_with, 'sound/effects/pickaxe/picaxe1.ogg', 50) //plays twice so people above and below can hear playsound(user_turf, 'sound/effects/pickaxe/picaxe1.ogg', 50) - var/list/effects = list(new /obj/effect/temp_visual/climbing_hook(target, away_dir), new /obj/effect/temp_visual/climbing_hook(user_turf, away_dir)) + var/list/effects = list(new /obj/effect/temp_visual/climbing_hook(interacting_with, away_dir), new /obj/effect/temp_visual/climbing_hook(user_turf, away_dir)) // Our climbers athletics ability var/fitness_level = user.mind?.get_skill_level(/datum/skill/athletics) @@ -65,8 +66,8 @@ var/final_climb_time = (climb_time - fitness_level) * misc_multiplier - if(do_after(user, final_climb_time, target)) - user.forceMove(target) + if(do_after(user, final_climb_time, interacting_with)) + user.forceMove(interacting_with) uses-- user.mind?.adjust_experience(/datum/skill/athletics, 50) //get some experience for our trouble, especially since this costs us a climbing rope use @@ -80,7 +81,7 @@ // didnt want to mess up is_blocked_turf_ignore_climbable /// checks if our target is blocked, also checks for border objects facing the above turf and climbable stuff /obj/item/climbing_hook/proc/target_blocked(turf/target, turf/above) - if(target.density || above.density) + if(target.density || (isopenspaceturf(target) && target.zPassOut(DOWN)) || !above.zPassOut(DOWN) || above.density) // we check if we would fall down from it additionally return TRUE for(var/atom/movable/atom_content as anything in target.contents) diff --git a/code/game/objects/items/devices/traitordevices.dm b/code/game/objects/items/devices/traitordevices.dm index 5a108c83e823b..c1ed690a3143c 100644 --- a/code/game/objects/items/devices/traitordevices.dm +++ b/code/game/objects/items/devices/traitordevices.dm @@ -341,7 +341,7 @@ effective or pretty fucking useless. . = ..() register_context() -/atom/movable/screen/alert/give/add_context(atom/source, list/context, obj/item/held_item, mob/user) +/obj/item/jammer/add_context(atom/source, list/context, obj/item/held_item, mob/user) context[SCREENTIP_CONTEXT_LMB] = "Release distruptor wave" context[SCREENTIP_CONTEXT_RMB] = "Toggle" return CONTEXTUAL_SCREENTIP_SET diff --git a/code/game/objects/items/eightball.dm b/code/game/objects/items/eightball.dm index 40f08e78ffc77..e44e989706a6d 100644 --- a/code/game/objects/items/eightball.dm +++ b/code/game/objects/items/eightball.dm @@ -15,26 +15,33 @@ var/cooldown_time = 10 SECONDS var/static/list/possible_answers = list( - "It is certain", - "It is decidedly so", - "Without a doubt", - "Yes definitely", - "You may rely on it", - "As I see it, yes", - "Most likely", - "Outlook good", - "Yes", - "Signs point to yes", - "Reply hazy try again", - "Ask again later", - "Better not tell you now", - "Cannot predict now", - "Concentrate and ask again", - "Don't count on it", - "My reply is no", - "My sources say no", - "Outlook not so good", - "Very doubtful") + "Yes" = list( + "It is certain", + "It is decidedly so", + "Without a doubt", + "Yes definitely", + "You may rely on it", + "As I see it, yes", + "Most likely", + "Outlook good", + "Yes", + "Signs point to yes", + ), + "Maybe" = list( + "Reply hazy try again", + "Ask again later", + "Better not tell you now", + "Cannot predict now", + "Concentrate and ask again", + ), + "No" = list( + "Don't count on it", + "My reply is no", + "My sources say no", + "Outlook not so good", + "Very doubtful" + ), + ) /obj/item/toy/eightball/Initialize(mapload) . = ..() @@ -77,8 +84,14 @@ /obj/item/toy/eightball/proc/start_shaking(mob/user) return TRUE +/// Different from get_answer(). +/obj/item/toy/eightball/proc/pick_from_answer_list() + //! This is for grabbing an answer from the answer matrix. + var/key = pick(possible_answers) + return pick(possible_answers[key]) + /obj/item/toy/eightball/proc/get_answer() - return pick(possible_answers) + return pick_from_answer_list() // A broken magic eightball, it only says "YOU SUCK" over and over again. @@ -89,7 +102,7 @@ /obj/item/toy/eightball/broken/Initialize(mapload) . = ..() - fixed_answer = pick(possible_answers) + fixed_answer = pick_from_answer_list() /obj/item/toy/eightball/broken/get_answer() return fixed_answer @@ -104,38 +117,10 @@ //these kind of store the same thing but one is easier to work with. var/list/votes = list() var/list/voted = list() - var/static/list/haunted_answers = list( - "yes" = list( - "It is certain", - "It is decidedly so", - "Without a doubt", - "Yes definitely", - "You may rely on it", - "As I see it, yes", - "Most likely", - "Outlook good", - "Yes", - "Signs point to yes" - ), - "maybe" = list( - "Reply hazy try again", - "Ask again later", - "Better not tell you now", - "Cannot predict now", - "Concentrate and ask again" - ), - "no" = list( - "Don't count on it", - "My reply is no", - "My sources say no", - "Outlook not so good", - "Very doubtful" - ) - ) /obj/item/toy/eightball/haunted/Initialize(mapload) . = ..() - for (var/answer in haunted_answers) + for (var/answer in possible_answers) votes[answer] = 0 SSpoints_of_interest.make_point_of_interest(src) @@ -153,7 +138,7 @@ /obj/item/toy/eightball/haunted/start_shaking(mob/user) // notify ghosts that someone's shaking a haunted eightball // and inform them of the message, (hopefully a yes/no question) - selected_message = tgui_input_text(user, "What is your question?", "Eightball", max_length = MAX_MESSAGE_LEN) || initial(selected_message) + selected_message = tgui_input_text(user, "What is your question?", "Eightball", max_length = CHAT_MESSAGE_MAX_LENGTH) || initial(selected_message) if (!(src in user.held_items)) return FALSE notify_ghosts( @@ -186,7 +171,7 @@ voted.Cut() - var/list/top_options = haunted_answers[top_vote] + var/list/top_options = possible_answers[top_vote] return pick(top_options) // Only ghosts can interact because only ghosts can open the ui @@ -210,11 +195,11 @@ data["question"] = selected_message data["answers"] = list() - for(var/vote in haunted_answers) + for(var/vote in possible_answers) var/list/answer_data = list() answer_data["answer"] = vote answer_data["amount"] = votes[vote] - answer_data["selected"] = voted[user.ckey] + answer_data["selected"] = (voted[user.ckey] == vote) data["answers"] += list(answer_data) return data @@ -229,7 +214,7 @@ switch(action) if("vote") var/selected_answer = params["answer"] - if(!(selected_answer in haunted_answers)) + if(!(selected_answer in possible_answers)) return var/oldvote = voted[user.ckey] if(oldvote) diff --git a/code/game/objects/items/food/lizard.dm b/code/game/objects/items/food/lizard.dm index e0e005502d87c..74534592a5feb 100644 --- a/code/game/objects/items/food/lizard.dm +++ b/code/game/objects/items/food/lizard.dm @@ -575,7 +575,7 @@ /datum/reagent/consumable/nutriment/protein = 10, ) tastes = list("bread" = 1, "meat" = 1) - foodtypes = MEAT | NUTS | RAW | GORE + foodtypes = MEAT | NUTS | GORE crafting_complexity = FOOD_COMPLEXITY_3 /obj/item/food/pizza/flatbread/stinging diff --git a/code/game/objects/items/food/packaged.dm b/code/game/objects/items/food/packaged.dm index b3578204a2daa..0c68d329d97e6 100644 --- a/code/game/objects/items/food/packaged.dm +++ b/code/game/objects/items/food/packaged.dm @@ -218,7 +218,7 @@ /obj/item/food/ready_donk name = "\improper Ready-Donk: Bachelor Chow" desc = "A quick Donk-dinner: now with flavour!" - icon_state = "ready_donk" + icon_state = "ready_donk_bachelor" trash_type = /obj/item/trash/ready_donk food_reagents = list(/datum/reagent/consumable/nutriment = 5) tastes = list("food?" = 2, "laziness" = 1) @@ -249,7 +249,7 @@ /obj/item/food/ready_donk/warm name = "warm Ready-Donk: Bachelor Chow" desc = "A quick Donk-dinner, now with flavour! And it's even hot!" - icon_state = "ready_donk_warm" + icon_state = "ready_donk_bachelor_warm" food_reagents = list( /datum/reagent/consumable/nutriment = 5, /datum/reagent/medicine/omnizine = 3, @@ -262,6 +262,7 @@ /obj/item/food/ready_donk/mac_n_cheese name = "\improper Ready-Donk: Donk-a-Roni" desc = "Neon-orange mac n' cheese in seconds!" + icon_state = "ready_donk_mac" tastes = list("cheesy pasta" = 2, "laziness" = 1) foodtypes = GRAIN | DAIRY | JUNKFOOD @@ -270,13 +271,14 @@ /obj/item/food/ready_donk/warm/mac_n_cheese name = "warm Ready-Donk: Donk-a-Roni" desc = "Neon-orange mac n' cheese, ready to eat!" - icon_state = "ready_donk_warm_mac" + icon_state = "ready_donk_mac_warm" tastes = list("cheesy pasta" = 2, "laziness" = 1) foodtypes = GRAIN | DAIRY | JUNKFOOD /obj/item/food/ready_donk/donkhiladas name = "\improper Ready-Donk: Donkhiladas" desc = "Donk Co's signature Donkhiladas with Donk sauce, for an 'authentic' taste of Mexico." + icon_state = "ready_donk_mex" tastes = list("enchiladas" = 2, "laziness" = 1) foodtypes = GRAIN | DAIRY | MEAT | VEGETABLES | JUNKFOOD @@ -285,13 +287,14 @@ /obj/item/food/ready_donk/warm/donkhiladas name = "warm Ready-Donk: Donkhiladas" desc = "Donk Co's signature Donkhiladas with Donk sauce, served as hot as the Mexican sun." - icon_state = "ready_donk_warm_mex" + icon_state = "ready_donk_mex_warm" tastes = list("enchiladas" = 2, "laziness" = 1) foodtypes = GRAIN | DAIRY | MEAT | VEGETABLES | JUNKFOOD /obj/item/food/ready_donk/nachos_grandes //which translates to... big nachos name = "\improper Ready-Donk: Donk Sol Series Boritos Nachos Grandes" desc = "Get ready for game day with Donk's classic Nachos Grandes, sponsors of the Donk Sol Series! Boritos chips loaded with cheese, spicy meat and beans, alongside separate guac, pico and donk sauce. Batter up!" + icon_state = "ready_donk_nachos" tastes = list("nachos" = 2, "laziness" = 1) foodtypes = GRAIN | DAIRY | MEAT | VEGETABLES | JUNKFOOD @@ -300,25 +303,58 @@ /obj/item/food/ready_donk/warm/nachos_grandes name = "warm Ready-Donk: Donk Sol Series Boritos Nachos Grandes" desc = "Get ready for game day with Donk's classic Nachos Grandes, sponsors of the Donk Sol Series! Boritos chips loaded with cheese, spicy meat and beans, alongside separate guac, pico and donk sauce. Served hotter than Sakamoto's fastball!" - icon_state = "ready_donk_warm_nachos" + icon_state = "ready_donk_nachos_warm" tastes = list("nachos" = 2, "laziness" = 1) foodtypes = GRAIN | DAIRY | MEAT | VEGETABLES | JUNKFOOD /obj/item/food/ready_donk/donkrange_chicken name = "\improper Ready-Donk: Donk-range Chicken" desc = "A Chinese classic, it's Donk's original spicy orange chicken with stir-fried peppers and onions, all over steamed rice." + icon_state = "ready_donk_orange" tastes = list("orange chicken" = 2, "laziness" = 1) foodtypes = GRAIN | MEAT | VEGETABLES | JUNKFOOD warm_type = /obj/item/food/ready_donk/warm/donkrange_chicken /obj/item/food/ready_donk/warm/donkrange_chicken - name = "warm Ready-Donk: Ready-Donk: Donk-range Chicken" + name = "warm Ready-Donk: Donk-range Chicken" desc = "A Chinese classic, it's Donk's original spicy orange chicken with stir-fried peppers and onions, all over steamed rice and served hotter than a dragon's breath." - icon_state = "ready_donk_warm_orange" + icon_state = "ready_donk_orange_warm" tastes = list("orange chicken" = 2, "laziness" = 1) foodtypes = GRAIN | MEAT | VEGETABLES | JUNKFOOD +/obj/item/food/ready_donk/salisbury_steak + name = "\improper Ready-Donk Donkriginals: Salisbury Steak" + desc = "The original and best: it's a slab of moulded beef, drenched in brown gravy, with a side of mashed potatoes. Better find a TV to eat this in front of." + icon_state = "ready_donk_salisbury" + tastes = list("salisbury steak" = 2, "laziness" = 1) + foodtypes = MEAT | VEGETABLES | JUNKFOOD + + warm_type = /obj/item/food/ready_donk/warm/salisbury_steak + +/obj/item/food/ready_donk/warm/salisbury_steak + name = "warm Ready-Donk Donkriginals: Salisbury Steak" + desc = "The original and best: it's a slab of moulded beef, drenched in brown gravy, with a side of mashed potatoes. It's almost as hot as a season finale." + icon_state = "ready_donk_salisbury_warm" + tastes = list("salisbury steak" = 2, "laziness" = 1) + foodtypes = MEAT | VEGETABLES | JUNKFOOD + +/obj/item/food/ready_donk/country_chicken + name = "\improper Ready-Donk Donkriginals: Country-Fried Chicken" + desc = "A TV dinner classic: \"crispy\" fried chicken in country gravy, mashed potatoes, and green beans." + icon_state = "ready_donk_chicken" + tastes = list("country-fried chicken" = 2, "laziness" = 1) + foodtypes = MEAT | DAIRY | VEGETABLES | JUNKFOOD + + warm_type = /obj/item/food/ready_donk/warm/country_chicken + +/obj/item/food/ready_donk/warm/country_chicken + name = "warm Ready-Donk Donkriginals: Country-Fried Chicken" + desc = "A TV dinner classic: \"crispy\" fried chicken in country gravy, mashed potatoes, and green beans. Get it while it's hot!" + icon_state = "ready_donk_chicken_warm" + tastes = list("country-fried chicken" = 2, "laziness" = 1) + foodtypes = MEAT | DAIRY | VEGETABLES | JUNKFOOD + // Rations /obj/item/food/rationpack name = "ration pack" diff --git a/code/game/objects/items/grenades/flashbang.dm b/code/game/objects/items/grenades/flashbang.dm index c83801d81fc53..2300d2c67174d 100644 --- a/code/game/objects/items/grenades/flashbang.dm +++ b/code/game/objects/items/grenades/flashbang.dm @@ -53,7 +53,7 @@ /obj/item/grenade/stingbang name = "stingbang" - icon_state = "timeg" + icon_state = "timeg_locked" inhand_icon_state = "flashbang" lefthand_file = 'icons/mob/inhands/equipment/security_lefthand.dmi' righthand_file = 'icons/mob/inhands/equipment/security_righthand.dmi' @@ -121,7 +121,7 @@ /obj/item/grenade/primer name = "rotfrag grenade" desc = "A grenade that generates more shrapnel the more you rotate it in your hand after pulling the pin. This one releases shrapnel shards." - icon_state = "timeg" + icon_state = "timeg_locked" inhand_icon_state = "flashbang" lefthand_file = 'icons/mob/inhands/equipment/security_lefthand.dmi' righthand_file = 'icons/mob/inhands/equipment/security_righthand.dmi' diff --git a/code/game/objects/items/holosign_creator.dm b/code/game/objects/items/holosign_creator.dm index 049ea8928feff..efe1d9e31f1ba 100644 --- a/code/game/objects/items/holosign_creator.dm +++ b/code/game/objects/items/holosign_creator.dm @@ -35,6 +35,11 @@ return . += span_notice("It is currently maintaining [signs.len]/[max_signs] projections.") +/obj/item/holosign_creator/check_allowed_items(atom/target, not_inside, target_self) + if(HAS_TRAIT(target, TRAIT_COMBAT_MODE_SKIP_INTERACTION)) + return FALSE + return ..() + /obj/item/holosign_creator/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) if(!check_allowed_items(interacting_with, not_inside = TRUE)) return NONE diff --git a/code/game/objects/items/hot_potato.dm b/code/game/objects/items/hot_potato.dm index 20233db522b39..8bede8813a256 100644 --- a/code/game/objects/items/hot_potato.dm +++ b/code/game/objects/items/hot_potato.dm @@ -18,7 +18,7 @@ var/stimulant = TRUE var/detonate_explosion = TRUE var/detonate_dev_range = 0 - var/detonate_heavy_range = 0 + var/detonate_heavy_range = 1 var/detonate_light_range = 2 var/detonate_flash_range = 5 var/detonate_fire_range = 5 @@ -51,7 +51,10 @@ /obj/item/hot_potato/proc/detonate() var/atom/location = loc location.visible_message(span_userdanger("[src] [detonate_explosion? "explodes" : "activates"]!"), span_userdanger("[src] activates! You've ran out of time!")) - if(detonate_explosion) + if(detonate_explosion && isliving(loc)) + var/mob/living/victim_mob = loc + if(victim_mob.is_holding(src)) + victim_mob.gib(DROP_ALL_REMAINS) explosion(src, detonate_dev_range, detonate_heavy_range, detonate_light_range, detonate_fire_range, detonate_flash_range) deactivate() if(!reusable) diff --git a/code/game/objects/items/inducer.dm b/code/game/objects/items/inducer.dm index 0f66cd4b6d108..ea942c4f663b6 100644 --- a/code/game/objects/items/inducer.dm +++ b/code/game/objects/items/inducer.dm @@ -61,8 +61,9 @@ /obj/item/inducer/examine(mob/living/user) . = ..() - if(!QDELETED(powerdevice)) - . += span_notice("Its display shows: [display_energy(powerdevice.charge)].") + var/obj/item/stock_parts/power_store/our_cell = get_cell(src, user) + if(!QDELETED(our_cell)) + . += span_notice("Its display shows: [display_energy(our_cell.charge)].") if(opened) . += span_notice("The cell can be removed with an empty hand.") . += span_notice("Plasma sheets can be used to recharge the cell.") @@ -146,11 +147,13 @@ to_chat(user, span_warning("You don't have the dexterity to use [src]!")) return ITEM_INTERACT_FAILURE - if(QDELETED(powerdevice)) + var/obj/item/stock_parts/power_store/our_cell = get_cell(src, user) + + if(QDELETED(our_cell)) balloon_alert(user, "no cell installed!") return ITEM_INTERACT_FAILURE - if(!powerdevice.charge) + if(!our_cell.charge) balloon_alert(user, "no charge!") return ITEM_INTERACT_FAILURE @@ -173,13 +176,13 @@ break //transfer of charge - var/transferred = min(powerdevice.charge, target_cell.used_charge(), (target_cell.rating_base * target_cell.rating * power_transfer_multiplier)) + var/transferred = min(our_cell.charge, target_cell.used_charge(), (target_cell.rating_base * target_cell.rating * power_transfer_multiplier)) if(!transferred) break - powerdevice.use(target_cell.give(transferred)) + our_cell.use(target_cell.give(transferred)) //update all appearances - powerdevice.update_appearance() + our_cell.update_appearance() target_cell.update_appearance() interacting_with.update_appearance() diff --git a/code/game/objects/items/inspector.dm b/code/game/objects/items/inspector.dm index d4abe4c1d1a5b..7783dcff072b5 100644 --- a/code/game/objects/items/inspector.dm +++ b/code/game/objects/items/inspector.dm @@ -20,7 +20,6 @@ interaction_flags_click = NEED_DEXTERITY throw_range = 1 throw_speed = 1 - COOLDOWN_DECLARE(scanning_person) //Cooldown for scanning a carbon ///How long it takes to print on time each mode, ordered NORMAL, FAST, HONK var/list/time_list = list(5 SECONDS, 1 SECONDS, 0.1 SECONDS) ///Which print time mode we're on. @@ -108,17 +107,8 @@ balloon_alert(user, "check cell!") return ITEM_INTERACT_BLOCKING - if(iscarbon(interacting_with)) //Prevents insta scanning people - if(!COOLDOWN_FINISHED(src, scanning_person)) - return ITEM_INTERACT_BLOCKING - - visible_message(span_warning("[user] starts scanning [interacting_with] with [src]")) - to_chat(interacting_with, span_userdanger("[user] is trying to scan you for contraband!")) - balloon_alert_to_viewers("scanning...") - playsound(src, SFX_INDUSTRIAL_SCAN, 20, TRUE, -2, TRUE, FALSE) - COOLDOWN_START(src, scanning_person, 4 SECONDS) - if(!do_after(user, 4 SECONDS, interacting_with)) - return ITEM_INTERACT_BLOCKING + if(iscarbon(interacting_with)) // Prevents scanning people + return if(contraband_scan(interacting_with, user)) playsound(src, 'sound/machines/uplink/uplinkerror.ogg', 40) diff --git a/code/game/objects/items/robot/robot_upgrades.dm b/code/game/objects/items/robot/robot_upgrades.dm index 3e5cc1eb8d560..b65c4a7ae90df 100644 --- a/code/game/objects/items/robot/robot_upgrades.dm +++ b/code/game/objects/items/robot/robot_upgrades.dm @@ -12,7 +12,7 @@ var/require_model = FALSE var/list/model_type = null /// Bitflags listing model compatibility. Used in the exosuit fabricator for creating sub-categories. - var/list/model_flags = NONE + var/model_flags = NONE /// List of items to add with the module, if any var/list/items_to_add @@ -665,6 +665,9 @@ /obj/item/inducer/cyborg/screwdriver_act(mob/living/user, obj/item/tool) return NONE +/obj/item/inducer/cyborg/item_interaction(mob/living/user, obj/item/tool, list/modifiers) + return ITEM_INTERACT_FAILURE + /obj/item/borg/upgrade/pinpointer name = "medical cyborg crew pinpointer" desc = "A crew pinpointer module for the medical cyborg. Permits remote access to the crew monitor." diff --git a/code/game/objects/items/stacks/golem_food/golem_status_effects.dm b/code/game/objects/items/stacks/golem_food/golem_status_effects.dm index bb6e90187ef38..f8c15a3ba869c 100644 --- a/code/game/objects/items/stacks/golem_food/golem_status_effects.dm +++ b/code/game/objects/items/stacks/golem_food/golem_status_effects.dm @@ -433,7 +433,7 @@ return owner.body_position == LYING_DOWN /datum/status_effect/golem/bananium/on_remove() - owner.remove_traits(owner, list(TRAIT_WADDLING, TRAIT_NO_SLIP_WATER), TRAIT_STATUS_EFFECT(id)) + owner.remove_traits(list(TRAIT_WADDLING, TRAIT_NO_SLIP_WATER), TRAIT_STATUS_EFFECT(id)) QDEL_NULL(slipperiness) return ..() diff --git a/code/game/objects/items/stacks/sheets/mineral.dm b/code/game/objects/items/stacks/sheets/mineral.dm index 0d4393efea6a4..ef3ddb77c0e44 100644 --- a/code/game/objects/items/stacks/sheets/mineral.dm +++ b/code/game/objects/items/stacks/sheets/mineral.dm @@ -41,6 +41,8 @@ GLOBAL_LIST_INIT(sandstone_recipes, list ( \ merge_type = /obj/item/stack/sheet/mineral/sandstone walltype = /turf/closed/wall/mineral/sandstone material_type = /datum/material/sandstone + drop_sound = SFX_STONE_DROP + pickup_sound = SFX_STONE_PICKUP /obj/item/stack/sheet/mineral/sandstone/get_main_recipes() . = ..() diff --git a/code/game/objects/items/stacks/stack.dm b/code/game/objects/items/stacks/stack.dm index fd1529eb3301c..999fbd5608d2b 100644 --- a/code/game/objects/items/stacks/stack.dm +++ b/code/game/objects/items/stacks/stack.dm @@ -591,7 +591,7 @@ return FALSE if(is_cyborg) // No merging cyborg stacks into other stacks return FALSE - if(ismob(loc) && !inhand) // no merging with items that are on the mob + if(ismob(loc) && !inhand && !HAS_TRAIT(loc, TRAIT_MOB_MERGE_STACKS)) // no merging with items that are on the mob return FALSE if(istype(loc, /obj/machinery)) // no merging items in machines that aren't both in componentparts var/obj/machinery/machine = loc diff --git a/code/game/objects/items/stacks/tiles/tile_types.dm b/code/game/objects/items/stacks/tiles/tile_types.dm index d3d3e51490363..20ee0e69df6d7 100644 --- a/code/game/objects/items/stacks/tiles/tile_types.dm +++ b/code/game/objects/items/stacks/tiles/tile_types.dm @@ -336,6 +336,9 @@ /obj/item/stack/tile/carpet/fifty amount = 50 +/obj/item/stack/tile/iron/fifty + amount = 50 + /obj/item/stack/tile/carpet/black/fifty amount = 50 diff --git a/code/game/objects/items/storage/toolbox.dm b/code/game/objects/items/storage/toolbox.dm index 5f08747e60c92..709476e8881a9 100644 --- a/code/game/objects/items/storage/toolbox.dm +++ b/code/game/objects/items/storage/toolbox.dm @@ -273,9 +273,9 @@ new /obj/item/gun_maintenance_supplies(src) new /obj/item/gun_maintenance_supplies(src) -//floorbot assembly +//repairbot assembly /obj/item/storage/toolbox/tool_act(mob/living/user, obj/item/tool, list/modifiers) - if(!istype(tool, /obj/item/stack/tile/iron)) + if(!istype(tool, /obj/item/assembly/prox_sensor)) return ..() var/static/list/allowed_toolbox = list( /obj/item/storage/toolbox/artistic, @@ -290,26 +290,22 @@ if(contents.len >= 1) balloon_alert(user, "not empty!") return ITEM_INTERACT_BLOCKING - if(tool.use(10)) - var/obj/item/bot_assembly/floorbot/B = new - B.toolbox = type - switch(B.toolbox) - if(/obj/item/storage/toolbox) - B.toolbox_color = "r" - if(/obj/item/storage/toolbox/emergency) - B.toolbox_color = "r" - if(/obj/item/storage/toolbox/electrical) - B.toolbox_color = "y" - if(/obj/item/storage/toolbox/artistic) - B.toolbox_color = "g" - if(/obj/item/storage/toolbox/syndicate) - B.toolbox_color = "s" - user.put_in_hands(B) - B.update_appearance() - B.balloon_alert(user, "tiles added") - qdel(src) - return ITEM_INTERACT_BLOCKING - balloon_alert(user, "needs 10 tiles!") + var/static/list/toolbox_colors = list( + /obj/item/storage/toolbox = "#445eb3", + /obj/item/storage/toolbox/emergency = "#445eb3", + /obj/item/storage/toolbox/electrical = "#b77931", + /obj/item/storage/toolbox/artistic = "#378752", + /obj/item/storage/toolbox/syndicate = "#3d3d3d", + ) + var/obj/item/bot_assembly/repairbot/repair = new + repair.toolbox = type + var/new_color = toolbox_colors[type] || "#445eb3" + repair.set_color(new_color) + user.put_in_hands(repair) + repair.update_appearance() + repair.balloon_alert(user, "sensor added!") + qdel(tool) + qdel(src) return ITEM_INTERACT_SUCCESS /obj/item/storage/toolbox/haunted diff --git a/code/game/objects/items/weaponry.dm b/code/game/objects/items/weaponry.dm index fa3aadbae95cf..dc0375ac04bd2 100644 --- a/code/game/objects/items/weaponry.dm +++ b/code/game/objects/items/weaponry.dm @@ -64,7 +64,7 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301 /obj/item/balloon_mallet/examine(mob/user) . = ..() if(HAS_TRAIT(user,TRAIT_BALLOON_SUTRA)) - . = "A sacred weapon of the higher castes from the clown planet, used to strike fear into the hearts of their foes. Wield it with care." + . += "A sacred weapon of the higher castes from the clown planet, used to strike fear into the hearts of their foes. Wield it with care." /obj/item/balloon_mallet/attack(mob/living/target, mob/living/user) playsound(loc, 'sound/mobs/non-humanoids/clown/hehe.ogg', 20) @@ -432,6 +432,42 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301 pain_mult = 0 jostle_pain_mult = 0 +/obj/item/carpenter_hammer + name = "carpenter hammer" + icon = 'icons/obj/weapons/hammer.dmi' + icon_state = "carpenter_hammer" + inhand_icon_state = "carpenter_hammer" + lefthand_file = 'icons/mob/inhands/weapons/hammers_lefthand.dmi' + righthand_file = 'icons/mob/inhands/weapons/hammers_righthand.dmi' + desc = "Uncanny looking hammer." + force = 20 + throwforce = 20 + throw_range = 4 + w_class = WEIGHT_CLASS_NORMAL + wound_bonus = 20 + demolition_mod = 1.25 + +/obj/item/carpenter_hammer/Initialize(mapload) + . = ..() + AddComponent(/datum/component/item_killsound, \ + allowed_mobs = list(/mob/living/carbon/human), \ + killsound = 'sound/items/weapons/hammer_death_scream.ogg', \ + replace_default_death_sound = TRUE, \ + ) + +/obj/item/carpenter_hammer/examine(mob/user) + . = ..() + . += "" + . += "Real World Tip:" + . += pick( + "Every building, from hospitals to homes, has a room that serves as the heart of the building \ + and carries blood and nutrients to its extremities. Try to find the heart of your home!", + "All the food you've tried is rotten. You've never eaten fresh food.", + "Viruses do not exist. Illness is simply your body punishing you for what you have done wrong.", + "Space stations must have at least 50 mammalian teeth embedded in the north walls for structural safety reasons.", + "Queen dragonfly sleeps and smiles.", + ) + /obj/item/switchblade name = "switchblade" icon = 'icons/obj/weapons/sword.dmi' diff --git a/code/game/objects/structures/beds_chairs/chair.dm b/code/game/objects/structures/beds_chairs/chair.dm index 50d06bafef0fd..38aadbb266229 100644 --- a/code/game/objects/structures/beds_chairs/chair.dm +++ b/code/game/objects/structures/beds_chairs/chair.dm @@ -271,11 +271,16 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/structure/chair/stool, 0) return if(!item_chair || has_buckled_mobs()) return + if(flags_1 & HOLOGRAM_1) + to_chat(user, span_notice("You try to pick up \the [src], but it fades away!")) + qdel(src) + return + user.visible_message(span_notice("[user] grabs \the [src.name]."), span_notice("You grab \the [src.name].")) - var/obj/item/C = new item_chair(loc) - C.set_custom_materials(custom_materials) - TransferComponents(C) - user.put_in_hands(C) + var/obj/item/chair_item = new item_chair(loc) + chair_item.set_custom_materials(custom_materials) + TransferComponents(chair_item) + user.put_in_hands(chair_item) qdel(src) /obj/structure/chair/user_buckle_mob(mob/living/M, mob/user, check_loc = TRUE) @@ -344,6 +349,11 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/structure/chair/stool/bar, 0) if(isgroundlessturf(T)) to_chat(user, span_warning("You need ground to plant this on!")) return + if(flags_1 & HOLOGRAM_1) + to_chat(user, span_notice("You try to place down \the [src], but it fades away!")) + qdel(src) + return + for(var/obj/A in T) if(istype(A, /obj/structure/chair)) to_chat(user, span_warning("There is already a chair here!")) @@ -353,10 +363,10 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/structure/chair/stool/bar, 0) return user.visible_message(span_notice("[user] rights \the [src.name]."), span_notice("You right \the [name].")) - var/obj/structure/chair/C = new origin_type(get_turf(loc)) - C.set_custom_materials(custom_materials) - TransferComponents(C) - C.setDir(user.dir) + var/obj/structure/chair/chair = new origin_type(get_turf(loc)) + chair.set_custom_materials(custom_materials) + TransferComponents(chair) + chair.setDir(user.dir) qdel(src) /obj/item/chair/proc/smash(mob/living/user) diff --git a/code/game/objects/structures/cannons/mounted_guns/mounted_gun.dm b/code/game/objects/structures/cannons/mounted_guns/mounted_gun.dm index f0fa9e27d7869..fa49fe0a106d5 100644 --- a/code/game/objects/structures/cannons/mounted_guns/mounted_gun.dm +++ b/code/game/objects/structures/cannons/mounted_guns/mounted_gun.dm @@ -22,7 +22,7 @@ ///Accepted "ammo" type var/obj/item/ammo_type = /obj/item/ammo_casing/strilka310 ///Projectile from said gun. Doesnt automatically inherit said ammo's projectile in case you wanted to make a gun that shoots floor tiles or something. - var/obj/item/projectile_type = /obj/projectile/bullet/strilka310 + var/obj/projectile/projectile_type = /obj/projectile/bullet/strilka310 ///If the gun has anything in it. var/loaded_gun = TRUE ///If the gun is currently loaded with its maximum capacity. diff --git a/code/game/objects/structures/lavaland/ore_vent.dm b/code/game/objects/structures/lavaland/ore_vent.dm index a6933d534689b..1eaff6e93dc7e 100644 --- a/code/game/objects/structures/lavaland/ore_vent.dm +++ b/code/game/objects/structures/lavaland/ore_vent.dm @@ -207,10 +207,10 @@ /** * This confirms that the user wants to start the wave defense event, and that they can start it. */ -/obj/structure/ore_vent/proc/pre_wave_defense(mob/user, spawn_drone = TRUE) +/obj/structure/ore_vent/proc/pre_wave_defense(mob/user, spawn_drone = TRUE, mech_scan = FALSE) if(tgui_alert(user, excavation_warning, "Begin defending ore vent?", list("Yes", "No")) != "Yes") return FALSE - if(!can_interact(user)) + if(!can_interact(user) && !mech_scan) return FALSE if(!COOLDOWN_FINISHED(src, wave_cooldown) || node) return FALSE @@ -337,24 +337,16 @@ * Gives a readout of the ores available in the vent that gets added to the description, * then asks the user if they want to start wave defense if it's already been discovered. * @params user The user who tapped the vent. - * @params scan_only If TRUE, the vent will only scan, and not prompt to start wave defense. Used by the mech mineral scanner. + * @params mech_scan If TRUE, will bypass interaction checks to allow mechs to be able to begin the wave defense. */ -/obj/structure/ore_vent/proc/scan_and_confirm(mob/living/user, scan_only = FALSE) +/obj/structure/ore_vent/proc/scan_and_confirm(mob/living/user, mech_scan = FALSE) if(tapped) balloon_alert_to_viewers("vent tapped!") return if(!COOLDOWN_FINISHED(src, wave_cooldown) || node) //We're already defending the vent, so don't scan it again. - if(!scan_only) - balloon_alert_to_viewers("protect the node drone!") + balloon_alert_to_viewers("protect the node drone!") return if(!discovered) - if(scan_only) - discovered = TRUE - generate_description(user) - balloon_alert_to_viewers("vent scanned!") - AddComponent(/datum/component/gps, name) - return - if(DOING_INTERACTION_WITH_TARGET(user, src)) balloon_alert(user, "already scanning!") return @@ -374,10 +366,8 @@ user_id_card.registered_account.mining_points += (MINER_POINT_MULTIPLIER) user_id_card.registered_account.bank_card_talk("You've been awarded [MINER_POINT_MULTIPLIER] mining points for discovery of an ore vent.") return - if(scan_only) - return - if(!pre_wave_defense(user, spawn_drone_on_tap)) + if(!pre_wave_defense(user, spawn_drone_on_tap, mech_scan)) return start_wave_defense() diff --git a/code/game/objects/structures/maintenance.dm b/code/game/objects/structures/maintenance.dm index d3eb552c46b8b..bf96397507afa 100644 --- a/code/game/objects/structures/maintenance.dm +++ b/code/game/objects/structures/maintenance.dm @@ -80,12 +80,11 @@ at the cost of risking a vicious bite.**/ return if(critter_infested && prob(50) && iscarbon(user)) var/mob/living/carbon/bite_victim = user - var/obj/item/bodypart/affecting = bite_victim.get_bodypart("[(user.active_hand_index % 2 == 0) ? "r" : "l" ]_arm") - to_chat(user, span_danger("You feel a sharp pain as an unseen creature sinks its [pick("fangs", "beak", "proboscis")] into your arm!")) - if(affecting?.receive_damage(30)) - bite_victim.update_damage_overlays() - playsound(src,'sound/items/weapons/bite.ogg', 70, TRUE) - return + var/obj/item/bodypart/affecting = bite_victim.get_active_hand() + to_chat(user, span_danger("You feel a sharp pain as an unseen creature sinks its [pick("fangs", "beak", "proboscis")] into your [affecting.plaintext_zone]!")) + bite_victim.apply_damage(30, BRUTE, affecting) + playsound(src,'sound/items/weapons/bite.ogg', 70, TRUE) + return to_chat(user, span_warning("You find nothing of value...")) /obj/structure/moisture_trap/attackby(obj/item/I, mob/user, params) diff --git a/code/game/objects/structures/mystery_box.dm b/code/game/objects/structures/mystery_box.dm index 0a0c9ca0a1017..3a1844aa2225e 100644 --- a/code/game/objects/structures/mystery_box.dm +++ b/code/game/objects/structures/mystery_box.dm @@ -272,10 +272,10 @@ GLOBAL_LIST_INIT(mystery_fishing, list( /obj/structure/mystery_box/wands/generate_valid_types() valid_types = GLOB.mystery_magic -///One of a kind, rarely found by fishing in the ocean. +///A fishing and pirate-themed mystery box, rarely found by fishing in the ocean, then another cannot be caught for the next 30 minutes. /obj/structure/mystery_box/fishing name = "treasure chest" - desc = "A pirate-y chest that seems equally magial and mysterious, capable of granting the user different pieces of gear." + desc = "A piratey coffer equally magical and mysterious, capable of granting different pieces of gear to whoever opens it." icon_state = "treasure" uses_left = 18 max_integrity = 100 diff --git a/code/game/objects/structures/ore_containers.dm b/code/game/objects/structures/ore_containers.dm index 6bc6f680116f4..75c7a03cfcfa9 100644 --- a/code/game/objects/structures/ore_containers.dm +++ b/code/game/objects/structures/ore_containers.dm @@ -23,25 +23,16 @@ ui.open() /obj/structure/ore_container/ui_data(mob/user) - var/list/data = list() - data["ores"] = list() + var/list/ores = list() for(var/obj/item/stack/ore/ore_item in contents) - data["ores"] += list(list( + ores += list(list( "id" = REF(ore_item), "name" = ore_item.name, "amount" = ore_item.amount, + "icon" = ore_item::icon, + "icon_state" = ore_item::icon_state, )) - return data - -/obj/structure/ore_container/ui_static_data(mob/user) - var/list/data = list() - data["ore_images"] = list() - for(var/obj/item/stack/ore_item as anything in subtypesof(/obj/item/stack/ore)) - data["ore_images"] += list(list( - "name" = initial(ore_item.name), - "icon" = icon2base64(getFlatIcon(image(icon = initial(ore_item.icon), icon_state = initial(ore_item.icon_state)), no_anim=TRUE)) - )) - return data + return list("ores" = ores) /obj/structure/ore_container/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state) . = ..() diff --git a/code/game/objects/structures/spawner.dm b/code/game/objects/structures/spawner.dm index db4981aeac77a..6a0bc3123d1f5 100644 --- a/code/game/objects/structures/spawner.dm +++ b/code/game/objects/structures/spawner.dm @@ -299,5 +299,5 @@ proteon.add_filter("sentient_proteon", 3, list("type" = "outline", "color" = COLOR_CULT_RED, "size" = 2, "alpha" = 40)) /obj/structure/spawner/sentient/proteon_spawner/handle_deconstruct(disassembled) - playsound('sound/effects/hallucinations/veryfar_noise.ogg', 125) + playsound(src, 'sound/effects/hallucinations/veryfar_noise.ogg', 75) visible_message(span_cult_bold("[src] completely falls apart, the screams of the damned reaching a feverous pitch before slowly fading away into nothing.")) diff --git a/code/game/turfs/closed/minerals.dm b/code/game/turfs/closed/minerals.dm index 3a6546f6eaa85..967c13f337220 100644 --- a/code/game/turfs/closed/minerals.dm +++ b/code/game/turfs/closed/minerals.dm @@ -25,7 +25,7 @@ transform = MAP_SWITCH(TRANSLATE_MATRIX(-4, -4), matrix()) temperature = TCMB - var/turf/open/floor/plating/turf_type = /turf/open/misc/asteroid/airless + var/turf/turf_type = /turf/open/misc/asteroid/airless /// The path of the ore stack we spawn when we're mined. var/obj/item/stack/ore/mineralType = null /// If we spawn a boulder like on the gulag, we use this in lou of mineralType diff --git a/code/game/turfs/open/ashplanet.dm b/code/game/turfs/open/ashplanet.dm index 31369a2e5cec8..e6703c04eb559 100644 --- a/code/game/turfs/open/ashplanet.dm +++ b/code/game/turfs/open/ashplanet.dm @@ -69,3 +69,6 @@ /turf/open/misc/ashplanet/wateryrock/Initialize(mapload) icon_state = "[icon_state][rand(1, 9)]" . = ..() + +/turf/open/misc/ashplanet/wateryrock/lavaland_atmos + initial_gas_mix = LAVALAND_DEFAULT_ATMOS diff --git a/code/game/turfs/open/water.dm b/code/game/turfs/open/water.dm index af1d06056b012..f970b22c74995 100644 --- a/code/game/turfs/open/water.dm +++ b/code/game/turfs/open/water.dm @@ -167,3 +167,6 @@ living.add_mood_event("hot_spring", /datum/mood_event/hot_spring_left) else living.add_mood_event("hot_spring", /datum/mood_event/hot_spring_hater_left) + +/turf/open/water/hot_spring/lavaland_atmos + initial_gas_mix = LAVALAND_DEFAULT_ATMOS diff --git a/code/game/world.dm b/code/game/world.dm index fe55b3963b504..7d261def6dec3 100644 --- a/code/game/world.dm +++ b/code/game/world.dm @@ -8,6 +8,13 @@ GLOBAL_VAR(restart_counter) GLOBAL_VAR(tracy_log) +GLOBAL_PROTECT(tracy_log) +GLOBAL_VAR(tracy_initialized) +GLOBAL_PROTECT(tracy_initialized) +GLOBAL_VAR(tracy_init_error) +GLOBAL_PROTECT(tracy_init_error) +GLOBAL_VAR(tracy_init_reason) +GLOBAL_PROTECT(tracy_init_reason) /** * WORLD INITIALIZATION @@ -66,15 +73,30 @@ GLOBAL_VAR(tracy_log) /world/proc/Genesis(tracy_initialized = FALSE) RETURN_TYPE(/datum/controller/master) + if(!tracy_initialized) + GLOB.tracy_initialized = FALSE +#ifndef OPENDREAM + if(!tracy_initialized) #ifdef USE_BYOND_TRACY #warn USE_BYOND_TRACY is enabled - if(!tracy_initialized) + var/should_init_tracy = TRUE + GLOB.tracy_init_reason = "USE_BYOND_TRACY defined" #else - if(!tracy_initialized && (USE_TRACY_PARAMETER in params)) + var/should_init_tracy = FALSE + if(USE_TRACY_PARAMETER in params) + should_init_tracy = TRUE + GLOB.tracy_init_reason = "world.params" + if(fexists(TRACY_ENABLE_PATH)) + GLOB.tracy_init_reason ||= "enabled for round" + SEND_TEXT(world.log, "[TRACY_ENABLE_PATH] exists, initializing byond-tracy!") + should_init_tracy = TRUE + fdel(TRACY_ENABLE_PATH) +#endif + if(should_init_tracy) + init_byond_tracy() + Genesis(tracy_initialized = TRUE) + return #endif - GLOB.tracy_log = init_byond_tracy() - Genesis(tracy_initialized = TRUE) - return Profile(PROFILE_RESTART) Profile(PROFILE_RESTART, type = "sendmaps") @@ -331,6 +353,7 @@ GLOBAL_VAR(tracy_log) if(do_hard_reboot) log_world("World hard rebooted at [time_stamp()]") shutdown_logging() // See comment below. + shutdown_byond_tracy() auxcleanup() TgsEndProcess() return ..() @@ -338,6 +361,7 @@ GLOBAL_VAR(tracy_log) log_world("World rebooted at [time_stamp()]") shutdown_logging() // Past this point, no logging procs can be used, at risk of data loss. + shutdown_byond_tracy() auxcleanup() TgsReboot() // TGS can decide to kill us right here, so it's important to do it last @@ -351,6 +375,7 @@ GLOBAL_VAR(tracy_log) call_ext(debug_server, "auxtools_shutdown")() /world/Del() + shutdown_byond_tracy() auxcleanup() . = ..() @@ -483,21 +508,31 @@ GLOBAL_VAR(tracy_log) DREAMLUAU_SET_EXECUTION_LIMIT_MILLIS(tick_lag * 100) /world/proc/init_byond_tracy() - var/library - - switch (system_type) - if (MS_WINDOWS) - library = "prof.dll" - if (UNIX) - library = "libprof.so" - else - CRASH("Unsupported platform: [system_type]") + if(!fexists(TRACY_DLL_PATH)) + SEND_TEXT(world.log, "Error initializing byond-tracy: [TRACY_DLL_PATH] not found!") + CRASH("Error initializing byond-tracy: [TRACY_DLL_PATH] not found!") - var/init_result = call_ext(library, "init")("block") + var/init_result = call_ext(TRACY_DLL_PATH, "init")("block") if(length(init_result) != 0 && init_result[1] == ".") // if first character is ., then it returned the output filename - return init_result + SEND_TEXT(world.log, "byond-tracy initialized (logfile: [init_result])") + GLOB.tracy_initialized = TRUE + return GLOB.tracy_log = init_result + else if(init_result == "already initialized") // not gonna question it. + GLOB.tracy_initialized = TRUE + SEND_TEXT(world.log, "byond-tracy already initialized ([GLOB.tracy_log ? "logfile: [GLOB.tracy_log]" : "no logfile"])") else if(init_result != "0") + GLOB.tracy_init_error = init_result + SEND_TEXT(world.log, "Error initializing byond-tracy: [init_result]") CRASH("Error initializing byond-tracy: [init_result]") + else + GLOB.tracy_initialized = TRUE + SEND_TEXT(world.log, "byond-tracy initialized (no logfile)") + +/world/proc/shutdown_byond_tracy() + if(GLOB.tracy_initialized) + SEND_TEXT(world.log, "Shutting down byond-tracy") + GLOB.tracy_initialized = FALSE + call_ext(TRACY_DLL_PATH, "destroy")() /world/proc/init_debugger() var/dll = GetConfig("env", "AUXTOOLS_DEBUG_DLL") diff --git a/code/modules/admin/IsBanned.dm b/code/modules/admin/IsBanned.dm index 52c9c65e5b917..f98520bb84a69 100644 --- a/code/modules/admin/IsBanned.dm +++ b/code/modules/admin/IsBanned.dm @@ -214,7 +214,7 @@ if (ban["fromdb"]) if(SSdbcore.Connect()) - INVOKE_ASYNC(SSdbcore, /datum/controller/subsystem/dbcore/proc.QuerySelect, list( + INVOKE_ASYNC(SSdbcore, TYPE_PROC_REF(/datum/controller/subsystem/dbcore, QuerySelect), list( SSdbcore.NewQuery( "INSERT INTO [format_table_name("stickyban_matched_ckey")] (matched_ckey, stickyban) VALUES (:ckey, :bannedckey) ON DUPLICATE KEY UPDATE last_matched = now()", list("ckey" = ckey, "bannedckey" = bannedckey) diff --git a/code/modules/admin/verbs/SDQL2/SDQL_2_wrappers.dm b/code/modules/admin/verbs/SDQL2/SDQL_2_wrappers.dm index 4da97d2c447bf..1305e5a660d6e 100644 --- a/code/modules/admin/verbs/SDQL2/SDQL_2_wrappers.dm +++ b/code/modules/admin/verbs/SDQL2/SDQL_2_wrappers.dm @@ -117,9 +117,6 @@ /proc/_text2num(T) return text2num(T) -/proc/_trimtext(Text) - return trimtext(Text) - /proc/_ohearers(Dist, Center = usr) return ohearers(Dist, Center) diff --git a/code/modules/admin/verbs/admin_newscaster.dm b/code/modules/admin/verbs/admin_newscaster.dm index b1be5560d69d9..7cac42e0b998e 100644 --- a/code/modules/admin/verbs/admin_newscaster.dm +++ b/code/modules/admin/verbs/admin_newscaster.dm @@ -128,7 +128,7 @@ ADMIN_VERB(access_news_network, R_ADMIN, "Access Newscaster Network", "Allows yo data["channelLocked"] = current_channel.locked data["channelCensored"] = current_channel.censored - //We send all the information about all channels and all messages in existance. + //We send all the information about all channels and all messages in existence. data["channels"] = channel_list data["messages"] = message_list data["wanted"] = wanted_info diff --git a/code/modules/admin/verbs/adminpm.dm b/code/modules/admin/verbs/adminpm.dm index 834e4741cdecf..abbcbb62ab648 100644 --- a/code/modules/admin/verbs/adminpm.dm +++ b/code/modules/admin/verbs/adminpm.dm @@ -502,7 +502,7 @@ ADMIN_VERB(cmd_admin_pm_panel, R_NONE, "Admin PM", "Show a list of clients to PM return TRUE -/// Notifies all admins about the existance of an admin pm, then logs the pm +/// Notifies all admins about the existence of an admin pm, then logs the pm /// message_target here can be either [EXTERNAL_PM_USER], indicating that this message is intended for some external chat channel /// or a /client, in which case we send in the standard form /// log_message is the raw message to send, it will be filtered and treated to ensure we do not break any text handling diff --git a/code/modules/admin/verbs/debug.dm b/code/modules/admin/verbs/debug.dm index b6c5e10ca1d81..13f1995c9ba3d 100644 --- a/code/modules/admin/verbs/debug.dm +++ b/code/modules/admin/verbs/debug.dm @@ -852,3 +852,42 @@ ADMIN_VERB(check_missing_sprites, R_DEBUG, "Debug Worn Item Sprites", "We're can actual_file_name = 'icons/mob/clothing/belt_mirror.dmi' if(!(sprite.icon_state in icon_states(actual_file_name))) to_chat(user, span_warning("ERROR sprites for [sprite.type]. Suit Storage slot."), confidential = TRUE) + +#ifndef OPENDREAM +ADMIN_VERB(start_tracy, R_DEBUG, "Run Tracy Now", "Start running the byond-tracy profiler immediately", ADMIN_CATEGORY_DEBUG) + if(GLOB.tracy_initialized) + to_chat(user, span_warning("byond-tracy is already running!"), avoid_highlighting = TRUE, type = MESSAGE_TYPE_DEBUG, confidential = TRUE) + return + else if(GLOB.tracy_init_error) + to_chat(user, span_danger("byond-tracy failed to initialize during an earlier attempt: [GLOB.tracy_init_error]"), avoid_highlighting = TRUE, type = MESSAGE_TYPE_DEBUG, confidential = TRUE) + return + message_admins(span_adminnotice("[key_name_admin(user)] is trying to start the byond-tracy profiler.")) + log_admin("[key_name(user)] is trying to start the byond-tracy profiler.") + GLOB.tracy_initialized = FALSE + GLOB.tracy_init_reason = "[user.ckey]" + world.init_byond_tracy() + if(GLOB.tracy_init_error) + to_chat(user, span_danger("byond-tracy failed to initialize: [GLOB.tracy_init_error]"), avoid_highlighting = TRUE, type = MESSAGE_TYPE_DEBUG, confidential = TRUE) + message_admins(span_adminnotice("[key_name_admin(user)] tried to start the byond-tracy profiler, but it failed to initialize ([GLOB.tracy_init_error])")) + log_admin("[key_name(user)] tried to start the byond-tracy profiler, but it failed to initialize ([GLOB.tracy_init_error])") + return + to_chat(user, span_notice("byond-tracy successfully started!"), avoid_highlighting = TRUE, type = MESSAGE_TYPE_DEBUG, confidential = TRUE) + message_admins(span_adminnotice("[key_name_admin(user)] started the byond-tracy profiler.")) + log_admin("[key_name(user)] started the byond-tracy profiler.") + if(GLOB.tracy_log) + rustg_file_write("[GLOB.tracy_log]", "[GLOB.log_directory]/tracy.loc") + +ADMIN_VERB_CUSTOM_EXIST_CHECK(start_tracy) + return CONFIG_GET(flag/allow_tracy_start) && fexists(TRACY_DLL_PATH) + +ADMIN_VERB(queue_tracy, R_DEBUG, "Toggle Tracy Next Round", "Toggle running the byond-tracy profiler next round", ADMIN_CATEGORY_DEBUG) + if(fexists(TRACY_ENABLE_PATH)) + fdel(TRACY_ENABLE_PATH) + else + rustg_file_write("[user.ckey]", TRACY_ENABLE_PATH) + message_admins(span_adminnotice("[key_name_admin(user)] [fexists(TRACY_ENABLE_PATH) ? "enabled" : "disabled"] the byond-tracy profiler for next round.")) + log_admin("[key_name(user)] [fexists(TRACY_ENABLE_PATH) ? "enabled" : "disabled"] the byond-tracy profiler for next round.") + +ADMIN_VERB_CUSTOM_EXIST_CHECK(queue_tracy) + return CONFIG_GET(flag/allow_tracy_queue) && fexists(TRACY_DLL_PATH) +#endif diff --git a/code/modules/admin/verbs/ert.dm b/code/modules/admin/verbs/ert.dm index 71722eb6d64ab..09903e7642978 100644 --- a/code/modules/admin/verbs/ert.dm +++ b/code/modules/admin/verbs/ert.dm @@ -157,7 +157,7 @@ spawn_turfs += get_turf(spawner) if(!brief_spawn) - brief_spawn = locate(/obj/effect/landmark/ert_shuttle_brief_spawn) in affected_turf + brief_spawn = get_turf(locate(/obj/effect/landmark/ert_shuttle_brief_spawn) in affected_turf) if(!length(spawn_turfs)) stack_trace("ERT shuttle loaded but found no spawnpoints, placing the ERT at wherever inside the shuttle instead.") @@ -206,7 +206,7 @@ candidate_living_exps = sort_list(candidate_living_exps, cmp=/proc/cmp_numeric_dsc) if(candidate_living_exps.len > ERT_EXPERIENCED_LEADER_CHOOSE_TOP) - candidate_living_exps = candidate_living_exps.Cut(ERT_EXPERIENCED_LEADER_CHOOSE_TOP+1) // pick from the top ERT_EXPERIENCED_LEADER_CHOOSE_TOP contenders in playtime + candidate_living_exps.Cut(ERT_EXPERIENCED_LEADER_CHOOSE_TOP+1) // pick from the top ERT_EXPERIENCED_LEADER_CHOOSE_TOP contenders in playtime earmarked_leader = pick(candidate_living_exps) else earmarked_leader = pick(candidates) diff --git a/code/modules/admin/view_variables/admin_delete.dm b/code/modules/admin/view_variables/admin_delete.dm index 5ef04b351cce3..b9a11b50e6547 100644 --- a/code/modules/admin/view_variables/admin_delete.dm +++ b/code/modules/admin/view_variables/admin_delete.dm @@ -16,6 +16,7 @@ log_admin("[key_name(usr)] deleted [D] [coords]") message_admins("[key_name_admin(usr)] deleted [D] [jmp_coords]") BLACKBOX_LOG_ADMIN_VERB("Delete") + SEND_SIGNAL(D, COMSIG_ADMIN_DELETING, src) if(isturf(D)) var/turf/T = D T.ScrapeAway() diff --git a/code/modules/antagonists/changeling/powers/absorb.dm b/code/modules/antagonists/changeling/powers/absorb.dm index 71b1509ec816c..167371b4d675d 100644 --- a/code/modules/antagonists/changeling/powers/absorb.dm +++ b/code/modules/antagonists/changeling/powers/absorb.dm @@ -106,12 +106,12 @@ var/list/recent_speech = target.copy_recent_speech() if(recent_speech.len) - changeling.antag_memory += "Some of [target]'s speech patterns, we should study these to better impersonate [target.p_them()]!
" + changeling.antag_memory += "Some of [target]'s speech patterns, we should study these to better impersonate [target.p_them()]: " to_chat(owner, span_boldnotice("Some of [target]'s speech patterns, we should study these to better impersonate [target.p_them()]!")) for(var/spoken_memory in recent_speech) - changeling.antag_memory += "\"[spoken_memory]\"
" + changeling.antag_memory += " \"[spoken_memory]\"" to_chat(owner, span_notice("\"[spoken_memory]\"")) - changeling.antag_memory += "We have no more knowledge of [target]'s speech patterns.
" + changeling.antag_memory += ". We have no more knowledge of [target]'s speech patterns. " to_chat(owner, span_boldnotice("We have no more knowledge of [target]'s speech patterns.")) diff --git a/code/modules/antagonists/changeling/powers/mutations.dm b/code/modules/antagonists/changeling/powers/mutations.dm index 158b32df216f0..874141237a983 100644 --- a/code/modules/antagonists/changeling/powers/mutations.dm +++ b/code/modules/antagonists/changeling/powers/mutations.dm @@ -71,7 +71,7 @@ if(HAS_TRAIT_FROM_ONLY(user, TRAIT_PARALYSIS_L_ARM, CHANGELING_TRAIT) || HAS_TRAIT_FROM_ONLY(user, TRAIT_PARALYSIS_R_ARM, CHANGELING_TRAIT)) user.balloon_alert(user, "not enough muscle!") // no cheesing repuprosed glands return - if(user.active_hand_index % 2 == 0) //we regen the arm before changing it into the weapon + if(IS_RIGHT_INDEX(user.active_hand_index)) //we regen the arm before changing it into the weapon limb_regen = user.regenerate_limb(BODY_ZONE_R_ARM, 1) else limb_regen = user.regenerate_limb(BODY_ZONE_L_ARM, 1) diff --git a/code/modules/antagonists/cult/cult_turf_overlay.dm b/code/modules/antagonists/cult/cult_turf_overlay.dm index df92d7aec90f0..e5e70bac1f722 100644 --- a/code/modules/antagonists/cult/cult_turf_overlay.dm +++ b/code/modules/antagonists/cult/cult_turf_overlay.dm @@ -10,7 +10,8 @@ /obj/effect/cult_turf/examine(mob/user) if(linked) - linked.examine(user) + return linked.examine(user) + return list() /obj/effect/cult_turf/singularity_act() return diff --git a/code/modules/antagonists/heretic/heretic_antag.dm b/code/modules/antagonists/heretic/heretic_antag.dm index 9063760c5bcdc..fe7a6f1b125b4 100644 --- a/code/modules/antagonists/heretic/heretic_antag.dm +++ b/code/modules/antagonists/heretic/heretic_antag.dm @@ -93,9 +93,9 @@ //if the knowledge is a spell, use the spell's button else if(ispath(knowledge,/datum/heretic_knowledge/spell)) var/datum/heretic_knowledge/spell/spell_knowledge = knowledge - var/datum/action/cooldown/spell/result_spell = spell_knowledge.spell_to_add - icon_path = result_spell.button_icon - icon_state = result_spell.button_icon_state + var/datum/action/result_action = spell_knowledge.action_to_add + icon_path = result_action.button_icon + icon_state = result_action.button_icon_state //if the knowledge is a summon, use the mob sprite else if(ispath(knowledge,/datum/heretic_knowledge/summon)) diff --git a/code/modules/antagonists/heretic/heretic_knowledge.dm b/code/modules/antagonists/heretic/heretic_knowledge.dm index d4fdf79dfbb59..0e445c862f495 100644 --- a/code/modules/antagonists/heretic/heretic_knowledge.dm +++ b/code/modules/antagonists/heretic/heretic_knowledge.dm @@ -187,26 +187,26 @@ /datum/heretic_knowledge/spell abstract_parent_type = /datum/heretic_knowledge/spell /// Spell path we add to the heretic. Type-path. - var/datum/action/cooldown/spell/spell_to_add + var/datum/action/action_to_add /// The spell we actually created. - var/datum/weakref/created_spell_ref + var/datum/weakref/created_action_ref /datum/heretic_knowledge/spell/Destroy() - QDEL_NULL(created_spell_ref) + QDEL_NULL(created_action_ref) return ..() /datum/heretic_knowledge/spell/on_gain(mob/user, datum/antagonist/heretic/our_heretic) // Added spells are tracked on the body, and not the mind, // because we handle heretic mind transfers // via the antag datum (on_gain and on_lose). - var/datum/action/cooldown/spell/created_spell = created_spell_ref?.resolve() || new spell_to_add(user) - created_spell.Grant(user) - created_spell_ref = WEAKREF(created_spell) + var/datum/action/created_action = created_action_ref?.resolve() || new action_to_add(user) + created_action.Grant(user) + created_action_ref = WEAKREF(created_action) /datum/heretic_knowledge/spell/on_lose(mob/user, datum/antagonist/heretic/our_heretic) - var/datum/action/cooldown/spell/created_spell = created_spell_ref?.resolve() - if(created_spell?.owner == user) - created_spell.Remove(user) + var/datum/action/cooldown/spell/created_action = created_action_ref?.resolve() + if(created_action?.owner == user) + created_action.Remove(user) /** * A knowledge subtype for knowledge that can only diff --git a/code/modules/antagonists/heretic/heretic_living_heart.dm b/code/modules/antagonists/heretic/heretic_living_heart.dm index 3e8f39fef4f94..81d7e1224575c 100644 --- a/code/modules/antagonists/heretic/heretic_living_heart.dm +++ b/code/modules/antagonists/heretic/heretic_living_heart.dm @@ -80,6 +80,8 @@ var/last_tracked_name /// Whether the target radial is currently opened. var/radial_open = FALSE + /// Navigator to our target that we have. + var/datum/status_effect/agent_pinpointer/scan/heretic/heretic_pinpointer /datum/action/cooldown/track_target/Grant(mob/granted) if(!IS_HERETIC(granted)) @@ -144,6 +146,7 @@ playsound(owner, 'sound/effects/singlebeat.ogg', 50, TRUE, SILENCED_SOUND_EXTRARANGE) owner.balloon_alert(owner, get_balloon_message(tracked_mob)) + // Let them know how to sacrifice people if they're able to be sac'd if(tracked_mob.stat == DEAD) to_chat(owner, span_hierophant("[tracked_mob] is dead. Bring them to a transmutation rune \ @@ -152,6 +155,26 @@ StartCooldown() return TRUE +/datum/action/cooldown/track_target/proc/make_navigate_arrow(turf/tracked_turf, arrow_color) + var/datum/hud/user_hud = owner.hud_used + if(!user_hud) + return + var/atom/movable/screen/heretic_arrow/arrow = new /atom/movable/screen/heretic_arrow(null, user_hud) + animate(arrow, transform = matrix(dir2angle(get_dir(owner, tracked_turf)), MATRIX_ROTATE), 0.2 SECONDS) + arrow.screen_loc = around_player + arrow.color = arrow_color + user_hud.infodisplay += arrow + user_hud.show_hud(user_hud.hud_version) + addtimer(CALLBACK(src, PROC_REF(end_effect), user_hud, arrow), 1.6 SECONDS) + +/datum/action/cooldown/track_target/proc/end_effect(datum/hud/user_hud, atom/movable/screen/heretic_arrow/arrow) + arrow.icon_state = "heretic_arrow_disappear" + addtimer(CALLBACK(src, PROC_REF(null_arrow), user_hud, arrow), 0.4 SECONDS) + +/datum/action/cooldown/track_target/proc/null_arrow(datum/hud/user_hud, atom/movable/screen/heretic_arrow/arrow) + user_hud.infodisplay -= arrow + user_hud.show_hud(user_hud.hud_version) + /// Callback for the radial to ensure it's closed when not allowed. /datum/action/cooldown/track_target/proc/check_menu() if(QDELETED(src)) @@ -204,17 +227,32 @@ var/dist = get_dist(our_turf, their_turf) var/dir = get_dir(our_turf, their_turf) + var/arrow_color + switch(dist) if(0 to 15) balloon_message = "very near, [dir2text(dir)]!" + arrow_color = COLOR_GREEN if(16 to 31) balloon_message = "near, [dir2text(dir)]!" + arrow_color = COLOR_YELLOW if(32 to 127) balloon_message = "far, [dir2text(dir)]!" + arrow_color = COLOR_ORANGE else balloon_message = "very far!" + arrow_color = COLOR_RED + + make_navigate_arrow(their_turf, arrow_color) if(tracked_mob.stat == DEAD) balloon_message = "they're dead, " + balloon_message return balloon_message + +/atom/movable/screen/heretic_arrow + icon = 'icons/effects/96x96.dmi' + name = "heretic arrow" + icon_state = "heretic_arrow_appear" + pixel_x = -32 + pixel_y = -32 diff --git a/code/modules/antagonists/heretic/influences.dm b/code/modules/antagonists/heretic/influences.dm index 7b316d6cdb984..494a8d30521b9 100644 --- a/code/modules/antagonists/heretic/influences.dm +++ b/code/modules/antagonists/heretic/influences.dm @@ -114,7 +114,7 @@ their_poor_arm.dismember() qdel(their_poor_arm) else - to_chat(human_user,span_danger("You pull your hand away from the hole as the eldritch energy flails, trying to latch onto existance itself!")) + to_chat(human_user,span_danger("You pull your hand away from the hole as the eldritch energy flails, trying to latch onto existence itself!")) return TRUE /obj/effect/visible_heretic_influence/attack_tk(mob/user) diff --git a/code/modules/antagonists/heretic/knife_effect.dm b/code/modules/antagonists/heretic/knife_effect.dm index 1bd44921cf957..e11fd79ab9f75 100644 --- a/code/modules/antagonists/heretic/knife_effect.dm +++ b/code/modules/antagonists/heretic/knife_effect.dm @@ -12,3 +12,7 @@ AddElement(/datum/element/movetype_handler) ADD_TRAIT(src, TRAIT_MOVE_FLYING, INNATE_TRAIT) add_filter("dio_knife", 2, list("type" = "outline", "color" = glow_color, "size" = 1)) + +/obj/effect/floating_blade/haunted + icon = 'icons/obj/weapons/khopesh.dmi' + icon_state = "render" diff --git a/code/modules/antagonists/heretic/knowledge/ash_lore.dm b/code/modules/antagonists/heretic/knowledge/ash_lore.dm index 61056d4210f40..3b5b80a621461 100644 --- a/code/modules/antagonists/heretic/knowledge/ash_lore.dm +++ b/code/modules/antagonists/heretic/knowledge/ash_lore.dm @@ -63,7 +63,7 @@ desc = "Grants you Ashen Passage, a spell that lets you phase out of reality and traverse a short distance, passing though any walls." gain_text = "He knew how to walk between the planes." - spell_to_add = /datum/action/cooldown/spell/jaunt/ethereal_jaunt/ash + action_to_add = /datum/action/cooldown/spell/jaunt/ethereal_jaunt/ash cost = 1 @@ -99,7 +99,7 @@ at a nearby enemy, setting them on fire and burning them. If they do not extinguish themselves, \ the beam will continue to another target." gain_text = "No fire was hot enough to rekindle them. No fire was bright enough to save them. No fire is eternal." - spell_to_add = /datum/action/cooldown/spell/charged/beam/fire_blast + action_to_add = /datum/action/cooldown/spell/charged/beam/fire_blast cost = 1 research_tree_icon_frame = 7 @@ -145,7 +145,7 @@ If any victims afflicted are in critical condition, they will also instantly die." gain_text = "The fire was inescapable, and yet, life remained in his charred body. \ The Nightwatcher was a particular man, always watching." - spell_to_add = /datum/action/cooldown/spell/aoe/fiery_rebirth + action_to_add = /datum/action/cooldown/spell/aoe/fiery_rebirth cost = 1 research_tree_icon_frame = 5 diff --git a/code/modules/antagonists/heretic/knowledge/blade_lore.dm b/code/modules/antagonists/heretic/knowledge/blade_lore.dm index 5cffc7bc304f2..dcca07b00af70 100644 --- a/code/modules/antagonists/heretic/knowledge/blade_lore.dm +++ b/code/modules/antagonists/heretic/knowledge/blade_lore.dm @@ -185,7 +185,7 @@ During this process, you will rapidly regenerate stamina and quickly recover from stuns, however, you will be unable to attack. \ This spell can be cast in rapid succession, but doing so will increase the cooldown." gain_text = "In the flurry of death, he found peace within himself. Despite insurmountable odds, he forged on." - spell_to_add = /datum/action/cooldown/spell/realignment + action_to_add = /datum/action/cooldown/spell/realignment cost = 1 @@ -364,7 +364,7 @@ at a target, dealing damage and causing bleeding." gain_text = "Without thinking, I took the knife of a fallen soldier and threw with all my might. My aim was true! \ The Torn Champion smiled at their first taste of agony, and with a nod, their blades became my own." - spell_to_add = /datum/action/cooldown/spell/pointed/projectile/furious_steel + action_to_add = /datum/action/cooldown/spell/pointed/projectile/furious_steel cost = 1 /datum/heretic_knowledge/ultimate/blade_final diff --git a/code/modules/antagonists/heretic/knowledge/cosmic_lore.dm b/code/modules/antagonists/heretic/knowledge/cosmic_lore.dm index 6a895a7ffdfd2..90fe514cde946 100644 --- a/code/modules/antagonists/heretic/knowledge/cosmic_lore.dm +++ b/code/modules/antagonists/heretic/knowledge/cosmic_lore.dm @@ -62,7 +62,7 @@ However, people with a star mark will get transported along with another person using the rune." gain_text = "The distant stars crept into my dreams, roaring and screaming without reason. \ I spoke, and heard my own words echoed back." - spell_to_add = /datum/action/cooldown/spell/cosmic_rune + action_to_add = /datum/action/cooldown/spell/cosmic_rune cost = 1 @@ -86,7 +86,7 @@ The beam lasts a minute, until the beam is obstructed or until a new target has been found." gain_text = "After waking in a cold sweat I felt a palm on my scalp, a sigil burned onto me. \ My veins now emitted a strange purple glow, the Beast knows I will surpass its expectations." - spell_to_add = /datum/action/cooldown/spell/touch/star_touch + action_to_add = /datum/action/cooldown/spell/touch/star_touch cost = 1 /datum/heretic_knowledge/spell/star_blast @@ -94,7 +94,7 @@ desc = "Fires a projectile that moves very slowly, raising a short-lived wall of cosmic fields where it goes. \ Anyone hit by the projectile will receive burn damage, a knockdown, and give people in a three tile range a star mark." gain_text = "The Beast was behind me now at all times, with each sacrifice words of affirmation coursed through me." - spell_to_add = /datum/action/cooldown/spell/pointed/projectile/star_blast + action_to_add = /datum/action/cooldown/spell/pointed/projectile/star_blast cost = 1 /datum/heretic_knowledge/blade_upgrade/cosmic @@ -199,7 +199,7 @@ desc = "Grants you Cosmic Expansion, a spell that creates a 3x3 area of cosmic fields around you. \ Nearby beings will also receive a star mark." gain_text = "The ground now shook beneath me. The Beast inhabited me, and their voice was intoxicating." - spell_to_add = /datum/action/cooldown/spell/conjure/cosmic_expansion + action_to_add = /datum/action/cooldown/spell/conjure/cosmic_expansion cost = 1 /datum/heretic_knowledge/ultimate/cosmic_final diff --git a/code/modules/antagonists/heretic/knowledge/flesh_lore.dm b/code/modules/antagonists/heretic/knowledge/flesh_lore.dm index 976ce2ae7ba4e..57e60c46b6367 100644 --- a/code/modules/antagonists/heretic/knowledge/flesh_lore.dm +++ b/code/modules/antagonists/heretic/knowledge/flesh_lore.dm @@ -214,7 +214,7 @@ This spell also allows you to heal your minions and summons, or restore failing organs to acceptable status." gain_text = "But they were not out of my reach for long. With every step, the screams grew, until at last \ I learned that they could be silenced." - spell_to_add = /datum/action/cooldown/spell/touch/flesh_surgery + action_to_add = /datum/action/cooldown/spell/touch/flesh_surgery cost = 1 /datum/heretic_knowledge/summon/raw_prophet diff --git a/code/modules/antagonists/heretic/knowledge/lock_lore.dm b/code/modules/antagonists/heretic/knowledge/lock_lore.dm index 28e02112fd70e..6333e9a8fa4fc 100644 --- a/code/modules/antagonists/heretic/knowledge/lock_lore.dm +++ b/code/modules/antagonists/heretic/knowledge/lock_lore.dm @@ -136,7 +136,7 @@ that puts a random item from the victims backpack into your hand." gain_text = "Consorting with Burglar spirits is frowned upon, but a Steward will always want to learn about new doors." - spell_to_add = /datum/action/cooldown/spell/pointed/burglar_finesse + action_to_add = /datum/action/cooldown/spell/pointed/burglar_finesse cost = 1 /datum/heretic_knowledge/blade_upgrade/flesh/lock //basically a chance-based weeping avulsion version of the former @@ -158,7 +158,7 @@ While in refuge, you cannot use your hands or spells, and you are immune to slowdown. \ You are invincible but unable to harm anything. Cancelled by being hit with an anti-magic item." gain_text = "Jealously, the Guard and the Hound hunted me. But I unlocked my form, and was but a haze, untouchable." - spell_to_add = /datum/action/cooldown/spell/caretaker + action_to_add = /datum/action/cooldown/spell/caretaker cost = 1 /datum/heretic_knowledge/ultimate/lock_final diff --git a/code/modules/antagonists/heretic/knowledge/moon_lore.dm b/code/modules/antagonists/heretic/knowledge/moon_lore.dm index 2ab75e96c5a78..9628305f50b46 100644 --- a/code/modules/antagonists/heretic/knowledge/moon_lore.dm +++ b/code/modules/antagonists/heretic/knowledge/moon_lore.dm @@ -32,7 +32,7 @@ research_tree_icon_state = "moon_blade" /datum/heretic_knowledge/limited_amount/starting/base_moon/on_gain(mob/user, datum/antagonist/heretic/our_heretic) - add_traits(user ,TRAIT_EMPATH, REF(src)) + ADD_TRAIT(user, TRAIT_EMPATH, REF(src)) /datum/heretic_knowledge/moon_grasp name = "Grasp of Lunacy" @@ -70,7 +70,7 @@ duration based on their sanity." gain_text = "The moon smiles upon us all and those who see its true side can bring its joy." - spell_to_add = /datum/action/cooldown/spell/pointed/moon_smile + action_to_add = /datum/action/cooldown/spell/pointed/moon_smile cost = 1 /datum/heretic_knowledge/mark/moon_mark @@ -89,7 +89,7 @@ desc = "Grants you Lunar Parade, a spell that - after a short charge - sends a carnival forward \ when hitting someone they are forced to join the parade and suffer hallucinations." gain_text = "The music like a reflection of the soul compelled them, like moths to a flame they followed" - spell_to_add = /datum/action/cooldown/spell/pointed/projectile/moon_parade + action_to_add = /datum/action/cooldown/spell/pointed/projectile/moon_parade cost = 1 /datum/heretic_knowledge/moon_amulet @@ -144,7 +144,7 @@ gain_text = "I grabbed his hand and we rose, those who saw the truth rose with us. \ The ringleader pointed up and the dim light of truth illuminated us further." - spell_to_add = /datum/action/cooldown/spell/aoe/moon_ringleader + action_to_add = /datum/action/cooldown/spell/aoe/moon_ringleader cost = 1 diff --git a/code/modules/antagonists/heretic/knowledge/rust_lore.dm b/code/modules/antagonists/heretic/knowledge/rust_lore.dm index a2f0a91e69a06..f624767f33e82 100644 --- a/code/modules/antagonists/heretic/knowledge/rust_lore.dm +++ b/code/modules/antagonists/heretic/knowledge/rust_lore.dm @@ -104,7 +104,7 @@ Anyone overtop the wall will be throw aside (or upwards) and sustain damage." gain_text = "Images of foreign and ominous structures began to dance in my mind. Covered head to toe in thick rust, \ they no longer looked man made. Or perhaps they never were in the first place." - spell_to_add = /datum/action/cooldown/spell/pointed/rust_construction + action_to_add = /datum/action/cooldown/spell/pointed/rust_construction cost = 1 /datum/heretic_knowledge/spell/area_conversion @@ -112,7 +112,7 @@ desc = "Grants you Aggressive Spread, a spell that spreads rust to nearby surfaces. \ Already rusted surfaces are destroyed \ Also improves the rusting abilities of non rust-heretics." gain_text = "All wise men know well not to visit the Rusted Hills... Yet the Blacksmith's tale was inspiring." - spell_to_add = /datum/action/cooldown/spell/aoe/rust_conversion + action_to_add = /datum/action/cooldown/spell/aoe/rust_conversion cost = 1 research_tree_icon_frame = 5 @@ -147,7 +147,7 @@ gain_text = "The corrosion was unstoppable. The rust was unpleasable. \ The Blacksmith was gone, and you hold their blade. Champions of hope, the Rustbringer is nigh!" - spell_to_add = /datum/action/cooldown/spell/cone/staggered/entropic_plume + action_to_add = /datum/action/cooldown/spell/cone/staggered/entropic_plume cost = 1 diff --git a/code/modules/antagonists/heretic/knowledge/side_blade_rust.dm b/code/modules/antagonists/heretic/knowledge/side_blade_rust.dm index 05b414fe34634..a09c9cd87973d 100644 --- a/code/modules/antagonists/heretic/knowledge/side_blade_rust.dm +++ b/code/modules/antagonists/heretic/knowledge/side_blade_rust.dm @@ -112,7 +112,7 @@ desc = "A charge that must be started on a rusted tile and will destroy any rusted objects you come into contact with, will deal high damage to others and rust around you during the charge." gain_text = "The hills sparkled now, as I neared them my mind began to wander. I quickly regained my resolve and pushed forward, this last leg would be the most treacherous." - spell_to_add = /datum/action/cooldown/mob_cooldown/charge/rust + action_to_add = /datum/action/cooldown/mob_cooldown/charge/rust cost = 1 diff --git a/code/modules/antagonists/heretic/knowledge/side_cosmos_ash.dm b/code/modules/antagonists/heretic/knowledge/side_cosmos_ash.dm index 03b4fc477ad1b..d15bb242989cf 100644 --- a/code/modules/antagonists/heretic/knowledge/side_cosmos_ash.dm +++ b/code/modules/antagonists/heretic/knowledge/side_cosmos_ash.dm @@ -36,7 +36,7 @@ You can only phase in and out when you are on a space or misc turf." gain_text = "You feel like your body can move through space as if you where dust." - spell_to_add = /datum/action/cooldown/spell/jaunt/space_crawl + action_to_add = /datum/action/cooldown/spell/jaunt/space_crawl cost = 1 diff --git a/code/modules/antagonists/heretic/knowledge/side_flesh_void.dm b/code/modules/antagonists/heretic/knowledge/side_flesh_void.dm index 7891b50aabcc9..bd7f1cf621c6f 100644 --- a/code/modules/antagonists/heretic/knowledge/side_flesh_void.dm +++ b/code/modules/antagonists/heretic/knowledge/side_flesh_void.dm @@ -35,7 +35,7 @@ Also has a chance to transfer wounds from you to the victim." gain_text = "\"No matter the man, we bleed all the same.\" That's what the Marshal told me." - spell_to_add = /datum/action/cooldown/spell/pointed/blood_siphon + action_to_add = /datum/action/cooldown/spell/pointed/blood_siphon cost = 1 /datum/heretic_knowledge/spell/void_prison @@ -47,7 +47,7 @@ But the only welts made are on my own beating fist. \ My smiling face turns to regard me, reflecting back in glassy eyes the empty path I have been lead down." - spell_to_add = /datum/action/cooldown/spell/pointed/void_prison + action_to_add = /datum/action/cooldown/spell/pointed/void_prison cost = 1 /datum/heretic_knowledge/spell/cleave @@ -57,7 +57,7 @@ gain_text = "At first I didn't understand these instruments of war, but the Priest \ told me to use them regardless. Soon, he said, I would know them well." - spell_to_add = /datum/action/cooldown/spell/pointed/cleave + action_to_add = /datum/action/cooldown/spell/pointed/cleave cost = 1 diff --git a/code/modules/antagonists/heretic/knowledge/side_lock_flesh.dm b/code/modules/antagonists/heretic/knowledge/side_lock_flesh.dm index aa85f31d006c5..0f7c9d9fc70e1 100644 --- a/code/modules/antagonists/heretic/knowledge/side_lock_flesh.dm +++ b/code/modules/antagonists/heretic/knowledge/side_lock_flesh.dm @@ -22,7 +22,7 @@ However, you will fall unconscious a short time after casting this spell." gain_text = "My shackles undone in dark fury, their feeble bindings crumble before my power." - spell_to_add = /datum/action/cooldown/spell/aoe/wave_of_desperation + action_to_add = /datum/action/cooldown/spell/aoe/wave_of_desperation cost = 1 /datum/heretic_knowledge/spell/apetra_vulnera @@ -32,7 +32,7 @@ Wounds a random limb if no limb is sufficiently damaged." gain_text = "Flesh opens, and blood spills. My master seeks sacrifice, and I shall appease." - spell_to_add = /datum/action/cooldown/spell/pointed/apetra_vulnera + action_to_add = /datum/action/cooldown/spell/pointed/apetra_vulnera cost = 1 diff --git a/code/modules/antagonists/heretic/knowledge/side_lock_moon.dm b/code/modules/antagonists/heretic/knowledge/side_lock_moon.dm index f8a3cdf465bd8..5d3795b0ce961 100644 --- a/code/modules/antagonists/heretic/knowledge/side_lock_moon.dm +++ b/code/modules/antagonists/heretic/knowledge/side_lock_moon.dm @@ -25,7 +25,7 @@ The caster takes 20 brain damage per use." gain_text = "My mind swings open like a gate, and its insight will let me perceive the truth." - spell_to_add = /datum/action/cooldown/spell/pointed/mind_gate + action_to_add = /datum/action/cooldown/spell/pointed/mind_gate cost = 1 /datum/heretic_knowledge/unfathomable_curio diff --git a/code/modules/antagonists/heretic/knowledge/side_void_blade.dm b/code/modules/antagonists/heretic/knowledge/side_void_blade.dm index 664db9969268b..df3ad9a34c7e3 100644 --- a/code/modules/antagonists/heretic/knowledge/side_void_blade.dm +++ b/code/modules/antagonists/heretic/knowledge/side_void_blade.dm @@ -116,22 +116,6 @@ demolition_mod = 1.5 sharpness = SHARP_EDGED -/obj/item/mutant_hand/shattered_risen/Initialize(mapload) - . = ..() - ADD_TRAIT(src, TRAIT_NODROP, HAND_REPLACEMENT_TRAIT) - -/obj/item/mutant_hand/shattered_risen/visual_equipped(mob/user, slot) - . = ..() - - // Even hand indexes are right hands, - // Odd hand indexes are left hand - // ...But also, we swap it intentionally here, - // so right icon is shown on the left (Because hands) - if(user.get_held_index_of_item(src) % 2 == 1) - icon_state = "[base_icon_state]_right" - else - icon_state = "[base_icon_state]_left" - /datum/heretic_knowledge/rune_carver name = "Carving Knife" desc = "Allows you to transmute a knife, a shard of glass, and a piece of paper to create a Carving Knife. \ diff --git a/code/modules/antagonists/heretic/knowledge/starting_lore.dm b/code/modules/antagonists/heretic/knowledge/starting_lore.dm index d6c9d1bc216a7..b20009febcf4b 100644 --- a/code/modules/antagonists/heretic/knowledge/starting_lore.dm +++ b/code/modules/antagonists/heretic/knowledge/starting_lore.dm @@ -21,7 +21,7 @@ GLOBAL_LIST_INIT(heretic_start_knowledge, initialize_starting_knowledge()) desc = "Starts your journey into the Mansus. \ Grants you the Mansus Grasp, a powerful and upgradable \ disabling spell that can be cast regardless of having a focus." - spell_to_add = /datum/action/cooldown/spell/touch/mansus_grasp + action_to_add = /datum/action/cooldown/spell/touch/mansus_grasp cost = 0 is_starting_knowledge = TRUE @@ -211,7 +211,7 @@ GLOBAL_LIST_INIT(heretic_start_knowledge, initialize_starting_knowledge()) name = "Cloak of Shadow" desc = "Grants you the spell Cloak of Shadow. This spell will completely conceal your identity in a purple smoke \ for three minutes, assisting you in keeping secrecy. Requires a focus to cast." - spell_to_add = /datum/action/cooldown/spell/shadow_cloak + action_to_add = /datum/action/cooldown/spell/shadow_cloak cost = 0 is_starting_knowledge = TRUE diff --git a/code/modules/antagonists/heretic/knowledge/void_lore.dm b/code/modules/antagonists/heretic/knowledge/void_lore.dm index fb4bc57924784..14e2ffe0e9ad5 100644 --- a/code/modules/antagonists/heretic/knowledge/void_lore.dm +++ b/code/modules/antagonists/heretic/knowledge/void_lore.dm @@ -116,7 +116,7 @@ gain_text = "The hum in the still, cold air turns to a cacophonous rattle. \ Over the noise, there is no distinction to the clattering of window panes and the yawning knowledge that ricochets through my skull. \ The doors won't close. I can't keep the cold out now." - spell_to_add = /datum/action/cooldown/spell/conjure/void_conduit + action_to_add = /datum/action/cooldown/spell/conjure/void_conduit cost = 1 /datum/heretic_knowledge/spell/void_phase @@ -125,7 +125,7 @@ Additionally causes damage to heathens around your original and target destination." gain_text = "The entity calls themself the Aristocrat. They effortlessly walk through air like \ nothing - leaving a harsh, cold breeze in their wake. They disappear, and I am left in the blizzard." - spell_to_add = /datum/action/cooldown/spell/pointed/void_phase + action_to_add = /datum/action/cooldown/spell/pointed/void_phase cost = 1 research_tree_icon_frame = 7 @@ -162,7 +162,7 @@ gain_text = "All is fleeting, but what else stays? I'm close to ending what was started. \ The Aristocrat reveals themselves to me again. They tell me I am late. Their pull is immense, I cannot turn back." - spell_to_add = /datum/action/cooldown/spell/aoe/void_pull + action_to_add = /datum/action/cooldown/spell/aoe/void_pull cost = 1 diff --git a/code/modules/antagonists/heretic/magic/furious_steel.dm b/code/modules/antagonists/heretic/magic/furious_steel.dm index 9414ca9d7116d..dceb9023bdbcc 100644 --- a/code/modules/antagonists/heretic/magic/furious_steel.dm +++ b/code/modules/antagonists/heretic/magic/furious_steel.dm @@ -19,9 +19,11 @@ active_msg = "You summon forth three blades of furious silver." deactive_msg = "You conceal the blades of furious silver." cast_range = 20 - projectile_type = /obj/effect/floating_blade + projectile_type = /obj/projectile/floating_blade projectile_amount = 3 + ///Effect of the projectile that surrounds us while the spell is active + var/projectile_effect = /obj/effect/floating_blade /// A ref to the status effect surrounding our heretic on activation. var/datum/status_effect/protective_blades/blade_effect @@ -67,7 +69,7 @@ QDEL_NULL(blade_effect) var/mob/living/living_user = on_who - blade_effect = living_user.apply_status_effect(/datum/status_effect/protective_blades, null, projectile_amount, 25, 0.66 SECONDS, projectile_type) + blade_effect = living_user.apply_status_effect(/datum/status_effect/protective_blades, null, projectile_amount, 25, 0.66 SECONDS, projectile_effect) RegisterSignal(blade_effect, COMSIG_QDELETING, PROC_REF(on_status_effect_deleted)) /datum/action/cooldown/spell/pointed/projectile/furious_steel/on_deactivation(mob/on_who, refund_cooldown = TRUE) @@ -167,3 +169,4 @@ deactive_msg = "You conceal the cursed blades." projectile_amount = 2 projectile_type = /obj/projectile/floating_blade/haunted + projectile_effect = /obj/effect/floating_blade/haunted diff --git a/code/modules/antagonists/heretic/magic/space_crawl.dm b/code/modules/antagonists/heretic/magic/space_crawl.dm index cce9f46085bc6..74b02c59c10e7 100644 --- a/code/modules/antagonists/heretic/magic/space_crawl.dm +++ b/code/modules/antagonists/heretic/magic/space_crawl.dm @@ -7,7 +7,7 @@ */ /datum/action/cooldown/spell/jaunt/space_crawl name = "Space Phase" - desc = "Allows you to phase in and out of existance while in space or misc tiles." + desc = "Allows you to phase in and out of existence while in space or misc tiles." background_icon_state = "bg_heretic" overlay_icon_state = "bg_heretic_border" diff --git a/code/modules/antagonists/heretic/magic/star_touch.dm b/code/modules/antagonists/heretic/magic/star_touch.dm index d9cd5a05eab2b..e8e824cc71851 100644 --- a/code/modules/antagonists/heretic/magic/star_touch.dm +++ b/code/modules/antagonists/heretic/magic/star_touch.dm @@ -201,35 +201,6 @@ if(current_target) on_beam_hit(current_target) -/// Checks if the beam is going through an invalid turf -/datum/status_effect/cosmic_beam/proc/los_check(atom/movable/user, mob/target) - var/turf/user_turf = user.loc - if(!istype(user_turf)) - return FALSE - var/obj/dummy = new(user_turf) - dummy.pass_flags |= PASSTABLE|PASSGLASS|PASSGRILLE //Grille/Glass so it can be used through common windows - var/turf/previous_step = user_turf - var/first_step = TRUE - for(var/turf/next_step as anything in (get_line(user_turf, target) - user_turf)) - if(first_step) - for(var/obj/blocker in user_turf) - if(!blocker.density || !(blocker.flags_1 & ON_BORDER_1)) - continue - if(blocker.CanPass(dummy, get_dir(user_turf, next_step))) - continue - return FALSE // Could not leave the first turf. - first_step = FALSE - if(next_step.density) - qdel(dummy) - return FALSE - for(var/atom/movable/movable as anything in next_step) - if(!movable.CanPass(dummy, get_dir(next_step, previous_step))) - qdel(dummy) - return FALSE - previous_step = next_step - qdel(dummy) - return TRUE - /// What to add when the beam connects to a target /datum/status_effect/cosmic_beam/proc/on_beam_hit(mob/living/target) if(!istype(target, /mob/living/basic/heretic_summon/star_gazer)) diff --git a/code/modules/antagonists/heretic/status_effects/buffs.dm b/code/modules/antagonists/heretic/status_effects/buffs.dm index 3004bdd9ee0ce..362e9750b49c1 100644 --- a/code/modules/antagonists/heretic/status_effects/buffs.dm +++ b/code/modules/antagonists/heretic/status_effects/buffs.dm @@ -260,7 +260,7 @@ max_num_blades = 4, blade_orbit_radius = 20, time_between_initial_blades = 0.25 SECONDS, - blade_type = /obj/effect/floating_blade, + blade_type = /obj/projectile/floating_blade, blade_recharge_time = 1 MINUTES, ) diff --git a/code/modules/antagonists/spy/spy_bounty.dm b/code/modules/antagonists/spy/spy_bounty.dm index 1aa318fb6828d..f45da0fdce832 100644 --- a/code/modules/antagonists/spy/spy_bounty.dm +++ b/code/modules/antagonists/spy/spy_bounty.dm @@ -639,7 +639,7 @@ theft_time = 10 SECONDS black_market_prob = 0 /// What typepath of bot we want to steal. - var/mob/living/simple_animal/bot/bot_type + var/mob/living/bot_type /// Weakref to the bot we want to steal. VAR_FINAL/datum/weakref/target_bot_ref @@ -655,7 +655,7 @@ /datum/spy_bounty/some_bot/init_bounty(datum/spy_bounty_handler/handler) for(var/datum/spy_bounty/some_bot/existing_bounty in handler.get_all_bounties()) - var/mob/living/simple_animal/bot/existing_bot_type = existing_bounty.bot_type + var/mob/living/existing_bot_type = existing_bounty.bot_type // ensures we don't get two similar bounties. // may occasionally cast a wider net than we'd desire, but it's not that bad. if(ispath(bot_type, initial(existing_bot_type.parent_type))) diff --git a/code/modules/antagonists/traitor/uplink_handler.dm b/code/modules/antagonists/traitor/uplink_handler.dm index 83899300614e5..e25473de6e319 100644 --- a/code/modules/antagonists/traitor/uplink_handler.dm +++ b/code/modules/antagonists/traitor/uplink_handler.dm @@ -69,10 +69,6 @@ SEND_SIGNAL(src, COMSIG_UPLINK_HANDLER_ON_UPDATE) return -/// Checks if traitor has enough reputation to purchase an item -/datum/uplink_handler/proc/not_enough_reputation(datum/uplink_item/to_purchase) - return has_progression && progression_points < to_purchase.progression_minimum - /// Checks for uplink flags as well as items restricted to roles and species /datum/uplink_handler/proc/check_if_restricted(datum/uplink_item/to_purchase) if(!to_purchase.can_be_bought(src)) @@ -104,7 +100,7 @@ var/current_stock = item_stock[to_purchase.stock_key] var/stock = current_stock != null ? current_stock : INFINITY - if(telecrystals < to_purchase.cost || stock <= 0 || not_enough_reputation(to_purchase)) + if(telecrystals < to_purchase.real_cost(src) || stock <= 0) return FALSE return TRUE @@ -116,7 +112,7 @@ if(to_purchase.limited_stock != -1 && !(to_purchase.stock_key in item_stock)) item_stock[to_purchase.stock_key] = to_purchase.limited_stock - telecrystals -= to_purchase.cost + telecrystals -= to_purchase.real_cost(src) to_purchase.purchase(user, src, source) if(to_purchase.stock_key in item_stock) diff --git a/code/modules/antagonists/wizard/equipment/soulstone.dm b/code/modules/antagonists/wizard/equipment/soulstone.dm index 751873c836277..52cd80e7155b8 100644 --- a/code/modules/antagonists/wizard/equipment/soulstone.dm +++ b/code/modules/antagonists/wizard/equipment/soulstone.dm @@ -158,9 +158,8 @@ return ..() /obj/item/soulstone/proc/hot_potato(mob/living/user) - to_chat(user, span_userdanger("Holy magics residing in \the [src] burn your hand!")) - var/obj/item/bodypart/affecting = user.get_bodypart("[(user.active_hand_index % 2 == 0) ? "r" : "l" ]_arm") - affecting.receive_damage( 0, 10 ) // 10 burn damage + to_chat(user, span_userdanger("Holy magics residing in [src] burn your hand!")) + user.apply_damage(10, BURN, user.get_active_hand()) user.emote("scream") user.update_damage_overlays() user.dropItemToGround(src) diff --git a/code/modules/antagonists/wizard/equipment/spellbook_entries/_entry.dm b/code/modules/antagonists/wizard/equipment/spellbook_entries/_entry.dm index 18e2dae715c34..28432b1ada883 100644 --- a/code/modules/antagonists/wizard/equipment/spellbook_entries/_entry.dm +++ b/code/modules/antagonists/wizard/equipment/spellbook_entries/_entry.dm @@ -31,10 +31,10 @@ /// Whether the spell requires wizard garb or not var/requires_wizard_garb = FALSE /// Used so you can't have specific spells together - var/list/no_coexistance_typecache + var/list/no_coexistence_typecache /datum/spellbook_entry/New() - no_coexistance_typecache = typecacheof(no_coexistance_typecache) + no_coexistence_typecache = typecacheof(no_coexistence_typecache) if(ispath(spell_type)) if(isnull(limit)) @@ -68,13 +68,13 @@ if(!isnull(limit) && times >= limit) return FALSE for(var/spell in user.actions) - if(is_type_in_typecache(spell, no_coexistance_typecache)) + if(is_type_in_typecache(spell, no_coexistence_typecache)) return FALSE var/datum/antagonist/wizard/wizard_datum = user.mind.has_antag_datum(/datum/antagonist/wizard) if(!wizard_datum) return TRUE for(var/perks in wizard_datum.perks) - if(is_type_in_typecache(perks, no_coexistance_typecache)) + if(is_type_in_typecache(perks, no_coexistence_typecache)) return FALSE if(is_type_in_list(src, wizard_datum.perks)) to_chat(user, span_warning("This perk already learned!")) diff --git a/code/modules/antagonists/wizard/equipment/spellbook_entries/defensive.dm b/code/modules/antagonists/wizard/equipment/spellbook_entries/defensive.dm index e7c204a39e214..585385e9d2ddf 100644 --- a/code/modules/antagonists/wizard/equipment/spellbook_entries/defensive.dm +++ b/code/modules/antagonists/wizard/equipment/spellbook_entries/defensive.dm @@ -55,7 +55,7 @@ it will become easier for others to find your item of power." spell_type = /datum/action/cooldown/spell/lichdom category = SPELLBOOK_CATEGORY_DEFENSIVE - no_coexistance_typecache = list(/datum/action/cooldown/spell/splattercasting, /datum/spellbook_entry/perks/wormborn) + no_coexistence_typecache = list(/datum/action/cooldown/spell/splattercasting, /datum/spellbook_entry/perks/wormborn) /datum/spellbook_entry/chuunibyou name = "Chuuni Invocations" diff --git a/code/modules/antagonists/wizard/equipment/spellbook_entries/offensive.dm b/code/modules/antagonists/wizard/equipment/spellbook_entries/offensive.dm index 6b8272ed5b7ad..d65e14578ec32 100644 --- a/code/modules/antagonists/wizard/equipment/spellbook_entries/offensive.dm +++ b/code/modules/antagonists/wizard/equipment/spellbook_entries/offensive.dm @@ -77,7 +77,7 @@ spell_type = /datum/action/cooldown/spell/conjure_item/infinite_guns/gun category = SPELLBOOK_CATEGORY_OFFENSIVE cost = 3 - no_coexistance_typecache = list(/datum/action/cooldown/spell/conjure_item/infinite_guns/arcane_barrage) + no_coexistence_typecache = list(/datum/action/cooldown/spell/conjure_item/infinite_guns/arcane_barrage) /datum/spellbook_entry/arcane_barrage name = "Arcane Barrage" @@ -85,7 +85,7 @@ spell_type = /datum/action/cooldown/spell/conjure_item/infinite_guns/arcane_barrage category = SPELLBOOK_CATEGORY_OFFENSIVE cost = 3 - no_coexistance_typecache = list(/datum/action/cooldown/spell/conjure_item/infinite_guns/gun) + no_coexistence_typecache = list(/datum/action/cooldown/spell/conjure_item/infinite_guns/gun) /datum/spellbook_entry/barnyard name = "Barnyard Curse" @@ -99,7 +99,7 @@ draining from you over time. You can replenish it from your victims, specifically their necks." spell_type = /datum/action/cooldown/spell/splattercasting category = SPELLBOOK_CATEGORY_OFFENSIVE - no_coexistance_typecache = list(/datum/action/cooldown/spell/lichdom) + no_coexistence_typecache = list(/datum/action/cooldown/spell/lichdom) /datum/spellbook_entry/sanguine_strike name = "Exsanguinating Strike" diff --git a/code/modules/antagonists/wizard/equipment/spellbook_entries/perks.dm b/code/modules/antagonists/wizard/equipment/spellbook_entries/perks.dm index 07c152d113d68..6c4947639f6c5 100644 --- a/code/modules/antagonists/wizard/equipment/spellbook_entries/perks.dm +++ b/code/modules/antagonists/wizard/equipment/spellbook_entries/perks.dm @@ -60,7 +60,7 @@ desc = "Your soul is infested with mana worms. When you die, you will be reborn as a large worm. \ When the worm dies, it has no such luck. Parasitic infection prevents you from binding your soul to objects." hud_icon = "wormborn" - no_coexistance_typecache = list(/datum/action/cooldown/spell/lichdom) + no_coexistence_typecache = list(/datum/action/cooldown/spell/lichdom) /datum/spellbook_entry/perks/wormborn/buy_spell(mob/living/carbon/human/user, obj/item/spellbook/book, log_buy) . = ..() diff --git a/code/modules/assembly/holder.dm b/code/modules/assembly/holder.dm index 5f50618e77dfa..5da6816eb8598 100644 --- a/code/modules/assembly/holder.dm +++ b/code/modules/assembly/holder.dm @@ -100,12 +100,12 @@ /obj/item/assembly_holder/update_overlays() . = ..() for(var/i in 1 to LAZYLEN(assemblies)) - if(i % 2 == 1) + if(IS_LEFT_INDEX(i)) var/obj/item/assembly/assembly = assemblies[i] . += "[assembly.icon_state]_left" for(var/left_overlay in assembly.attached_overlays) . += "[left_overlay]_l" - if(i % 2 == 0) + if(IS_RIGHT_INDEX(i)) var/obj/item/assembly/assembly = assemblies[i] var/mutable_appearance/right = mutable_appearance(icon, "[assembly.icon_state]_left") right.transform = matrix(-1, 0, 0, 0, 1, 0) diff --git a/code/modules/assembly/mousetrap.dm b/code/modules/assembly/mousetrap.dm index 19f853885b5ac..bb3fcb07c54b8 100644 --- a/code/modules/assembly/mousetrap.dm +++ b/code/modules/assembly/mousetrap.dm @@ -161,7 +161,7 @@ return FALSE if((HAS_TRAIT(user, TRAIT_DUMB) || HAS_TRAIT(user, TRAIT_CLUMSY)) && prob(50)) var/which_hand = BODY_ZONE_PRECISE_L_HAND - if(!(user.active_hand_index % 2)) + if(IS_RIGHT_INDEX(user.active_hand_index)) which_hand = BODY_ZONE_PRECISE_R_HAND triggered(user, which_hand) user.visible_message(span_warning("[user] accidentally sets off [src], breaking their fingers."), \ @@ -210,7 +210,7 @@ if(finder) finder.visible_message(span_warning("[finder] accidentally sets off [src], breaking their fingers."), \ span_warning("You accidentally trigger [src]!")) - triggered(finder, (finder.active_hand_index % 2 == 0) ? BODY_ZONE_PRECISE_R_HAND : BODY_ZONE_PRECISE_L_HAND) + triggered(finder, (IS_RIGHT_INDEX(finder.active_hand_index)) ? BODY_ZONE_PRECISE_R_HAND : BODY_ZONE_PRECISE_L_HAND) return TRUE //end the search! else visible_message(span_warning("[src] snaps shut!")) diff --git a/code/modules/atmospherics/environmental/LINDA_fire.dm b/code/modules/atmospherics/environmental/LINDA_fire.dm index 47a2af4651cbc..c2ffe56fc5769 100644 --- a/code/modules/atmospherics/environmental/LINDA_fire.dm +++ b/code/modules/atmospherics/environmental/LINDA_fire.dm @@ -15,6 +15,28 @@ /turf/proc/hotspot_expose(exposed_temperature, exposed_volume, soh = 0) return +/turf/open/proc/set_active_hotspot(obj/effect/hotspot/new_lad) + if(active_hotspot == new_lad) + return + var/hotspot_around = NONE + if(active_hotspot) + if(new_lad) + hotspot_around = active_hotspot.smoothing_junction + if(!QDELETED(active_hotspot)) + QDEL_NULL(active_hotspot) + else + for(var/direction in GLOB.cardinals) + var/turf/open/open = get_step(src, direction) + if(!isopenturf(open) || !open.active_hotspot) + continue + var/existing_directions = open.active_hotspot.smoothing_junction + open.active_hotspot.set_smoothed_icon_state(existing_directions | REVERSE_DIR(direction)) + hotspot_around |= direction + + active_hotspot = new_lad + if(active_hotspot) + active_hotspot.set_smoothed_icon_state(hotspot_around) + /** * Handles the creation of hotspots and initial activation of turfs. * Setting the conditions for the reaction to actually happen for gasmixtures @@ -55,10 +77,13 @@ if(((exposed_temperature > PLASMA_MINIMUM_BURN_TEMPERATURE) && (plas > 0.5 || trit > 0.5 || h2 > 0.5)) || \ ((exposed_temperature < FREON_MAXIMUM_BURN_TEMPERATURE) && (freon > 0.5))) - active_hotspot = new /obj/effect/hotspot(src, exposed_volume*25, exposed_temperature) + set_active_hotspot(new /obj/effect/hotspot(src, exposed_volume * 25, exposed_temperature)) + if(COOLDOWN_FINISHED(src, fire_puff_cooldown)) + playsound(src, 'sound/effects/fire_puff.ogg', 50) + COOLDOWN_START(src, fire_puff_cooldown, 5 SECONDS) active_hotspot.just_spawned = (current_cycle < SSair.times_fired) - //remove just_spawned protection if no longer processing this cell + //remove just_spawned protection if no longer processing this cell SSair.add_to_active(src) /** @@ -78,6 +103,9 @@ light_power = 1 light_color = LIGHT_COLOR_FIRE + /// base sprite used for our icon states when smoothing + /// BAAAASICALY the same as icon_state but is helpful to avoid duplicated work + var/fire_stage = "" /** * Volume is the representation of how big and healthy a fire is. * Hotspot volume will be divided by turf volume to get the ratio for temperature setting on non bypassing mode. @@ -93,7 +121,8 @@ var/visual_update_tick = 0 ///Are we burning freon? var/cold_fire = FALSE - + ///the group of hotspots we are a part of + var/datum/hot_group/our_hot_group /obj/effect/hotspot/Initialize(mapload, starting_volume, starting_temperature) . = ..() @@ -110,6 +139,24 @@ COMSIG_ATOM_ABSTRACT_ENTERED = PROC_REF(on_entered), ) AddElement(/datum/element/connect_loc, loc_connections) + var/turf/open/our_turf = loc + //on creation we check adjacent turfs for hot spot to start grouping, if surrounding do not have hot spots we create our own + for(var/turf/open/to_check as anything in our_turf.atmos_adjacent_turfs) + if(to_check.active_hotspot) + var/obj/effect/hotspot/enemy_spot = to_check.active_hotspot + if(!our_hot_group) + enemy_spot.our_hot_group.add_to_group(src) + else if(our_hot_group != enemy_spot.our_hot_group && enemy_spot.our_hot_group) //if we belongs to a hot group from prior loop and we encounter another hot spot with a group then we merge + our_hot_group.merge_hot_groups(enemy_spot.our_hot_group) + if(!our_hot_group)//if after loop through all the adjacents turfs and we havent belong to a group yet, make our own + our_hot_group = new + our_hot_group.add_to_group(src) + +/obj/effect/hotspot/set_smoothed_icon_state(new_junction) + + smoothing_junction = new_junction + + update_color() /** * Perform interactions between the hotspot and the gasmixture. @@ -130,7 +177,7 @@ if(!istype(location) || !(location.air)) return - location.active_hotspot = src + location.set_active_hotspot(src) bypassing = !just_spawned && (volume > CELL_VOLUME*0.95) @@ -199,7 +246,7 @@ sparkle_overlay.alpha = sparkle_amt * 255 add_overlay(sparkle_overlay) if(temperature > 400000 && temperature < 1500000) //Lightning because very anime. - var/mutable_appearance/lightning_overlay = mutable_appearance(icon, "overcharged") + var/mutable_appearance/lightning_overlay = mutable_appearance('icons/effects/fire.dmi', "overcharged") lightning_overlay.blend_mode = BLEND_ADD add_overlay(lightning_overlay) if(temperature > 4500000) //This is where noblium happens. Some fusion-y effects. @@ -264,7 +311,7 @@ perform_exposure() if(bypassing) - icon_state = "3" + set_fire_stage("heavy") if(!cold_fire) location.burn_tile() @@ -280,20 +327,30 @@ else if(volume > CELL_VOLUME*0.4) - icon_state = "2" + set_fire_stage("medium") else - icon_state = "1" + set_fire_stage("light") if((visual_update_tick++ % 7) == 0) update_color() return TRUE +/obj/effect/hotspot/proc/set_fire_stage(stage) + if(fire_stage == stage) + return + fire_stage = stage + icon_state = stage + dir = pick(GLOB.cardinals) + update_color() + /obj/effect/hotspot/Destroy() SSair.hotspots -= src var/turf/open/T = loc if(istype(T) && T.active_hotspot == src) - T.active_hotspot = null + our_hot_group.remove_from_group(src) + our_hot_group = null + T.set_active_hotspot(null) return ..() /obj/effect/hotspot/proc/on_entered(datum/source, atom/movable/arrived, atom/old_loc, list/atom/old_locs) @@ -305,4 +362,95 @@ /obj/effect/hotspot/singularity_pull(atom/singularity, current_size) return +/datum/looping_sound/fire + mid_sounds = list('sound/effects/fireclip1.ogg' = 1, 'sound/effects/fireclip2.ogg' = 1, 'sound/effects/fireclip3.ogg' = 1, 'sound/effects/fireclip4.ogg' = 1, + 'sound/effects/fireclip5.ogg' = 1, 'sound/effects/fireclip6.ogg' = 1, 'sound/effects/fireclip7.ogg' = 1) + volume = 50 + mid_length = 2 SECONDS + falloff_distance = 1 + +#define MIN_SIZE_SOUND 2 +///handle the grouping of hotspot and then determining an average center to play sound in +/datum/hot_group + var/list/obj/effect/hotspot/spot_list = list() + ///the sound center turf which the looping sound will play + var/turf/open/current_sound_loc + var/datum/looping_sound/fire/sound + var/tiles_limit = 80 // arbitrary limit so we dont have one giant group + ///these lists and average var are to find the average center of a group + var/list/x_coord = list() + var/list/y_coord = list() + var/list/z_coord = list() + var/average_x + var/average_y + var/average_Z + ///the range for the sound to drop off based on the size of the group + var/drop_off_dist + COOLDOWN_DECLARE(update_sound_center) + + +/datum/hot_group/Destroy() + . = ..() + current_sound_loc = null + spot_list = null + qdel(sound) + +/datum/hot_group/proc/remove_from_group(obj/effect/hotspot/target) + spot_list -= target + var/turf/open/target_turf = target.loc + x_coord -= target_turf.x + y_coord -= target_turf.y + if(!length(spot_list)) + qdel(src) + return + +/datum/hot_group/proc/add_to_group(obj/effect/hotspot/target) + spot_list += target + target.our_hot_group = src + var/turf/open/target_turf = target.loc + x_coord += target_turf.x + y_coord += target_turf.y + z_coord += target_turf.z + if(COOLDOWN_FINISHED(src, update_sound_center) && length(spot_list) > MIN_SIZE_SOUND)//arbitrary size to start playing the sound + update_sound() + COOLDOWN_START(src, update_sound_center, 5 SECONDS) + +/datum/hot_group/proc/merge_hot_groups(datum/hot_group/enemy_group) + if(length(spot_list) >= tiles_limit || length(enemy_group.spot_list) >= tiles_limit) + return + var/datum/hot_group/saving_group + var/datum/hot_group/sacrificial_group + if(length(spot_list) > length(enemy_group.spot_list) || (length(spot_list) == length(enemy_group.spot_list) && prob(50)))//we're bigger take all of their territory! + saving_group = src + sacrificial_group = enemy_group + else + saving_group = enemy_group + sacrificial_group = src + for(var/obj/effect/hotspot/reference as anything in sacrificial_group.spot_list) + reference.our_hot_group = saving_group + saving_group.spot_list += sacrificial_group.spot_list + saving_group.x_coord += sacrificial_group.x_coord + saving_group.y_coord += sacrificial_group.y_coord + qdel(sacrificial_group) + if(COOLDOWN_FINISHED(src, update_sound_center) && length(spot_list) > MIN_SIZE_SOUND)//arbitrary size to start playing the sound + update_sound() + COOLDOWN_START(src, update_sound_center, 5 SECONDS) + +/datum/hot_group/proc/update_sound() + //we can draw a cross around the average middle of any globs of group, curves or hollow groups may cause issues with this + average_x = round((max(x_coord) + min(x_coord))/2) + average_y = round((max(y_coord) + min(y_coord))/2) + average_Z = round((min(z_coord) + max(z_coord))/2) + drop_off_dist = max((max(y_coord) - min(y_coord)), (max(x_coord) - min(x_coord)), 1)// pick the largest value between the width and length of the group to determine sound drop off + var/turf/open/sound_turf = locate(average_x, average_y, average_Z) + if(sound) + sound.falloff_distance = drop_off_dist + if(sound_turf != current_sound_loc) + sound.parent = sound_turf + return + sound = new(sound_turf, TRUE) + sound.falloff_distance = drop_off_dist + current_sound_loc = sound_turf + +#undef MIN_SIZE_SOUND #undef INSUFFICIENT diff --git a/code/modules/atmospherics/environmental/LINDA_turf_tile.dm b/code/modules/atmospherics/environmental/LINDA_turf_tile.dm index dc56aa3fda7f7..ebdb64b9afd9d 100644 --- a/code/modules/atmospherics/environmental/LINDA_turf_tile.dm +++ b/code/modules/atmospherics/environmental/LINDA_turf_tile.dm @@ -37,7 +37,7 @@ ///Are we active? var/excited = FALSE ///Our gas mix - var/datum/gas_mixture/turf/air + var/datum/gas_mixture/air ///If there is an active hotspot on us store a reference to it here var/obj/effect/hotspot/active_hotspot @@ -50,6 +50,8 @@ ///gas IDs of current active gas overlays var/list/atmos_overlay_types var/significant_share_ticker = 0 + ///the cooldown on playing a fire starting sound each time a tile is ignited + COOLDOWN_DECLARE(fire_puff_cooldown) #ifdef TRACK_MAX_SHARE var/max_share = 0 #endif @@ -693,5 +695,6 @@ Then we space some of our heat, and think about if we should stop conducting. temperature += heat / heat_capacity //The higher your own heat cap the less heat you get from this arrangement sharer.temperature -= heat / sharer.heat_capacity + #undef LAST_SHARE_CHECK #undef PLANET_SHARE_CHECK diff --git a/code/modules/autowiki/pages/fishing.dm b/code/modules/autowiki/pages/fishing.dm index eab26bd6c6c03..ce2872235bb4a 100644 --- a/code/modules/autowiki/pages/fishing.dm +++ b/code/modules/autowiki/pages/fishing.dm @@ -44,7 +44,7 @@ if(fish::breeding_timeout != def_breeding) extra_info += "It takes [DisplayTimeText(fish::breeding_timeout)] to reproduce instead of [def_breeding_text]" if(length(extra_info)) - description += "
[extra_info.Join(extra_info,"
")]" + description += "
[extra_info.Join("
")]" var/list/output_list = list( "name" = full_capitalize(escape_value(fish::name)), diff --git a/code/modules/bitrunning/alerts.dm b/code/modules/bitrunning/alerts.dm index 54738b594c22d..478ae3c04cbd3 100644 --- a/code/modules/bitrunning/alerts.dm +++ b/code/modules/bitrunning/alerts.dm @@ -7,6 +7,7 @@ name = "Domain Completed" desc = "The domain is completed. Activate to exit." timeout = 20 SECONDS + clickable_glow = TRUE /atom/movable/screen/alert/bitrunning/qserver_domain_complete/Click(location, control, params) . = ..() diff --git a/code/modules/bitrunning/components/avatar_connection.dm b/code/modules/bitrunning/components/avatar_connection.dm index 7925461652a00..1ed1647a672b4 100644 --- a/code/modules/bitrunning/components/avatar_connection.dm +++ b/code/modules/bitrunning/components/avatar_connection.dm @@ -64,7 +64,9 @@ var/alias = our_client?.prefs?.read_preference(/datum/preference/name/hacker_alias) || pick(GLOB.hacker_aliases) if(alias && avatar.real_name != alias) - avatar.fully_replace_character_name(avatar.real_name, alias) + avatar.fully_replace_character_name(newname = alias) + + update_avatar_id() for(var/skill_type in old_mind.known_skills) avatar.mind.set_experience(skill_type, old_mind.get_skill_exp(skill_type), silent = TRUE) @@ -111,6 +113,20 @@ )) +/// Updates our avatar's ID to match our avatar's name. +/datum/component/avatar_connection/proc/update_avatar_id() + var/mob/living/avatar = parent + var/obj/item/card/id/our_id = locate() in avatar.get_all_contents() + if(isnull(our_id)) + return + + our_id.registered_name = avatar.real_name + our_id.update_label() + our_id.update_icon() + if(our_id.registered_account) + our_id.registered_account.account_holder = avatar.real_name + + /// Disconnects the avatar and returns the mind to the old_body. /datum/component/avatar_connection/proc/full_avatar_disconnect(cause_damage = FALSE, datum/source) #ifndef UNIT_TESTS diff --git a/code/modules/bitrunning/objects/vendor.dm b/code/modules/bitrunning/objects/vendor.dm index d44630bc3beed..f373a8617b445 100644 --- a/code/modules/bitrunning/objects/vendor.dm +++ b/code/modules/bitrunning/objects/vendor.dm @@ -33,7 +33,7 @@ /obj/machinery/computer/order_console/bitrunning/order_groceries(mob/living/purchaser, obj/item/card/id/card, list/groceries) var/list/things_to_order = list() for(var/datum/orderable_item/item as anything in groceries) - things_to_order[item.item_path] = groceries[item] + things_to_order[item.purchase_path] = groceries[item] var/datum/supply_pack/bitrunning/pack = new( purchaser = purchaser, \ diff --git a/code/modules/bitrunning/orders/bepis.dm b/code/modules/bitrunning/orders/bepis.dm index 4b7253bdaf24a..f10eaaf3245a2 100644 --- a/code/modules/bitrunning/orders/bepis.dm +++ b/code/modules/bitrunning/orders/bepis.dm @@ -2,18 +2,18 @@ category_index = CATEGORY_BEPIS /datum/orderable_item/bepis/circuit_stack - item_path = /obj/item/stack/circuit_stack/full + purchase_path = /obj/item/stack/circuit_stack/full cost_per_order = 150 /datum/orderable_item/bepis/survival_pen - item_path = /obj/item/pen/survival + purchase_path = /obj/item/pen/survival cost_per_order = 150 /datum/orderable_item/bepis/party_sleeper - item_path = /obj/item/circuitboard/machine/sleeper/party + purchase_path = /obj/item/circuitboard/machine/sleeper/party cost_per_order = 750 desc = "A decommissioned sleeper circuitboard, repurposed for recreational purposes." /datum/orderable_item/bepis/sprayoncan - item_path = /obj/item/toy/sprayoncan + purchase_path = /obj/item/toy/sprayoncan cost_per_order = 750 diff --git a/code/modules/bitrunning/orders/flair.dm b/code/modules/bitrunning/orders/flair.dm index ef36348eb6ae9..0b1b79b03d0b9 100644 --- a/code/modules/bitrunning/orders/flair.dm +++ b/code/modules/bitrunning/orders/flair.dm @@ -2,39 +2,39 @@ category_index = CATEGORY_BITRUNNING_FLAIR /datum/orderable_item/bitrunning_flair/cornchips - item_path = /obj/item/food/cornchips + purchase_path = /obj/item/food/cornchips cost_per_order = 100 /datum/orderable_item/bitrunning_flair/mountain_wind - item_path = /obj/item/reagent_containers/cup/soda_cans/space_mountain_wind + purchase_path = /obj/item/reagent_containers/cup/soda_cans/space_mountain_wind cost_per_order = 100 /datum/orderable_item/bitrunning_flair/pwr_game - item_path = /obj/item/reagent_containers/cup/soda_cans/pwr_game + purchase_path = /obj/item/reagent_containers/cup/soda_cans/pwr_game cost_per_order = 200 /datum/orderable_item/bitrunning_flair/grey_bull - item_path = /obj/item/reagent_containers/cup/soda_cans/grey_bull + purchase_path = /obj/item/reagent_containers/cup/soda_cans/grey_bull cost_per_order = 200 /datum/orderable_item/bitrunning_flair/medkit - item_path = /obj/item/storage/medkit/brute + purchase_path = /obj/item/storage/medkit/brute desc = "Don't beat yourself up, it's just a game!" cost_per_order = 500 /datum/orderable_item/bitrunning_flair/medkit_fire - item_path = /obj/item/storage/medkit/fire + purchase_path = /obj/item/storage/medkit/fire desc = "Great after heated gaming sessions." cost_per_order = 500 /datum/orderable_item/bitrunning_flair/oval_sunglasses - item_path = /obj/item/clothing/glasses/sunglasses/oval + purchase_path = /obj/item/clothing/glasses/sunglasses/oval cost_per_order = 1000 /datum/orderable_item/bitrunning_flair/trenchcoat - item_path = /obj/item/clothing/suit/jacket/trenchcoat + purchase_path = /obj/item/clothing/suit/jacket/trenchcoat cost_per_order = 1000 /datum/orderable_item/bitrunning_flair/jackboots - item_path = /obj/item/clothing/shoes/jackboots + purchase_path = /obj/item/clothing/shoes/jackboots cost_per_order = 1000 diff --git a/code/modules/bitrunning/orders/tech.dm b/code/modules/bitrunning/orders/tech.dm index 9dd1db17c799d..cb509fb625201 100644 --- a/code/modules/bitrunning/orders/tech.dm +++ b/code/modules/bitrunning/orders/tech.dm @@ -3,54 +3,54 @@ /datum/orderable_item/bitrunning_tech/item_tier1 cost_per_order = 750 - item_path = /obj/item/bitrunning_disk/item/tier1 + purchase_path = /obj/item/bitrunning_disk/item/tier1 desc = "This disk contains a program that lets you equip a medical beamgun, a C4 explosive, or a box of infinite pizza." /datum/orderable_item/bitrunning_tech/item_tier2 cost_per_order = 1250 - item_path = /obj/item/bitrunning_disk/item/tier2 + purchase_path = /obj/item/bitrunning_disk/item/tier2 desc = "This disk contains a program that lets you equip a luxury medipen, a pistol, or an armour vest." /datum/orderable_item/bitrunning_tech/item_tier3 cost_per_order = 2000 - item_path = /obj/item/bitrunning_disk/item/tier3 + purchase_path = /obj/item/bitrunning_disk/item/tier3 desc = "This disk contains a program that lets you equip an advanced energy gun, a dual bladed energy sword, or a minibomb." /datum/orderable_item/bitrunning_tech/ability_tier1 cost_per_order = 750 - item_path = /obj/item/bitrunning_disk/ability/tier1 + purchase_path = /obj/item/bitrunning_disk/ability/tier1 desc = "This disk contains a program that lets you cast Summon Cheese or Lesser Heal." /datum/orderable_item/bitrunning_tech/ability_tier2 cost_per_order = 1500 - item_path = /obj/item/bitrunning_disk/ability/tier2 + purchase_path = /obj/item/bitrunning_disk/ability/tier2 desc = "This disk contains a program that lets you cast Fireball, Lightning Bolt, or Forcewall." /datum/orderable_item/bitrunning_tech/ability_tier3 cost_per_order = 2500 - item_path = /obj/item/bitrunning_disk/ability/tier3 + purchase_path = /obj/item/bitrunning_disk/ability/tier3 desc = "This disk contains a program that lets you shapeshift into a lesser ashdrake, or a polar bear." /datum/orderable_item/bitrunning_tech/flip_skillchip - item_path = /obj/item/skillchip/matrix_taunt + purchase_path = /obj/item/skillchip/matrix_taunt cost_per_order = 1500 /datum/orderable_item/bitrunning_tech/pka_mod - item_path = /obj/item/bitrunning_disk/item/pka_mods + purchase_path = /obj/item/bitrunning_disk/item/pka_mods cost_per_order = 750 desc = "This disk contains a program that lets you equip modkits for the proto-kinetic accelerator. Proto-kinetic accelerator not included." /datum/orderable_item/bitrunning_tech/pka_mod/premium - item_path = /obj/item/bitrunning_disk/item/pka_mods/premium + purchase_path = /obj/item/bitrunning_disk/item/pka_mods/premium cost_per_order = 1600 desc = "This disk contains a program that lets you equip stronger modkits for the proto-kinetic accelerator. Proto-kinetic accelerator not included." /datum/orderable_item/bitrunning_tech/pkc_mod - item_path = /obj/item/bitrunning_disk/item/pkc_mods + purchase_path = /obj/item/bitrunning_disk/item/pkc_mods cost_per_order = 750 desc = "This disk contains a program that lets you equip trophies for the proto-kinetic crusher. Proto-kinetic crusher no included." /datum/orderable_item/bitrunning_tech/pkc_mod/premium - item_path = /obj/item/bitrunning_disk/item/pkc_mods/premium + purchase_path = /obj/item/bitrunning_disk/item/pkc_mods/premium cost_per_order = 1600 desc = "This disk contains a program that lets you equip stronger trophies for the proto-kinetic crusher. Proto-kinetic crusher not included." diff --git a/code/modules/bitrunning/server/_parent.dm b/code/modules/bitrunning/server/_parent.dm index 672a79ba72cef..5e29c1729b490 100644 --- a/code/modules/bitrunning/server/_parent.dm +++ b/code/modules/bitrunning/server/_parent.dm @@ -45,7 +45,7 @@ /// Maximum rate at which a glitch can spawn var/threat_prob_max = 15 /// The turfs we can place a hololadder on. - var/turf/exit_turfs = list() + var/list/turf/exit_turfs = list() /// Determines if we broadcast to entertainment monitors or not var/broadcasting = FALSE /// Cooldown between being able to toggle broadcasting diff --git a/code/modules/capture_the_flag/ctf_game.dm b/code/modules/capture_the_flag/ctf_game.dm index 2f292218e79f6..968e6e2953e95 100644 --- a/code/modules/capture_the_flag/ctf_game.dm +++ b/code/modules/capture_the_flag/ctf_game.dm @@ -403,7 +403,7 @@ alpha = 255 /obj/structure/trap/ctf/examine(mob/user) - return + return list() /obj/structure/trap/ctf/trap_effect(mob/living/living) if(!is_ctf_target(living)) diff --git a/code/modules/cargo/bounties/assistant.dm b/code/modules/cargo/bounties/assistant.dm index 23e578c2ed2db..a93fdc97d8e69 100644 --- a/code/modules/cargo/bounties/assistant.dm +++ b/code/modules/cargo/bounties/assistant.dm @@ -174,7 +174,7 @@ name = "Crayons" description = "Dr. Jones's kid ate all of our crayons again. Please send us yours." reward = CARGO_CRATE_VALUE * 4 - required_count = 24 + required_count = 8 wanted_types = list(/obj/item/toy/crayon = TRUE) /datum/bounty/item/assistant/pens diff --git a/code/modules/cargo/bounties/botany.dm b/code/modules/cargo/bounties/botany.dm index 905122584bf34..042bb60636f09 100644 --- a/code/modules/cargo/bounties/botany.dm +++ b/code/modules/cargo/bounties/botany.dm @@ -1,8 +1,8 @@ /datum/bounty/item/botany reward = CARGO_CRATE_VALUE * 10 - var/datum/bounty/item/botany/multiplier = 0 //adds bonus reward money; increased for higher tier or rare mutations - var/datum/bounty/item/botany/bonus_desc //for adding extra flavor text to bounty descriptions - var/datum/bounty/item/botany/foodtype = "meal" //same here + var/multiplier = 0 //adds bonus reward money; increased for higher tier or rare mutations + var/bonus_desc //for adding extra flavor text to bounty descriptions + var/foodtype = "meal" //same here /datum/bounty/item/botany/New() ..() diff --git a/code/modules/cargo/centcom_podlauncher.dm b/code/modules/cargo/centcom_podlauncher.dm index 1ba739d3343a4..bb1c4ea8a8b86 100644 --- a/code/modules/cargo/centcom_podlauncher.dm +++ b/code/modules/cargo/centcom_podlauncher.dm @@ -303,7 +303,7 @@ ADMIN_VERB(centcom_podlauncher, R_ADMIN, "Config/Launch Supplypod", "Configure a return if (!isnum(boomInput[i])) //If the user doesn't input a number, set that specific explosion value to zero tgui_alert(usr, "That wasn't a number! Value set to default (zero) instead.") - boomInput = 0 + boomInput[i] = 0 explosionChoice = 1 temp_pod.explosionSize = boomInput . = TRUE diff --git a/code/modules/cargo/markets/market_items/weapons.dm b/code/modules/cargo/markets/market_items/weapons.dm index 94aa533c26e3f..f9fd6245c8d99 100644 --- a/code/modules/cargo/markets/market_items/weapons.dm +++ b/code/modules/cargo/markets/market_items/weapons.dm @@ -64,6 +64,16 @@ stock_max = 3 availability_prob = 45 +/datum/market_item/weapon/carpenter_hammer + name = "Carpenter hammer" + desc = "When you really want to look like a psycho..." + item = /obj/item/carpenter_hammer + + price_min = CARGO_CRATE_VALUE * 1 + price_max = CARGO_CRATE_VALUE * 1.25 + stock_max = 2 + availability_prob = 65 + /datum/market_item/weapon/emp_grenade name = "EMP Grenade" desc = "Use this grenade for SHOCKING results!" diff --git a/code/modules/cargo/packs/emergency.dm b/code/modules/cargo/packs/emergency.dm index 2d19c276ec115..3cbe3b56aff65 100644 --- a/code/modules/cargo/packs/emergency.dm +++ b/code/modules/cargo/packs/emergency.dm @@ -24,7 +24,7 @@ cost = CARGO_CRATE_VALUE * 4 contains = list( /mob/living/basic/bot/medbot = 2, - /mob/living/simple_animal/bot/floorbot = 2, + /mob/living/basic/bot/repairbot = 2, /obj/item/tank/internals/emergency_oxygen = 5, /obj/item/clothing/mask/breath = 5, ) diff --git a/code/modules/cargo/packs/medical.dm b/code/modules/cargo/packs/medical.dm index d021fa8665ff2..8255a43d0490b 100644 --- a/code/modules/cargo/packs/medical.dm +++ b/code/modules/cargo/packs/medical.dm @@ -192,6 +192,14 @@ crate_name = "Strong-Arm implant crate" discountable = SUPPLY_PACK_RARE_DISCOUNTABLE +/datum/supply_pack/medical/paperwork_implants + name = "Paperwork Implant Set" + desc = "A crate containing two implants, which can be surgically implanted to effectivize crewmembers at paperwork. Warranty void if exposed to electromagnetic pulses." + cost = CARGO_CRATE_VALUE * 3 + contains = list(/obj/item/organ/cyberimp/arm/paperwork = 2) + crate_name = "Paperwork implant crate" + discountable = SUPPLY_PACK_RARE_DISCOUNTABLE + /datum/supply_pack/medical/lost_crew name = "Recovered NT Employee corpse" desc = "We don't have the accomodations to bring them back, could we send them to you? Please revive and employ them. \ diff --git a/code/modules/cargo/packs/service.dm b/code/modules/cargo/packs/service.dm index bde635695fd28..0e704a62df49d 100644 --- a/code/modules/cargo/packs/service.dm +++ b/code/modules/cargo/packs/service.dm @@ -237,12 +237,16 @@ /datum/supply_pack/service/randomized/ready_donk name = "Ready-Donk Variety Crate" - desc = "Featuring a line up of Donk Co.'s most popular pastry! Contains \ + desc = "Featuring a line up of Donk Co.'s fan-favourite microwave meal! Contains \ a random assortment of Ready Donk products." cost = CARGO_CRATE_VALUE * 3 contains = list(/obj/item/food/ready_donk, /obj/item/food/ready_donk/mac_n_cheese, /obj/item/food/ready_donk/donkhiladas, + /obj/item/food/ready_donk/nachos_grandes, + /obj/item/food/ready_donk/donkrange_chicken, + /obj/item/food/ready_donk/salisbury_steak, + /obj/item/food/ready_donk/country_chicken, ) crate_name = "\improper Ready-Donk crate" crate_type = /obj/structure/closet/crate/freezer/donk diff --git a/code/modules/client/client_colour.dm b/code/modules/client/client_colour.dm index 4ca500a9e7198..08e79c305a454 100644 --- a/code/modules/client/client_colour.dm +++ b/code/modules/client/client_colour.dm @@ -220,6 +220,9 @@ /datum/client_colour/malfunction colour = list(/*R*/ 0,0,0,0, /*G*/ 0,175,0,0, /*B*/ 0,0,0,0, /*A*/ 0,0,0,1, /*C*/0,-130,0,0) // Matrix colors +/datum/client_colour/perceptomatrix + colour = list(/*R*/ 1,0,0,0, /*G*/ 0,1,0,0, /*B*/ 0,0,1,0, /*A*/ 0,0,0,1, /*C*/0,-0.02,-0.02,0) // veeery slightly pink + /datum/client_colour/monochrome colour = COLOR_MATRIX_GRAYSCALE priority = PRIORITY_HIGH //we can't see colors anyway! diff --git a/code/modules/client/client_defines.dm b/code/modules/client/client_defines.dm index c8e9e9a64c270..fe559b2b71bfa 100644 --- a/code/modules/client/client_defines.dm +++ b/code/modules/client/client_defines.dm @@ -269,3 +269,7 @@ ///Which ambient sound this client is currently being provided. var/current_ambient_sound + + /// Does this client's mob need to rebuild its plane masters after login? + /// This is currently only used so a client can switch between 515 and 516 without breaking their rendering. + var/rebuild_plane_masters = FALSE diff --git a/code/modules/client/client_procs.dm b/code/modules/client/client_procs.dm index e0f359ac1e639..4bd8ce5497e2d 100644 --- a/code/modules/client/client_procs.dm +++ b/code/modules/client/client_procs.dm @@ -329,10 +329,20 @@ GLOBAL_LIST_INIT(blacklisted_builds, list( if(GLOB.player_details[ckey]) reconnecting = TRUE player_details = GLOB.player_details[ckey] - player_details.byond_version = full_version + var/old_version = player_details.byond_version + player_details.byond_version = byond_version + player_details.byond_build = byond_build + +#if MIN_COMPILER_VERSION > 516 + #warn Fully change default relay_loc to "1,1", rather than changing it based on client version +#endif + if(old_version != byond_version) + rebuild_plane_masters = TRUE + else player_details = new(ckey) - player_details.byond_version = full_version + player_details.byond_version = byond_version + player_details.byond_build = byond_build GLOB.player_details[ckey] = player_details @@ -726,22 +736,16 @@ GLOBAL_LIST_INIT(blacklisted_builds, list( qdel(query_datediff) qdel(query_get_client_age) if(!new_player) - var/datum/db_query/query_log_player = SSdbcore.NewQuery( + SSdbcore.FireAndForget( "UPDATE [format_table_name("player")] SET lastseen = Now(), lastseen_round_id = :round_id, ip = INET_ATON(:ip), computerid = :computerid, lastadminrank = :admin_rank, accountjoindate = :account_join_date WHERE ckey = :ckey", list("round_id" = GLOB.round_id, "ip" = address, "computerid" = computer_id, "admin_rank" = admin_rank, "account_join_date" = account_join_date || null, "ckey" = ckey) ) - if(!query_log_player.Execute()) - qdel(query_log_player) - return - qdel(query_log_player) if(!account_join_date) account_join_date = "Error" - var/datum/db_query/query_log_connection = SSdbcore.NewQuery({" + SSdbcore.FireAndForget({" INSERT INTO `[format_table_name("connection_log")]` (`id`,`datetime`,`server_ip`,`server_port`,`round_id`,`ckey`,`ip`,`computerid`) VALUES(null,Now(),INET_ATON(:internet_address),:port,:round_id,:ckey,INET_ATON(:ip),:computerid) "}, list("internet_address" = world.internet_address || "0", "port" = world.port, "round_id" = GLOB.round_id, "ckey" = ckey, "ip" = address, "computerid" = computer_id)) - query_log_connection.Execute() - qdel(query_log_connection) SSserver_maint.UpdateHubStatus() diff --git a/code/modules/client/player_details.dm b/code/modules/client/player_details.dm index 3a880dcdbb550..d0982a0c31268 100644 --- a/code/modules/client/player_details.dm +++ b/code/modules/client/player_details.dm @@ -1,6 +1,6 @@ ///assoc list of ckey -> /datum/player_details -GLOBAL_LIST_EMPTY(player_details) +GLOBAL_LIST_EMPTY_TYPED(player_details, /datum/player_details) /// Tracks information about a client between log in and log outs /datum/player_details @@ -18,8 +18,10 @@ GLOBAL_LIST_EMPTY(player_details) /// Lazylist of preference slots this client has joined the round under /// Numbers are stored as strings var/list/joined_as_slots - /// Version of byond this client is using - var/byond_version = "Unknown" + /// Major version of BYOND this client is using. + var/byond_version + /// Build number of BYOND this client is using. + var/byond_build /// Tracks achievements they have earned var/datum/achievement_data/achievements /// World.time this player last died @@ -35,6 +37,12 @@ GLOBAL_LIST_EMPTY(player_details) previous_names += html_encode("[previous_name] ([played_names[previous_name]])") return previous_names.Join("; ") +/// Returns the full version string (i.e 515.1642) of the BYOND version and build. +/datum/player_details/proc/full_byond_version() + if(!byond_version) + return "Unknown" + return "[byond_version].[byond_build || "xxx"]" + /// Adds the new names to the player's played_names list on their /datum/player_details for use of admins. /// `ckey` should be their ckey, and `data` should be an associative list with the keys being the names they played under and the values being the unique mob ID tied to that name. /proc/log_played_names(ckey, data) diff --git a/code/modules/clothing/gloves/special.dm b/code/modules/clothing/gloves/special.dm index dcbc798eab92a..09df92bb8c4f2 100644 --- a/code/modules/clothing/gloves/special.dm +++ b/code/modules/clothing/gloves/special.dm @@ -273,9 +273,3 @@ var/body_zone = pick(BODY_ZONE_R_ARM, BODY_ZONE_L_ARM) user.apply_damage(damage, BRUTE, body_zone, user.run_armor_check(body_zone, MELEE)) playsound(src,'sound/items/weapons/bite.ogg', damage * 2, TRUE) - -/obj/item/clothing/gloves/botanic_leather/janitor - name = "janitor gloves" - desc = "These rubber gloves protect against thorns, barbs, prickles, glass shards and any other threats that might be found in the station's trash. They're also quite warm." - icon_state = "janitor_doppler" - inhand_icon_state = null diff --git a/code/modules/clothing/head/hardhat.dm b/code/modules/clothing/head/hardhat.dm index 56a8661a4127a..3b74106d4361b 100644 --- a/code/modules/clothing/head/hardhat.dm +++ b/code/modules/clothing/head/hardhat.dm @@ -143,7 +143,7 @@ /obj/item/clothing/head/utility/hardhat/welding/adjust_visor(mob/living/user) . = ..() if(.) - playsound(src, 'sound/vehicles/mecha/mechmove03.ogg', 50, TRUE) + playsound(src, up ? SFX_VISOR_UP : SFX_VISOR_DOWN, 50, TRUE) /obj/item/clothing/head/utility/hardhat/welding/worn_overlays(mutable_appearance/standing, isinhands) . = ..() diff --git a/code/modules/clothing/head/hat.dm b/code/modules/clothing/head/hat.dm index 426ab39b3edb9..a8247a55603e2 100644 --- a/code/modules/clothing/head/hat.dm +++ b/code/modules/clothing/head/hat.dm @@ -352,9 +352,3 @@ icon_state = "paper" worn_icon_state = "paper" dog_fashion = /datum/dog_fashion/head - -/obj/item/clothing/head/hats/janitor_doppler - name = "janitor cap" - desc = "A regal purple cap to keep your head clean as you clean the filthy." - icon_state = "janitor_doppler" - inhand_icon_state = "greyscale_softcap" diff --git a/code/modules/clothing/head/perceptomatrix.dm b/code/modules/clothing/head/perceptomatrix.dm new file mode 100644 index 0000000000000..4250a1e399663 --- /dev/null +++ b/code/modules/clothing/head/perceptomatrix.dm @@ -0,0 +1,248 @@ + +#define PERCEPTOMATRIX_INACTIVE_FLAGS SNUG_FIT|STACKABLE_HELMET_EXEMPT|STOPSPRESSUREDAMAGE|BLOCK_GAS_SMOKE_EFFECT +#define PERCEPTOMATRIX_ACTIVE_FLAGS PERCEPTOMATRIX_INACTIVE_FLAGS|CASTING_CLOTHES // we love casting spells + +/// Helmet which can turn you into a BEAST!! once an anomaly core is inserted +/obj/item/clothing/head/helmet/perceptomatrix + name = "perceptomatrix helm" + desc = "This piece of headgear harnesses the energies of a hallucinative anomaly to create a safe audiovisual replica of -all- external stimuli directly into the cerebral cortex, \ + granting the user effective immunity to both psychic threats, and anything that would affect their perception - be it ear, eye, or even brain damage. \ + It can also violently discharge said energy, inducing hallucinations in others." + icon_state = "perceptomatrix_helmet_inactive" + worn_icon_state = "perceptomatrix_helmet_inactive" + base_icon_state = "perceptomatrix_helmet" + force = 10 + dog_fashion = null + cold_protection = HEAD + min_cold_protection_temperature = HELMET_MIN_TEMP_PROTECT + heat_protection = HEAD + max_heat_protection_temperature = HELMET_MAX_TEMP_PROTECT + strip_delay = 8 SECONDS + clothing_flags = PERCEPTOMATRIX_ACTIVE_FLAGS + clothing_traits = list( + /* eye/ear protection */ + TRAIT_NOFLASH, + TRAIT_TRUE_NIGHT_VISION, + TRAIT_SIGHT_BYPASS, + TRAIT_EXPANDED_FOV, + TRAIT_GOOD_HEARING, + /* mental protection */ + TRAIT_PERCEPTUAL_TRAUMA_BYPASS, + TRAIT_RDS_SUPPRESSED, + TRAIT_MADNESS_IMMUNE, + TRAIT_HALLUCINATION_IMMUNE, + /* psychic protection */ + TRAIT_NO_MINDSWAP, + TRAIT_UNCONVERTABLE, + ) + flags_cover = HEADCOVERSEYES|EARS_COVERED + flags_inv = HIDEHAIR|HIDEFACE + flash_protect = FLASH_PROTECTION_WELDER_SENSITIVE + resistance_flags = FIRE_PROOF | ACID_PROOF + equip_sound = 'sound/items/handling/helmet/helmet_equip1.ogg' + pickup_sound = 'sound/items/handling/helmet/helmet_pickup1.ogg' + drop_sound = 'sound/items/handling/helmet/helmet_drop1.ogg' + armor_type = /datum/armor/head_helmet_matrix + actions_types = list(/datum/action/cooldown/spell/pointed/percept_hallucination) + + /// If we have a core or not + var/core_installed = FALSE + /// Active components to add onto the mob, deleted and created on core installation/removal + var/list/active_components = list() + +// weaker overall but better against energy +/datum/armor/head_helmet_matrix + melee = 15 + bullet = 15 + laser = 45 + energy = 60 + bomb = 15 + fire = 50 + acid = 50 + wound = 10 + +/obj/item/clothing/head/helmet/perceptomatrix/Initialize(mapload) + . = ..() + + update_appearance(UPDATE_ICON_STATE) + update_anomaly_state() + +/obj/item/clothing/head/helmet/perceptomatrix/equipped(mob/living/user, slot) + . = ..() + if(slot & ITEM_SLOT_HEAD) + RegisterSignal(user, COMSIG_MOB_BEFORE_SPELL_CAST, PROC_REF(pre_cast_core_check)) + +/obj/item/clothing/head/helmet/perceptomatrix/dropped(mob/living/user, silent) + UnregisterSignal(user, COMSIG_MOB_BEFORE_SPELL_CAST) + ..() + +// Prevent casting the spell w/o the core. +/obj/item/clothing/head/helmet/perceptomatrix/proc/pre_cast_core_check(mob/caster, datum/action/cooldown/spell/spell) + SIGNAL_HANDLER + if((!core_installed) && spell.school == SCHOOL_PSYCHIC) + to_chat(caster, span_warning("You can't zap minds through [src]'s shielding without a core installed!")) + return SPELL_CANCEL_CAST + +/obj/item/clothing/head/helmet/perceptomatrix/proc/update_anomaly_state() + + // If the core isn't installed, or it's temporarily deactivated, disable special functions. + if(!core_installed) + clothing_flags = PERCEPTOMATRIX_INACTIVE_FLAGS + detach_clothing_traits(clothing_traits) + QDEL_LIST(active_components) + RemoveElement(/datum/element/wearable_client_colour, /datum/client_colour/perceptomatrix, ITEM_SLOT_HEAD, forced = TRUE) + return + + clothing_flags = PERCEPTOMATRIX_ACTIVE_FLAGS + attach_clothing_traits(initial(clothing_traits)) + + // When someone makes TRAIT_DEAF an element, or status effect, or whatever, give this item a way to bypass said deafness. + // just blocking future instances of deafness isn't what the item is meant to do but there's no proper way to do it otherwise at the moment. + active_components += AddComponent(/datum/component/wearertargeting/earprotection, list(ITEM_SLOT_HEAD), reduce_amount = 2) // should be same as highest value + active_components += AddComponent( + /datum/component/anti_magic, \ + antimagic_flags = MAGIC_RESISTANCE_MIND, \ + inventory_flags = ITEM_SLOT_HEAD, \ + ) + AddElement(/datum/element/wearable_client_colour, /datum/client_colour/perceptomatrix, ITEM_SLOT_HEAD, forced = TRUE) + + update_icon_state() + +/obj/item/clothing/head/helmet/perceptomatrix/Destroy(force) + QDEL_LIST(active_components) + return ..() + +/obj/item/clothing/head/helmet/perceptomatrix/examine(mob/user) + . = ..() + if (!core_installed) + . += span_warning("It requires a hallucination anomaly core in order to function.") + +/obj/item/clothing/head/helmet/perceptomatrix/item_action_slot_check(slot, mob/user, datum/action/action) + return slot & ITEM_SLOT_HEAD + +/obj/item/clothing/head/helmet/perceptomatrix/update_icon_state() + icon_state = base_icon_state + (core_installed ? "" : "_inactive") + worn_icon_state = base_icon_state + (core_installed ? "" : "_inactive") + return ..() + +/obj/item/clothing/head/helmet/perceptomatrix/item_interaction(mob/user, obj/item/weapon, params) + if (!istype(weapon, /obj/item/assembly/signaler/anomaly/hallucination)) + return NONE + balloon_alert(user, "inserting...") + if (!do_after(user, delay = 3 SECONDS, target = src)) + return ITEM_INTERACT_BLOCKING + qdel(weapon) + core_installed = TRUE + update_anomaly_state() + update_appearance(UPDATE_ICON_STATE) + playsound(src, 'sound/machines/crate/crate_open.ogg', 50, FALSE) + return ITEM_INTERACT_SUCCESS + +/obj/item/clothing/head/helmet/perceptomatrix/functioning + core_installed = TRUE + +/datum/action/cooldown/spell/pointed/percept_hallucination + name = "Hallucinate" + desc = "Redirect perceptual energies towards a target, staggering them." + button_icon_state = "blind" + ranged_mousepointer = 'icons/effects/mouse_pointers/blind_target.dmi' + + sound = 'sound/items/weapons/emitter2.ogg' + school = SCHOOL_PSYCHIC + cooldown_time = 15 SECONDS + + invocation_type = INVOCATION_NONE + spell_requirements = NONE + antimagic_flags = MAGIC_RESISTANCE_MIND + + active_msg = "You prepare to zap a target with hallucinations..." + + /// The amount of blurriness to apply + var/eye_blur_duration = 7 SECONDS + /// The amount of stagger to apply + var/stagger_duration = 3 SECONDS + /// The amount of hallucination to apply + var/hallucination_duration = 25 SECONDS + /// Spark system + var/datum/effect_system/spark_spread/quantum/spark_sys + +/datum/action/cooldown/spell/pointed/percept_hallucination/New(Target) + . = ..() + + spark_sys = new /datum/effect_system/spark_spread/quantum + +/datum/action/cooldown/spell/pointed/percept_hallucination/Destroy() + QDEL_NULL(spark_sys) + return ..() + +/datum/action/cooldown/spell/pointed/percept_hallucination/is_valid_target(atom/cast_on) + . = ..() + if(!.) + return FALSE + if(ishuman(cast_on)) + return TRUE + if(istype(cast_on, /obj/item/food/pancakes)) + return TRUE + + return FALSE + +/datum/action/cooldown/spell/pointed/percept_hallucination/proc/blows_up_pancakes_with_mind(obj/item/food/pancakes/pancakes) + + owner.visible_message( + span_userdanger("[owner] blows up [pancakes] with [owner.p_their()] mind!"), + span_userdanger("You blow up [pancakes] with your mind!") + ) + + for(var/mob/chef in get_hearers_in_view(7, pancakes)) + if(!chef.mind) + continue + // if cooked by chef, or if EITHER 5% chance OR its april fools. a || (b || c) + if(HAS_TRAIT_FROM(pancakes, TRAIT_FOOD_CHEF_MADE, REF(chef.mind)) || (prob(5) || check_holidays(APRIL_FOOLS))) + chef.say("Ma fuckin' pancakes!") + + playsound(pancakes, 'sound/effects/fuse.ogg', 80) + animate(pancakes, time = 1, pixel_z = 12, easing = ELASTIC_EASING) + animate(time = 1, pixel_z = 0, easing = BOUNCE_EASING) + for(var/i in 1 to 15) + animate(color = (i % 2) ? "#ffffff": "#ff6739", time = 1, easing = QUAD_EASING, flags = ANIMATION_CONTINUE) + + addtimer(CALLBACK(src, PROC_REF(pancake_explosion), pancakes), 1.5 SECONDS) + +/datum/action/cooldown/spell/pointed/percept_hallucination/proc/pancake_explosion(obj/pancakes) + explosion(pancakes, devastation_range = -1, heavy_impact_range = -1, light_impact_range = 1, flame_range = 2) + qdel(pancakes) + StartCooldown() + +/datum/action/cooldown/spell/pointed/percept_hallucination/proc/cast_fx(atom/cast_on) + owner.Beam(cast_on, icon_state = "greyscale_lightning", beam_color = COLOR_FADED_PINK, time = 0.5 SECONDS) + + spark_sys.set_up(2, 1, get_turf(owner)) + spark_sys.start() + spark_sys.set_up(4, 1, get_turf(cast_on)) + spark_sys.start() + +/datum/action/cooldown/spell/pointed/percept_hallucination/cast(mob/living/carbon/human/cast_on) + . = ..() + + cast_fx(cast_on) + + if(istype(cast_on, /obj/item/food/pancakes)) + blows_up_pancakes_with_mind(cast_on) + return + + if(cast_on.can_block_magic(antimagic_flags)) + to_chat(cast_on, span_notice("You feel psychic energies reflecting off you.")) + to_chat(owner, span_warning("[cast_on] deflects the energy!")) + return + + to_chat(cast_on, span_warning("Your brain feels like it's on fire!")) + cast_on.emote("scream") + cast_on.set_eye_blur_if_lower(eye_blur_duration) + cast_on.adjust_staggered(stagger_duration) + cast_on.apply_status_effect(/datum/status_effect/hallucination, hallucination_duration, \ + hallucination_duration * 0.2, hallucination_duration) // lower/upper hallucination freq. bound + + return + +#undef PERCEPTOMATRIX_INACTIVE_FLAGS +#undef PERCEPTOMATRIX_ACTIVE_FLAGS diff --git a/code/modules/clothing/masks/gasmask.dm b/code/modules/clothing/masks/gasmask.dm index afbdeef519224..bae0225c021a4 100644 --- a/code/modules/clothing/masks/gasmask.dm +++ b/code/modules/clothing/masks/gasmask.dm @@ -94,9 +94,6 @@ GLOBAL_LIST_INIT(clown_mask_options, list( var/valid_wearer = ismob(loc) var/mob/wearer = loc if(istype(tool, /obj/item/cigarette)) - if(flags_cover & MASKCOVERSMOUTH) - balloon_alert(user, "mask's mouth is covered!") - return ..() if(max_filters <= 0 || cig) balloon_alert(user, "can't hold that!") @@ -240,7 +237,7 @@ GLOBAL_LIST_INIT(clown_mask_options, list( /obj/item/clothing/mask/gas/welding/adjust_visor(mob/living/user) . = ..() if(.) - playsound(src, 'sound/vehicles/mecha/mechmove03.ogg', 50, TRUE) + playsound(src, up ? SFX_VISOR_UP : SFX_VISOR_DOWN, 50, TRUE) if(!fishing_modifier) return if(up) diff --git a/code/modules/clothing/shoes/galoshes.dm b/code/modules/clothing/shoes/galoshes.dm index 584ab3ff72ced..d42b8ffddb388 100644 --- a/code/modules/clothing/shoes/galoshes.dm +++ b/code/modules/clothing/shoes/galoshes.dm @@ -39,8 +39,3 @@ var/turf/open/t_loc = get_turf(src) SEND_SIGNAL(t_loc, COMSIG_TURF_MAKE_DRY, TURF_WET_WATER, TRUE, INFINITY) - -/obj/item/clothing/shoes/galoshes/doppler - name = "purple galoshes" - desc = "A pair of purple rubber boots, designed to prevent slipping on wet surfaces." - icon_state = "galoshes_doppler" diff --git a/code/modules/clothing/spacesuits/plasmamen.dm b/code/modules/clothing/spacesuits/plasmamen.dm index 0a672d5566ac3..903142fdaa203 100644 --- a/code/modules/clothing/spacesuits/plasmamen.dm +++ b/code/modules/clothing/spacesuits/plasmamen.dm @@ -139,7 +139,7 @@ to_chat(user, span_notice("Your helmet's torch can't pass through your welding visor!")) set_light_on(FALSE) helmet_on = FALSE - playsound(src, 'sound/vehicles/mecha/mechmove03.ogg', 50, TRUE) //Visors don't just come from nothing + playsound(src, up ? SFX_VISOR_UP : SFX_VISOR_DOWN, 50, TRUE) update_appearance() /obj/item/clothing/head/helmet/space/plasmaman/update_icon_state() diff --git a/code/modules/clothing/suits/jobs.dm b/code/modules/clothing/suits/jobs.dm index 2976314e60e5f..affe103e307bf 100644 --- a/code/modules/clothing/suits/jobs.dm +++ b/code/modules/clothing/suits/jobs.dm @@ -56,16 +56,6 @@ . = ..() AddComponent(/datum/component/adjust_fishing_difficulty, -4) -//Janitor -/obj/item/clothing/suit/apron/janitor_cloak - name = "waterproof poncho" - desc = "A transparent, waterproof cloak for your cleaning needs." - icon_state = "janicloak" - inhand_icon_state = null - body_parts_covered = CHEST|GROIN|ARMS - - - //Captain /obj/item/clothing/suit/jacket/capjacket name = "captain's parade jacket" diff --git a/code/modules/clothing/under/jobs/civilian/civilian.dm b/code/modules/clothing/under/jobs/civilian/civilian.dm index b0246f2deca66..35eb2db3029dd 100644 --- a/code/modules/clothing/under/jobs/civilian/civilian.dm +++ b/code/modules/clothing/under/jobs/civilian/civilian.dm @@ -108,24 +108,6 @@ female_sprite_flags = FEMALE_UNIFORM_TOP_ONLY can_adjust = FALSE -/obj/item/clothing/under/rank/civilian/janitor/doppler - name = "janitor uniform" - desc = "It's the official uniform of the station's janitor. It has minor protection from biohazards." - icon_state = "janitor_doppler" - inhand_icon_state = "janitor" - body_parts_covered = CHEST|GROIN - can_adjust = TRUE - alt_covers_chest = TRUE - -/obj/item/clothing/under/rank/civilian/janitor/doppler_ct - name = "janitor crop top" - desc = "It's the unofficial uniform of the station's janitor. It has minor protection from biohazards." - icon_state = "janitor_doppler_ct" - inhand_icon_state = "janitor" - body_parts_covered = CHEST|GROIN - can_adjust = TRUE - alt_covers_chest = TRUE - /obj/item/clothing/under/rank/civilian/lawyer name = "Lawyer suit" desc = "Slick threads." diff --git a/code/modules/detectivework/evidence.dm b/code/modules/detectivework/evidence.dm index c81852958b4a8..59e2f0feb86b1 100644 --- a/code/modules/detectivework/evidence.dm +++ b/code/modules/detectivework/evidence.dm @@ -18,23 +18,13 @@ max_slots = 1, max_specific_storage = WEIGHT_CLASS_NORMAL, ) + atom_storage.allow_quick_gather = TRUE + atom_storage.collection_mode = COLLECT_ONE RegisterSignal(atom_storage, COMSIG_STORAGE_STORED_ITEM, PROC_REF(on_insert)) RegisterSignal(atom_storage, COMSIG_STORAGE_REMOVED_ITEM, PROC_REF(on_remove)) atom_storage.rustle_sound = 'sound/items/evidence_bag/evidence_bag_zip.ogg' atom_storage.remove_rustle_sound = 'sound/items/evidence_bag/evidence_bag_unzip.ogg' -/obj/item/evidencebag/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) - if(interacting_with == loc || !isitem(interacting_with) || HAS_TRAIT(interacting_with, TRAIT_COMBAT_MODE_SKIP_INTERACTION)) - return NONE - if(atom_storage.attempt_insert(interacting_with, user)) - return ITEM_INTERACT_SUCCESS - return NONE - -/obj/item/evidencebag/item_interaction(mob/living/user, obj/item/tool, list/modifiers) - if(atom_storage.attempt_insert(tool, user)) - return ITEM_INTERACT_SUCCESS - return NONE - /obj/item/evidencebag/update_desc(updates) . = ..() if(!atom_storage.get_total_weight()) @@ -65,12 +55,15 @@ /obj/item/evidencebag/proc/on_insert(datum/storage/storage, obj/item/to_insert, mob/user, force) SIGNAL_HANDLER + update_weight_class(to_insert.w_class) /obj/item/evidencebag/proc/on_remove(datum/storage/storage, obj/item/to_remove, atom/remove_to_loc, silent) SIGNAL_HANDLER + if(!atom_storage.get_total_weight()) return + update_weight_class(WEIGHT_CLASS_TINY) /obj/item/evidencebag/attack_self(mob/user) diff --git a/code/modules/escape_menu/escape_menu.dm b/code/modules/escape_menu/escape_menu.dm index 57fe4b88813cc..38d456594de51 100644 --- a/code/modules/escape_menu/escape_menu.dm +++ b/code/modules/escape_menu/escape_menu.dm @@ -47,6 +47,10 @@ GLOBAL_LIST_EMPTY(escape_menus) RegisterSignal(client, COMSIG_QDELETING, PROC_REF(on_client_qdel)) RegisterSignal(client, COMSIG_CLIENT_MOB_LOGIN, PROC_REF(on_client_mob_login)) + SEND_SOUND(client, 'sound/misc/escape_menu/esc_open.ogg') + var/sound/esc_middle = sound('sound/misc/escape_menu/esc_middle.ogg', repeat = FALSE, channel = CHANNEL_ESCAPEMENU, volume = 80) + SEND_SOUND(client, esc_middle) + if (!isnull(ckey)) GLOB.escape_menus[ckey] = src @@ -57,6 +61,10 @@ GLOBAL_LIST_EMPTY(escape_menus) GLOB.escape_menus -= ckey plane_master_controller.remove_filter("escape_menu_blur") + var/sound/esc_clear = sound(null, repeat = FALSE, channel = CHANNEL_ESCAPEMENU) //yes, I'm doing it like this with a null, no its absolutely intentional, cuts off the sound right as needed. + SEND_SOUND(client, esc_clear) + SEND_SOUND(client, 'sound/misc/escape_menu/esc_close.ogg') + return ..() /datum/escape_menu/proc/on_client_qdel() diff --git a/code/modules/events/wormholes.dm b/code/modules/events/wormholes.dm index 685c24fcc2779..0284bef43724c 100644 --- a/code/modules/events/wormholes.dm +++ b/code/modules/events/wormholes.dm @@ -65,7 +65,7 @@ GLOBAL_LIST_EMPTY(all_wormholes) // So we can pick wormholes to teleport to . = ..() GLOB.all_wormholes -= src -/obj/effect/portal/wormhole/teleport(atom/movable/M) +/obj/effect/portal/wormhole/teleport(atom/movable/M, force = FALSE) if(iseffect(M)) //sparks don't teleport return if(M.anchored) diff --git a/code/modules/fishing/bait.dm b/code/modules/fishing/bait.dm index aad7a8d3d1d89..275f387cbdae7 100644 --- a/code/modules/fishing/bait.dm +++ b/code/modules/fishing/bait.dm @@ -63,7 +63,7 @@ /obj/item/fishing_lure name = "artificial minnow" - desc = "A fishing lure meant to attract smaller omnivore fish." + desc = "A fishing lure that may attract small fish. Too tiny, too large, or too picky prey won't be interested in it, though." icon = 'icons/obj/fishing.dmi' icon_state = "minnow" w_class = WEIGHT_CLASS_SMALL @@ -129,8 +129,8 @@ return multiplier /obj/item/fishing_lure/plug - name = "big plug lure" - desc = "A fishing lure used to catch larger omnivore fish." + name = "artificial plug lure" + desc = "A bigger fishing lure that may attract larger fish. Tiny or picky prey will remain uninterested." icon_state = "plug" /obj/item/fishing_lure/plug/is_catchable_fish(obj/item/fish/fish_type, list/fish_properties) @@ -164,7 +164,7 @@ /obj/item/fishing_lure/spoon name = "\improper Indy spoon lure" - desc = "A lustrous piece of metal mimicking the scales of a fish. Good for catching small to medium freshwater omnivore fish." + desc = "A lustrous piece of metal mimicking the scales of a fish. It specializes in catching small-to-medium-sized fish that live in freshwater." icon_state = "spoon" spin_frequency = list(1.25 SECONDS, 2.25 SECONDS) @@ -184,7 +184,7 @@ /obj/item/fishing_lure/artificial_fly name = "\improper Silkbuzz artificial fly" - desc = "A fishing lure resembling a large wooly fly. Good for catching all sort of picky fish." + desc = "A fishing lure resembling a large wooly fly. Unlike most other lures, it's fancy enough to catch the interest of picky fish, but only those." icon_state = "artificial_fly" spin_frequency = list(1.1 SECONDS, 2 SECONDS) @@ -196,7 +196,7 @@ /obj/item/fishing_lure/led name = "\improper LED fishing lure" - desc = "A heavy, waterproof and fish-looking LED stick, used to catch abyssal and demersal fish alike." + desc = "A heavy, waterproof and fish-looking LED stick, specialized to catch only nocturnal and deep-dwelling fish." icon_state = "led" spin_frequency = list(3 SECONDS, 3.8 SECONDS) @@ -224,7 +224,7 @@ /obj/item/fishing_lure/lucky_coin name = "\improper Maneki-Coin lure" - desc = "A faux-gold lure used to attract shiny-loving fish." + desc = "A faux-gold lure. Catches the attention of fishies that love shinies. Not nearly tasty-looking enough for anything else." icon_state = "lucky_coin" spin_frequency = list(1.5 SECONDS, 2.7 SECONDS) @@ -244,7 +244,7 @@ /obj/item/fishing_lure/algae name = "plastic algae lure" - desc = "A soft clump of fake algae used to attract herbivore water critters." + desc = "A soft clump of fake algae. Herbivores love it. Nothing else does, not even omnivores." icon_state = "algae" spin_frequency = list(3 SECONDS, 5 SECONDS) @@ -256,7 +256,7 @@ /obj/item/fishing_lure/grub name = "\improper Twister Worm lure" - desc = "A soft plastic lure with the body of a grub and a twisting tail. Good for panfish and other small omnivore fish." + desc = "A soft plastic lure with the body of a grub and a twisting tail. Specialized for catching small fish, as long as they aren't herbivores, picky, or picky herbivores." icon_state = "grub" spin_frequency = list(1 SECONDS, 2.7 SECONDS) @@ -270,7 +270,7 @@ /obj/item/fishing_lure/buzzbait name = "\improper Electric-Buzz lure" - desc = "A metallic, colored clanked attached to a series of cables that somehow attract shock-worthy fish." + desc = "A metallic, colored clanker attached to a series of cables that somehow attract shock-worthy fish." icon_state = "buzzbait" spin_frequency = list(0.8 SECONDS, 1.7 SECONDS) @@ -282,7 +282,7 @@ /obj/item/fishing_lure/spinnerbait name = "spinnerbait lure" - desc = "A versatile lure, good for catching all sort of predatory freshwater fish." + desc = "A spinny, vulnerable lure, great for attracting freshwater predators, though omnivores won't be interested in it." icon_state = "spinnerbait" spin_frequency = list(2 SECONDS, 4 SECONDS) @@ -299,7 +299,7 @@ /obj/item/fishing_lure/daisy_chain name = "daisy chain lure" - desc = "A lure resembling a small school of fish, good for catching several saltwater predators." + desc = "A lure resembling a small school of fish. Saltwater predators love it, but not much else will." icon_state = "daisy_chain" spin_frequency = list(2 SECONDS, 4 SECONDS) diff --git a/code/modules/fishing/fish/_fish.dm b/code/modules/fishing/fish/_fish.dm index 8eee6f1663503..033e6e60f2f6e 100644 --- a/code/modules/fishing/fish/_fish.dm +++ b/code/modules/fishing/fish/_fish.dm @@ -237,7 +237,7 @@ span_notice("You release [src] into [interacting_with]. [goodbye_text]"), \ span_notice("You hear a splash.")) playsound(interacting_with, 'sound/effects/splash.ogg', 50) - SEND_SIGNAL(interacting_with, COMSIG_FISH_RELEASED_INTO, src) + SEND_SIGNAL(interacting_with, COMSIG_FISH_RELEASED_INTO, src, user) qdel(src) return ITEM_INTERACT_SUCCESS diff --git a/code/modules/fishing/fish/fish_traits.dm b/code/modules/fishing/fish/fish_traits.dm index 90a0aa2e75772..dd0edb7ca3d2f 100644 --- a/code/modules/fishing/fish/fish_traits.dm +++ b/code/modules/fishing/fish/fish_traits.dm @@ -806,4 +806,4 @@ GLOBAL_LIST_INIT(spontaneous_fish_traits, populate_spontaneous_fish_traits()) return var/init_alpha = initial(source.alpha) if(init_alpha != source.alpha) - animate(source.alpha, alpha = init_alpha, time = 1.2 SECONDS, easing = CIRCULAR_EASING|EASE_OUT) + animate(source, alpha = init_alpha, time = 1.2 SECONDS, easing = CIRCULAR_EASING|EASE_OUT) diff --git a/code/modules/fishing/fishing_equipment.dm b/code/modules/fishing/fishing_equipment.dm index 1b589e18be3da..ab72b0b0fb26e 100644 --- a/code/modules/fishing/fishing_equipment.dm +++ b/code/modules/fishing/fishing_equipment.dm @@ -12,8 +12,8 @@ icon = 'icons/obj/fishing.dmi' icon_state = "reel_blue" w_class = WEIGHT_CLASS_SMALL - ///A list of traits that this fishing line has, checked by fish traits and the minigame. - var/list/fishing_line_traits + ///A bitfield of traits that this fishing line has, checked by fish traits and the minigame. + var/fishing_line_traits /// Color of the fishing line var/line_color = COLOR_GRAY ///The description given to the autowiki @@ -146,11 +146,11 @@ icon_state = "hook" w_class = WEIGHT_CLASS_TINY - /// A list of traits that this fishing hook has, checked by fish traits and the minigame - var/list/fishing_hook_traits + /// A bitfield of traits that this fishing hook has, checked by fish traits and the minigame + var/fishing_hook_traits /// icon state added to main rod icon when this hook is equipped var/rod_overlay_icon_state = "hook_overlay" - /// What subtype of `/obj/item/chasm_detritus` do we fish out of chasms? Defaults to `/obj/item/chasm_detritus`. + /// What subtype of `/datum/chasm_detritus` do we fish out of chasms? Defaults to `/datum/chasm_detritus`. var/chasm_detritus_type = /datum/chasm_detritus ///The description given to the autowiki var/wiki_desc = "A generic fishing hook. You won't be able to fish without one." diff --git a/code/modules/fishing/fishing_rod.dm b/code/modules/fishing/fishing_rod.dm index 4bd045616b3e8..f554a475ad491 100644 --- a/code/modules/fishing/fishing_rod.dm +++ b/code/modules/fishing/fishing_rod.dm @@ -332,7 +332,7 @@ QDEL_NULL(fishing_line) var/beam_color = line?.line_color || default_line_color fishing_line = new(firer, target, icon_state = "fishing_line", beam_color = beam_color, emissive = FALSE, override_target_pixel_y = target_py) - fishing_line.lefthand = firer.get_held_index_of_item(src) % 2 == 1 + fishing_line.lefthand = IS_LEFT_INDEX(firer.get_held_index_of_item(src)) RegisterSignal(fishing_line, COMSIG_BEAM_BEFORE_DRAW, PROC_REF(check_los)) RegisterSignal(fishing_line, COMSIG_QDELETING, PROC_REF(clear_line)) INVOKE_ASYNC(fishing_line, TYPE_PROC_REF(/datum/beam/, Start)) diff --git a/code/modules/fishing/sources/source_types.dm b/code/modules/fishing/sources/source_types.dm index eafdbe989991d..e15f290cefe5b 100644 --- a/code/modules/fishing/sources/source_types.dm +++ b/code/modules/fishing/sources/source_types.dm @@ -27,6 +27,7 @@ fish_count_regen = list( /obj/item/fish/clownfish/lube = 3 MINUTES, /obj/item/fish/swordfish = 5 MINUTES, + /obj/structure/mystery_box/fishing = 32 MINUTES, ) fishing_difficulty = FISHING_DEFAULT_DIFFICULTY + 5 fish_source_flags = FISH_SOURCE_FLAG_EXPLOSIVE_MALUS @@ -358,7 +359,9 @@ fish_counts = list( /obj/structure/closet/crate/necropolis/tendril = 1 ) - + fish_count_regen = list( + /obj/structure/closet/crate/necropolis/tendril = 27 MINUTES, + ) fishing_difficulty = FISHING_DEFAULT_DIFFICULTY + 10 fish_source_flags = FISH_SOURCE_FLAG_EXPLOSIVE_MALUS @@ -386,6 +389,10 @@ /obj/item/stack/sheet/mineral/adamantine = 3, /obj/item/stack/sheet/mineral/runite = 2, ) + fish_count_regen = list( + /obj/item/stack/sheet/mineral/adamantine = 8 MINUTES, + /obj/item/stack/sheet/mineral/runite = 10 MINUTES, + ) overlay_state = "portal_plasma" /datum/fish_source/moisture_trap @@ -614,6 +621,9 @@ fish_counts = list( /mob/living/basic/carp/mega = 2, ) + fish_count_regen = list( + /mob/living/basic/carp/mega = 9 MINUTES, + ) fishing_difficulty = FISHING_DEFAULT_DIFFICULTY + 18 /datum/fish_source/deepfryer @@ -635,6 +645,7 @@ fish_count_regen = list( /obj/item/fish/fryish = 2 MINUTES, /obj/item/fish/fryish/fritterish = 6 MINUTES, + /obj/item/fish/fryish/nessie = 22 MINUTES, ) fishing_difficulty = FISHING_DEFAULT_DIFFICULTY + 13 diff --git a/code/modules/food_and_drinks/machinery/gibber.dm b/code/modules/food_and_drinks/machinery/gibber.dm index cd50f29ffe478..4703b9fae1d1b 100644 --- a/code/modules/food_and_drinks/machinery/gibber.dm +++ b/code/modules/food_and_drinks/machinery/gibber.dm @@ -182,7 +182,7 @@ var/typeofmeat = /obj/item/food/meat/slab/human var/typeofskin - var/obj/item/food/meat/slab/allmeat[meat_produced] + var/list/results = list() var/obj/item/stack/sheet/animalhide/skin var/list/datum/disease/diseases = mob_occupant.get_static_viruses() @@ -201,22 +201,29 @@ if(isalien(C)) typeofskin = /obj/item/stack/sheet/animalhide/xeno - var/occupant_volume - if(occupant?.reagents) - occupant_volume = occupant.reagents.total_volume - for (var/i=1 to meat_produced) + for (var/i in 1 to meat_produced) var/obj/item/food/meat/slab/newmeat = new typeofmeat newmeat.name = "[sourcename] [newmeat.name]" newmeat.set_custom_materials(list(GET_MATERIAL_REF(/datum/material/meat/mob_meat, occupant) = 4 * SHEET_MATERIAL_AMOUNT)) - if(istype(newmeat)) - newmeat.subjectname = sourcename - newmeat.reagents.add_reagent (/datum/reagent/consumable/nutriment, sourcenutriment / meat_produced) // Thehehe. Fat guys go first - if(occupant_volume) - occupant.reagents.trans_to(newmeat, occupant_volume / meat_produced, remove_blacklisted = TRUE) - if(sourcejob) - newmeat.subjectjob = sourcejob + if(!istype(newmeat)) + continue + newmeat.subjectname = sourcename + if(sourcejob) + newmeat.subjectjob = sourcejob + + results += newmeat + + SEND_SIGNAL(occupant, COMSIG_LIVING_GIBBER_ACT, user, src, results) + + var/reagents_in_produced = 0 + for(var/obj/item/result as anything in results) + if(result.reagents) + reagents_in_produced++ + + for(var/obj/item/result as anything in results) + occupant.reagents.trans_to(result, occupant.reagents.total_volume / reagents_in_produced, remove_blacklisted = TRUE) + result.reagents?.add_reagent(/datum/reagent/consumable/nutriment/fat, sourcenutriment / reagents_in_produced) // Thehehe. Fat guys go first - allmeat[i] = newmeat if(typeofskin) skin = new typeofskin @@ -227,9 +234,9 @@ mob_occupant.ghostize() set_occupant(null) qdel(mob_occupant) - addtimer(CALLBACK(src, PROC_REF(make_meat), skin, allmeat, meat_produced, gibtype, diseases), gibtime) + addtimer(CALLBACK(src, PROC_REF(make_meat), skin, results, meat_produced, gibtype, diseases), gibtime) -/obj/machinery/gibber/proc/make_meat(obj/item/stack/sheet/animalhide/skin, list/obj/item/food/meat/slab/allmeat, meat_produced, gibtype, list/datum/disease/diseases) +/obj/machinery/gibber/proc/make_meat(obj/item/stack/sheet/animalhide/skin, list/results, meat_produced, gibtype, list/datum/disease/diseases) playsound(src.loc, 'sound/effects/splat.ogg', 50, TRUE) operating = FALSE if (!dirty && prob(50)) @@ -239,9 +246,9 @@ if(skin) skin.forceMove(loc) skin.throw_at(pick(nearby_turfs),meat_produced,3) - for (var/i=1 to meat_produced) - var/obj/item/meatslab = allmeat[i] + var/iteration = 1 + for (var/obj/item/meatslab in results) if(LAZYLEN(diseases)) var/list/datum/disease/diseases_to_add = list() for(var/datum/disease/disease as anything in diseases) @@ -254,11 +261,15 @@ meatslab.AddComponent(/datum/component/infective, diseases_to_add) meatslab.forceMove(loc) - meatslab.throw_at(pick(nearby_turfs),i,3) - for (var/turfs=1 to meat_produced) - var/turf/gibturf = pick(nearby_turfs) - if (!gibturf.density && (src in view(gibturf))) - new gibtype(gibturf, i, diseases) + meatslab.throw_at(pick(nearby_turfs), iteration, 3) + + iteration++ + + for (var/i in 1 to meat_produced**2) //2 slabs: 4 giblets, 3 slabs: 9, etc. + var/turf/gibturf = pick(nearby_turfs) + if (!gibturf.density && (src in view(gibturf))) + new gibtype(gibturf, round(1 + i / meat_produced), diseases) + pixel_x = base_pixel_x //return to its spot after shaking operating = FALSE diff --git a/code/modules/food_and_drinks/machinery/smartfridge.dm b/code/modules/food_and_drinks/machinery/smartfridge.dm index 0481d1c491092..afd566b7e479d 100644 --- a/code/modules/food_and_drinks/machinery/smartfridge.dm +++ b/code/modules/food_and_drinks/machinery/smartfridge.dm @@ -526,7 +526,7 @@ /obj/machinery/smartfridge/drying/proc/toggle_drying(forceoff, mob/user) if(drying || forceoff) drying = FALSE - current_user = FALSE + current_user = null update_use_power(IDLE_POWER_USE) else drying = TRUE diff --git a/code/modules/hallucination/stray_bullet.dm b/code/modules/hallucination/stray_bullet.dm index 13ace2933350a..11f88c8c964ed 100644 --- a/code/modules/hallucination/stray_bullet.dm +++ b/code/modules/hallucination/stray_bullet.dm @@ -101,7 +101,6 @@ spawn_hit(target, TRUE) qdel(src) - return TRUE /// Called when a mob is hit by the fake projectile /obj/projectile/hallucination/proc/on_mob_hit(mob/living/hit_mob) diff --git a/code/modules/hydroponics/seeds.dm b/code/modules/hydroponics/seeds.dm index 4589a3c4312b5..e0e88f7c402d9 100644 --- a/code/modules/hydroponics/seeds.dm +++ b/code/modules/hydroponics/seeds.dm @@ -50,7 +50,7 @@ var/list/genes = list() /// A list of reagents to add to product. var/list/reagents_add - // Format: "reagent_id" = potency multiplier + // Format: /datum/reagent/type = potency multiplier // Stronger reagents must always come first to avoid being displaced by weaker ones. // Total amount of any reagent in plant is calculated by formula: max(round(potency * multiplier), 1) ///If the chance below passes, then this many weeds sprout during growth diff --git a/code/modules/jobs/job_types/janitor.dm b/code/modules/jobs/job_types/janitor.dm index 1d770bd2e9455..13a3496c609d3 100644 --- a/code/modules/jobs/job_types/janitor.dm +++ b/code/modules/jobs/job_types/janitor.dm @@ -37,10 +37,8 @@ jobtype = /datum/job/janitor id_trim = /datum/id_trim/job/janitor - uniform = /obj/item/clothing/under/rank/civilian/janitor/doppler - suit = /obj/item/clothing/suit/apron/janitor_cloak + uniform = /obj/item/clothing/under/rank/civilian/janitor belt = /obj/item/modular_computer/pda/janitor - gloves = /obj/item/clothing/gloves/botanic_leather/janitor ears = /obj/item/radio/headset/headset_srv skillchips = list(/obj/item/skillchip/job/janitor) backpack_contents = list(/obj/item/access_key) diff --git a/code/modules/jobs/job_types/security_officer.dm b/code/modules/jobs/job_types/security_officer.dm index 9b2dc91137cd5..a84d4e0e73765 100644 --- a/code/modules/jobs/job_types/security_officer.dm +++ b/code/modules/jobs/job_types/security_officer.dm @@ -83,7 +83,7 @@ GLOBAL_LIST_EMPTY(security_officer_distribution) var/ears = null var/accessory = null - var/list/dep_trim = null + var/datum/id_trim/dep_trim = null var/destination = null switch(department) diff --git a/code/modules/library/bibles.dm b/code/modules/library/bibles.dm index 99c28b76ff244..4c31092199dbe 100644 --- a/code/modules/library/bibles.dm +++ b/code/modules/library/bibles.dm @@ -367,8 +367,7 @@ GLOBAL_LIST_INIT(bibleitemstates, list( uses -= 1 to_chat(user, span_userdanger("You try to open the book AND IT BITES YOU!")) playsound(src.loc, 'sound/effects/snap.ogg', 50, TRUE) - var/active_hand_zone = (!(user.active_hand_index % RIGHT_HANDS) ? BODY_ZONE_R_ARM : BODY_ZONE_L_ARM) - user.apply_damage(5, BRUTE, active_hand_zone, attacking_item = src) + user.apply_damage(5, BRUTE, user.get_active_hand(), attacking_item = src) to_chat(user, span_notice("Your name appears on the inside cover, in blood.")) owner_name = user.real_name diff --git a/code/modules/mafia/abilities/investigative/reveal.dm b/code/modules/mafia/abilities/investigative/reveal.dm index 5e38d3c9fafa2..241610171569a 100644 --- a/code/modules/mafia/abilities/investigative/reveal.dm +++ b/code/modules/mafia/abilities/investigative/reveal.dm @@ -4,11 +4,11 @@ * During the night, revealing someone will announce their role when day comes. * This is one time use, we'll delete ourselves once done. */ -/datum/mafia_ability/reaveal_role +/datum/mafia_ability/reveal_role name = "Reveal" ability_action = "psychologically evaluate" -/datum/mafia_ability/reaveal_role/perform_action_target(datum/mafia_controller/game, datum/mafia_role/day_target) +/datum/mafia_ability/reveal_role/perform_action_target(datum/mafia_controller/game, datum/mafia_role/day_target) . = ..() if(!.) return FALSE @@ -17,7 +17,7 @@ target_role.reveal_role(game, verbose = TRUE) return TRUE -/datum/mafia_ability/vest/clean_action_refs(datum/mafia_controller/game) +/datum/mafia_ability/reveal_role/clean_action_refs(datum/mafia_controller/game) if(using_ability) host_role.role_unique_actions -= src qdel(src) diff --git a/code/modules/mafia/roles/town/town_investigative.dm b/code/modules/mafia/roles/town/town_investigative.dm index a09cff3acd28b..76b81eab3bd1b 100644 --- a/code/modules/mafia/roles/town/town_investigative.dm +++ b/code/modules/mafia/roles/town/town_investigative.dm @@ -20,7 +20,7 @@ hud_icon = "hudpsychologist" revealed_icon = "psychologist" - role_unique_actions = list(/datum/mafia_ability/reaveal_role) + role_unique_actions = list(/datum/mafia_ability/reveal_role) /datum/mafia_role/chaplain name = "Chaplain" diff --git a/code/modules/manufactorio/machines/crafter.dm b/code/modules/manufactorio/machines/crafter.dm index 4b3f2dba1c4b9..d164976b81a48 100644 --- a/code/modules/manufactorio/machines/crafter.dm +++ b/code/modules/manufactorio/machines/crafter.dm @@ -22,6 +22,7 @@ craftsman = AddComponent(/datum/component/personal_crafting/machine) if(ispath(recipe)) recipe = locate(recipe) in (cooking ? GLOB.cooking_recipes : GLOB.crafting_recipes) + START_PROCESSING(SSmanufacturing, src) /obj/machinery/power/manufacturing/crafter/examine(mob/user) . = ..() @@ -45,8 +46,7 @@ var/turf/machine_turf = get_turf(src) if(length(machine_turf.contents) >= MANUFACTURING_TURF_LAG_LIMIT) return MANUFACTURING_FAIL_FULL - receiving.Move(machine_turf, receive_dir) - START_PROCESSING(SSmanufacturing, src) + receiving.forceMove(machine_turf) return MANUFACTURING_SUCCESS /obj/machinery/power/manufacturing/crafter/multitool_act(mob/living/user, obj/item/tool) diff --git a/code/modules/manufactorio/machines/lathe.dm b/code/modules/manufactorio/machines/lathe.dm index 431d7af1c11db..351e5c25030a9 100644 --- a/code/modules/manufactorio/machines/lathe.dm +++ b/code/modules/manufactorio/machines/lathe.dm @@ -125,7 +125,7 @@ return var/craft_time = (design.construction_time * design.lathe_time_factor) ** 0.8 - flick_overlay_view(mutable_appearance(icon, "crafter_printing"), craft_time) + flick_overlay_view(mutable_appearance(icon, "lathe_printing"), craft_time) print_sound.start() add_load(power_cost) busy = addtimer(CALLBACK(src, PROC_REF(do_make_item), design, materials_needed), craft_time, TIMER_UNIQUE | TIMER_STOPPABLE | TIMER_DELETE_ME) diff --git a/code/modules/manufactorio/machines/sorter.dm b/code/modules/manufactorio/machines/sorter.dm index 247a96ea606f6..b1e45e708eb0f 100644 --- a/code/modules/manufactorio/machines/sorter.dm +++ b/code/modules/manufactorio/machines/sorter.dm @@ -125,21 +125,32 @@ return ismob(moving) ? moving.Move(get_step(src,dir), dir) : send_resource(moving, dir) /obj/machinery/power/manufacturing/sorter/process() - if(delay_timerid || !length(loc?.contents - 1)) + if(!anchored || delay_timerid || !length(loc?.contents - 1)) return launch_everything() +/// Is target something we should even attempt to start launching? +/obj/machinery/power/manufacturing/sorter/proc/can_be_launched(atom/movable/target) + . = TRUE + if(!istype(target) || target == src || target.anchored) //target is not movable, us or anchored + return FALSE + var/mob/living/probably_living = target + if(isdead(target) || (istype(probably_living) && probably_living.incorporeal_move)) //target is incorporeal + return FALSE + /obj/machinery/power/manufacturing/sorter/proc/on_entered(datum/source, atom/movable/mover) SIGNAL_HANDLER - if(mover == src || !istype(mover) || mover.anchored || delay_timerid) + if(!anchored || !can_be_launched(mover) || delay_timerid) return delay_timerid = addtimer(CALLBACK(src, PROC_REF(launch_everything)), 0.2 SECONDS) /obj/machinery/power/manufacturing/sorter/proc/launch_everything() delay_timerid = null + if(!anchored) + return var/turf/where_we_at = get_turf(src) for(var/atom/movable/mover as anything in where_we_at.contents) - if(mover.anchored) + if(!can_be_launched(mover)) continue for(var/datum/sortrouter_filter/sorting as anything in sort_filters) if(sorting.meets_conditions(mover) == sorting.inverted) diff --git a/code/modules/mapfluff/ruins/objects_and_mobs/ash_walker_den.dm b/code/modules/mapfluff/ruins/objects_and_mobs/ash_walker_den.dm index 7ef451ddc303a..ce57035a7661c 100644 --- a/code/modules/mapfluff/ruins/objects_and_mobs/ash_walker_den.dm +++ b/code/modules/mapfluff/ruins/objects_and_mobs/ash_walker_den.dm @@ -59,13 +59,13 @@ if(offeredmob.mind?.has_antag_datum(/datum/antagonist/ashwalker) && (offeredmob.ckey || offeredmob.get_ghost(FALSE, TRUE))) //special interactions for dead lava lizards with ghosts attached visible_message(span_warning("Serrated tendrils carefully pull [offeredmob] to [src], absorbing the body and creating it anew.")) - var/datum/mind/deadmind + var/mob/deadmob if(offeredmob.ckey) - deadmind = offeredmob + deadmob = offeredmob else - deadmind = offeredmob.get_ghost(FALSE, TRUE) - to_chat(deadmind, "Your body has been returned to the nest. You are being remade anew, and will awaken shortly.
Your memories will remain intact in your new body, as your soul is being salvaged") - SEND_SOUND(deadmind, sound('sound/effects/magic/enter_blood.ogg',volume=100)) + deadmob = offeredmob.get_ghost(FALSE, TRUE) + to_chat(deadmob, "Your body has been returned to the nest. You are being remade anew, and will awaken shortly.
Your memories will remain intact in your new body, as your soul is being salvaged") + SEND_SOUND(deadmob, sound('sound/effects/magic/enter_blood.ogg',volume=100)) addtimer(CALLBACK(src, PROC_REF(remake_walker), offeredmob), 20 SECONDS) offeredmob.forceMove(src) return diff --git a/code/modules/mapfluff/ruins/spaceruin_code/hauntedtradingpost.dm b/code/modules/mapfluff/ruins/spaceruin_code/hauntedtradingpost.dm index 39458ac942964..ac4f257dc2a52 100644 --- a/code/modules/mapfluff/ruins/spaceruin_code/hauntedtradingpost.dm +++ b/code/modules/mapfluff/ruins/spaceruin_code/hauntedtradingpost.dm @@ -245,7 +245,7 @@ //is this being used as part of the haunted trading post ruin? if true, will self destruct when boss dies var/donk_ai_slave = FALSE // machine that the trap inhabits - var/obj/structure/host_machine + var/obj/machinery/host_machine // turf that the trap is on var/turf/my_turf //how long until trap zaps everything, after it detects something diff --git a/code/modules/mapping/reader.dm b/code/modules/mapping/reader.dm index bca2ace626062..10d506f8c48e5 100644 --- a/code/modules/mapping/reader.dm +++ b/code/modules/mapping/reader.dm @@ -839,7 +839,7 @@ GLOBAL_LIST_EMPTY(map_model_default) if(member_string[length(member_string)] == "}") variables_start = findtext(member_string, "{") - var/path_text = trimtext(copytext(member_string, 1, variables_start)) + var/path_text = trim(copytext(member_string, 1, variables_start)) var/atom_def = text2path(path_text) //path definition, e.g /obj/foo/bar if(!ispath(atom_def, /atom)) // Skip the item if the path does not exist. Fix your crap, mappers! @@ -1011,7 +1011,7 @@ GLOBAL_LIST_EMPTY(map_model_default) // check if this is a simple variable (as in list(var1, var2)) or an associative one (as in list(var1="foo",var2=7)) var/equal_position = findtext(text,"=",old_position, position) - var/trim_left = trimtext(copytext(text,old_position,(equal_position ? equal_position : position))) + var/trim_left = trim(copytext(text,old_position,(equal_position ? equal_position : position))) var/left_constant = parse_constant(trim_left) if(position) old_position = position + length(text[position]) @@ -1021,7 +1021,7 @@ GLOBAL_LIST_EMPTY(map_model_default) if(equal_position && !isnum(left_constant)) // Associative var, so do the association. // Note that numbers cannot be keys - the RHS is dropped if so. - var/trim_right = trimtext(copytext(text, equal_position + length(text[equal_position]), position)) + var/trim_right = trim(copytext(text, equal_position + length(text[equal_position]), position)) var/right_constant = parse_constant(trim_right) .[left_constant] = right_constant else // simple var diff --git a/code/modules/mining/boulder_processing/boulder.dm b/code/modules/mining/boulder_processing/boulder.dm index e345f870f7874..9f2dba12ab291 100644 --- a/code/modules/mining/boulder_processing/boulder.dm +++ b/code/modules/mining/boulder_processing/boulder.dm @@ -158,8 +158,10 @@ /** * This function is called while breaking boulders manually, and drops ore based on the boulder's mineral content. * Quantity of ore spawned here is 1 less than if the boulder was processed by a machine, but clamped at 10 maximum, 1 minimum. + * + * target_destination: Optional - Sets the location directly instead of dropping it */ -/obj/item/boulder/proc/convert_to_ore() +/obj/item/boulder/proc/convert_to_ore(atom/target_destination) for(var/datum/material/picked in custom_materials) var/obj/item/stack/ore/cracked_ore // Take the associated value and convert it into ore stacks... var/quantity = clamp(round((custom_materials[picked] - SHEET_MATERIAL_AMOUNT)/SHEET_MATERIAL_AMOUNT), 1, 10) //but less resources than if they processed it by hand. @@ -168,7 +170,10 @@ if(isnull(cracked_ore_type)) stack_trace("boulder found containing material type [picked.type] with no set ore_type") continue - cracked_ore = new cracked_ore_type (drop_location(), quantity) + var/atom/ore_destination = drop_location() + if(target_destination) + ore_destination = target_destination + cracked_ore = new cracked_ore_type (ore_destination, quantity) SSblackbox.record_feedback("tally", "ore_mined", quantity, cracked_ore.type) ///Moves boulder contents to the drop location, and then deletes the boulder. diff --git a/code/modules/mining/equipment/grapple_gun.dm b/code/modules/mining/equipment/grapple_gun.dm index 0247d0164b025..fa7f0b0b73570 100644 --- a/code/modules/mining/equipment/grapple_gun.dm +++ b/code/modules/mining/equipment/grapple_gun.dm @@ -10,7 +10,7 @@ inhand_icon_state = "gun" item_flags = NOBLUDGEON ///overlay when the hook is retracted - var/static/mutable_appearance/hook_overlay = new(icon = 'icons/obj/mining.dmi', icon_state = "grapple_gun_hooked") + var/static/mutable_appearance/hook_overlay = mutable_appearance(icon = 'icons/obj/mining.dmi', icon_state = "grapple_gun_hooked") ///is the hook retracted var/hooked = TRUE ///addtimer id for launching the user diff --git a/code/modules/mining/equipment/wormhole_jaunter.dm b/code/modules/mining/equipment/wormhole_jaunter.dm index 6ffcfa7bc6752..fa9b63a4658a7 100644 --- a/code/modules/mining/equipment/wormhole_jaunter.dm +++ b/code/modules/mining/equipment/wormhole_jaunter.dm @@ -103,7 +103,7 @@ light_on = FALSE wibbles = FALSE -/obj/effect/portal/jaunt_tunnel/teleport(atom/movable/M) +/obj/effect/portal/jaunt_tunnel/teleport(atom/movable/M, force = FALSE) . = ..() if(.) // KERPLUNK diff --git a/code/modules/mining/lavaland/tendril_loot.dm b/code/modules/mining/lavaland/tendril_loot.dm index fe338b35ccb93..cfcffa6fea17d 100644 --- a/code/modules/mining/lavaland/tendril_loot.dm +++ b/code/modules/mining/lavaland/tendril_loot.dm @@ -760,8 +760,10 @@ berserk_value *= PROJECTILE_HIT_MULTIPLIER berserk_charge = clamp(round(berserk_charge + berserk_value), 0, MAX_BERSERK_CHARGE) if(berserk_charge >= MAX_BERSERK_CHARGE) + var/datum/action/item_action/berserk_mode/ragemode = locate() in actions to_chat(owner, span_notice("Berserk mode is fully charged.")) balloon_alert(owner, "berserk charged") + ragemode?.build_all_button_icons(UPDATE_BUTTON_STATUS) /obj/item/clothing/head/hooded/berserker/IsReflect() if(berserk_active) @@ -769,6 +771,7 @@ /// Starts berserk, reducing incoming brute by 50%, doubled attacking speed, NOGUNS trait, adding a color and giving them the berserk movespeed modifier /obj/item/clothing/head/hooded/berserker/proc/berserk_mode(mob/living/carbon/human/user) + var/datum/action/item_action/berserk_mode/ragemode = locate() in actions to_chat(user, span_warning("You enter berserk mode.")) playsound(user, 'sound/effects/magic/staff_healing.ogg', 50) user.add_movespeed_modifier(/datum/movespeed_modifier/berserk) @@ -779,6 +782,7 @@ ADD_TRAIT(src, TRAIT_NODROP, BERSERK_TRAIT) berserk_active = TRUE START_PROCESSING(SSobj, src) + ragemode?.build_all_button_icons(UPDATE_BUTTON_STATUS) /// Ends berserk, reverting the changes from the proc [berserk_mode] /obj/item/clothing/head/hooded/berserker/proc/end_berserk(mob/living/carbon/human/user) @@ -787,6 +791,8 @@ berserk_active = FALSE if(QDELETED(user)) return + var/datum/action/item_action/berserk_mode/ragemode = locate() in actions + ragemode?.build_all_button_icons(UPDATE_BUTTON_STATUS) to_chat(user, span_warning("You exit berserk mode.")) playsound(user, 'sound/effects/magic/summonitems_generic.ogg', 50) user.remove_movespeed_modifier(/datum/movespeed_modifier/berserk) diff --git a/code/modules/mining/machine_redemption.dm b/code/modules/mining/machine_redemption.dm index 312acb6672014..24e0f53a87ab7 100644 --- a/code/modules/mining/machine_redemption.dm +++ b/code/modules/mining/machine_redemption.dm @@ -229,21 +229,27 @@ for(var/datum/material/material as anything in mat_container.materials) var/amount = mat_container.materials[material] var/sheet_amount = amount / SHEET_MATERIAL_AMOUNT + var/obj/sheet_type = material.sheet_type data["materials"] += list(list( "name" = material.name, "id" = REF(material), "amount" = sheet_amount, "category" = "material", "value" = ore_values[material.type], + "icon" = sheet_type::icon, + "icon_state" = sheet_type::icon_state, )) for(var/research in stored_research.researched_designs) var/datum/design/alloy = SSresearch.techweb_design_by_id(research) + var/obj/alloy_type = alloy.build_path data["materials"] += list(list( "name" = alloy.name, "id" = alloy.id, "category" = "alloy", "amount" = can_smelt_alloy(alloy), + "icon" = alloy_type::icon, + "icon_state" = alloy_type::icon_state, )) data["disconnected"] = null @@ -274,29 +280,6 @@ ) return data -/obj/machinery/mineral/ore_redemption/ui_static_data(mob/user) - var/list/data = list() - - var/datum/component/material_container/mat_container = materials.mat_container - if (mat_container) - for(var/datum/material/material as anything in mat_container.materials) - var/obj/material_display = initial(material.sheet_type) - data["material_icons"] += list(list( - "id" = REF(material), - "product_icon" = icon2base64(getFlatIcon(image(icon = initial(material_display.icon), icon_state = initial(material_display.icon_state)), no_anim=TRUE)), - )) - - for(var/research in stored_research.researched_designs) - var/datum/design/alloy = SSresearch.techweb_design_by_id(research) - var/obj/alloy_display = initial(alloy.build_path) - data["material_icons"] += list(list( - "id" = alloy.id, - "product_icon" = icon2base64(getFlatIcon(image(icon = initial(alloy_display.icon), icon_state = initial(alloy_display.icon_state)), no_anim=TRUE)), - )) - - return data - - /obj/machinery/mineral/ore_redemption/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state) . = ..() if(.) diff --git a/code/modules/mining/satchel_ore_box.dm b/code/modules/mining/satchel_ore_box.dm index 94be35108d0b0..2745bdb5d09d7 100644 --- a/code/modules/mining/satchel_ore_box.dm +++ b/code/modules/mining/satchel_ore_box.dm @@ -66,6 +66,13 @@ else return ..() +/obj/structure/ore_box/Entered(atom/movable/arrived, atom/old_loc, list/atom/old_locs) + . = ..() + if(istype(arrived, /obj/item/boulder) && ismecha(loc)) //Boulders being put into a mech's orebox get processed + var/obj/item/boulder/to_process = arrived + to_process.convert_to_ore(src) + qdel(to_process) + /obj/structure/ore_box/ui_interact(mob/user, datum/tgui/ui) ui = SStgui.try_update_ui(user, src, ui) if(!ui) diff --git a/code/modules/mining/shelters.dm b/code/modules/mining/shelters.dm index 539854a394756..5a08b29202208 100644 --- a/code/modules/mining/shelters.dm +++ b/code/modules/mining/shelters.dm @@ -17,7 +17,7 @@ /datum/map_template/shelter/New() . = ..() blacklisted_turfs = typecacheof(/turf/closed) - banned_areas = typecacheof(/area/shuttle) + banned_areas = typecacheof(list(/area/shuttle, /area/station/holodeck)) /datum/map_template/shelter/proc/check_deploy(turf/deploy_location, obj/item/survivalcapsule/capsule, ignore_flags = NONE) var/affected = get_affected_turfs(deploy_location, centered=TRUE) diff --git a/code/modules/mob/inventory.dm b/code/modules/mob/inventory.dm index ee173795c1321..14e38e65144b3 100644 --- a/code/modules/mob/inventory.dm +++ b/code/modules/mob/inventory.dm @@ -16,7 +16,7 @@ //So we're treating each "pair" of limbs as a team, so "both" refers to them /mob/proc/get_inactive_hand_index() var/other_hand = 0 - if(!(active_hand_index % 2)) + if(IS_RIGHT_INDEX(active_hand_index)) other_hand = active_hand_index-1 //finding the matching "left" limb else other_hand = active_hand_index+1 //finding the matching "right" limb @@ -33,7 +33,7 @@ //Odd = left. Even = right /mob/proc/held_index_to_dir(i) - if(!(i % 2)) + if(IS_RIGHT_INDEX(i)) return "r" return "l" @@ -132,7 +132,7 @@ if(i > 2) hand += "upper " var/num = 0 - if(!(i % 2)) + if(IS_RIGHT_INDEX(i)) num = i-2 hand += "right hand" else diff --git a/code/modules/mob/living/basic/bots/_bots.dm b/code/modules/mob/living/basic/bots/_bots.dm index be7ce8bc5ddc5..19534cebafd58 100644 --- a/code/modules/mob/living/basic/bots/_bots.dm +++ b/code/modules/mob/living/basic/bots/_bots.dm @@ -16,10 +16,6 @@ GLOBAL_LIST_INIT(command_strings, list( basic_mob_flags = DEL_ON_DEATH density = FALSE - icon = 'icons/mob/silicon/aibots.dmi' - icon_state = "medibot0" - base_icon_state = "medibot" - damage_coeff = list(BRUTE = 1, BURN = 1, TOX = 0, STAMINA = 0, OXY = 0) habitable_atmos = null hud_possible = list(DIAG_STAT_HUD, DIAG_BOT_HUD, DIAG_HUD, DIAG_BATT_HUD, DIAG_PATH_HUD = HUD_LIST_LIST) @@ -103,6 +99,8 @@ GLOBAL_LIST_INIT(command_strings, list( TRAIT_IMMOBILIZED, TRAIT_HANDS_BLOCKED, ) + ///name of the UI we will attempt to open + var/bot_ui = "SimpleBot" /// If true we will offer this COOLDOWN_DECLARE(offer_ghosts_cooldown) @@ -371,7 +369,7 @@ GLOBAL_LIST_INIT(command_strings, list( /mob/living/basic/bot/ui_interact(mob/user, datum/tgui/ui) ui = SStgui.try_update_ui(user, src, ui) if(!ui) - ui = new(user, src, "SimpleBot", name) + ui = new(user, src, bot_ui, name) ui.open() /mob/living/basic/bot/click_alt(mob/user) diff --git a/code/modules/mob/living/basic/bots/bot_ai.dm b/code/modules/mob/living/basic/bots/bot_ai.dm index d777614d7433e..dfef7f1e3788c 100644 --- a/code/modules/mob/living/basic/bots/bot_ai.dm +++ b/code/modules/mob/living/basic/bots/bot_ai.dm @@ -17,16 +17,18 @@ /datum/ai_planning_subtree/manage_unreachable_list, ) max_target_distance = AI_BOT_PATH_LENGTH + can_idle = FALSE + ///minimum distance we need to be from our target in path calculations + var/minimum_distance = 0 ///keys to be reset when the bot is reseted var/list/reset_keys = list( BB_BEACON_TARGET, BB_PREVIOUS_BEACON_TARGET, BB_BOT_SUMMON_TARGET, ) - can_idle = FALSE /datum/targeting_strategy/basic/bot/can_attack(mob/living/living_mob, atom/the_target, vision_range) - var/datum/ai_controller/my_controller = living_mob.ai_controller + var/datum/ai_controller/basic_controller/bot/my_controller = living_mob.ai_controller if(isnull(my_controller)) return FALSE if(!ishuman(the_target) || LAZYACCESS(my_controller.blackboard[BB_TEMPORARY_IGNORE_LIST], the_target)) @@ -36,7 +38,7 @@ return FALSE if(get_turf(living_mob) == get_turf(living_target)) return ..() - var/list/path = get_path_to(living_mob, living_target, max_distance = 10, access = my_controller.get_access()) + var/list/path = get_path_to(living_mob, living_target, mintargetdist = my_controller.minimum_distance, max_distance = 10, access = my_controller.get_access()) if(!length(path) || QDELETED(living_mob)) my_controller?.set_blackboard_key_assoc_lazylist(BB_TEMPORARY_IGNORE_LIST, living_target, TRUE) return FALSE @@ -101,7 +103,7 @@ return TRUE if(get_turf(pawn) == get_turf(target)) return TRUE - var/list/path = get_path_to(pawn, target, max_distance = distance, access = get_access()) + var/list/path = get_path_to(pawn, target, simulated_only = !HAS_TRAIT(pawn, TRAIT_SPACEWALK), mintargetdist = minimum_distance, max_distance = distance, access = get_access()) if(!length(path)) return FALSE return TRUE @@ -265,14 +267,15 @@ action_cooldown = 2 SECONDS behavior_flags = AI_BEHAVIOR_CAN_PLAN_DURING_EXECUTION -/datum/ai_behavior/bot_search/perform(seconds_per_tick, datum/ai_controller/basic_controller/bot/controller, target_key, looking_for, radius = 5, pathing_distance = 10, bypass_add_blacklist = FALSE) +/datum/ai_behavior/bot_search/perform(seconds_per_tick, datum/ai_controller/basic_controller/bot/controller, target_key, looking_for, radius = 5, pathing_distance = 10, bypass_add_blacklist = FALSE, turf_search = FALSE) if(!istype(controller)) stack_trace("attempted to give [controller.pawn] the bot search behavior!") return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED var/mob/living/living_pawn = controller.pawn var/list/ignore_list = controller.blackboard[BB_TEMPORARY_IGNORE_LIST] - for(var/atom/potential_target as anything in oview(radius, controller.pawn)) + var/list/objects_to_search = turf_search ? spiral_range_turfs(radius, controller.pawn) : oview(radius, controller.pawn) //use range turfs instead of oview when we can for performance + for(var/atom/potential_target as anything in objects_to_search) if(QDELETED(living_pawn)) return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED if(!is_type_in_typecache(potential_target, looking_for)) @@ -301,3 +304,37 @@ announcement.announce(pick(list_to_pick_from)) return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED + +///behavior to interact with atoms +/datum/ai_behavior/bot_interact + behavior_flags = AI_BEHAVIOR_REQUIRE_MOVEMENT | AI_BEHAVIOR_REQUIRE_REACH + ///should we remove the target afterwards? + var/clear_target = TRUE + +/datum/ai_behavior/bot_interact/setup(datum/ai_controller/controller, target_key) + . = ..() + var/turf/target = controller.blackboard[target_key] + if(isnull(target)) + return FALSE + set_movement_target(controller, target) + +/datum/ai_behavior/bot_interact/perform(seconds_per_tick, datum/ai_controller/controller, target_key) + var/mob/living/basic/living_pawn = controller.pawn + var/atom/target = controller.blackboard[target_key] + + if(QDELETED(target)) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED + + living_pawn.UnarmedAttack(target, proximity_flag = TRUE) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED + +/datum/ai_behavior/bot_interact/finish_action(datum/ai_controller/controller, succeeded, target_key) + . = ..() + var/atom/target = controller.blackboard[target_key] + if(clear_target) + controller.clear_blackboard_key(target_key) + if(!succeeded && !isnull(target)) + controller.set_blackboard_key_assoc_lazylist(BB_TEMPORARY_IGNORE_LIST, target, TRUE) + +/datum/ai_behavior/bot_interact/keep_target + clear_target = FALSE diff --git a/code/modules/mob/living/basic/bots/bot_hud.dm b/code/modules/mob/living/basic/bots/bot_hud.dm index 6cb3f6bcd01b0..50d40dad01d6c 100644 --- a/code/modules/mob/living/basic/bots/bot_hud.dm +++ b/code/modules/mob/living/basic/bots/bot_hud.dm @@ -27,7 +27,7 @@ switch(mode) if(BOT_SUMMON, BOT_RESPONDING) //Responding to PDA or AI summons holder.icon_state = "hudcalled" - if(BOT_CLEANING, BOT_REPAIRING, BOT_HEALING) //Cleanbot cleaning, Floorbot fixing, or Medibot Healing + if(BOT_CLEANING, BOT_HEALING) //Cleanbot cleaning, Floorbot fixing, or Medibot Healing holder.icon_state = "hudworking" if(BOT_PATROL, BOT_START_PATROL) //Patrol mode holder.icon_state = "hudpatrol" diff --git a/code/modules/mob/living/basic/bots/repairbot/repairbot.dm b/code/modules/mob/living/basic/bots/repairbot/repairbot.dm new file mode 100644 index 0000000000000..89dad9b4f356c --- /dev/null +++ b/code/modules/mob/living/basic/bots/repairbot/repairbot.dm @@ -0,0 +1,389 @@ + +/mob/living/basic/bot/repairbot + name = "\improper Repairbot" + desc = "I can fix it!" + icon = 'icons/mob/silicon/aibots.dmi' + icon_state = "repairbot_base" + base_icon_state = "repairbot_base" + pass_flags = parent_type::pass_flags | PASSTABLE + density = FALSE + layer = BELOW_MOB_LAYER + anchored = FALSE + health = 100 + can_be_held = TRUE + maxHealth = 100 + path_image_color = "#80dae7" + bot_ui = "RepairBot" + req_one_access = list(ACCESS_ROBOTICS, ACCESS_ENGINEERING) + radio_key = /obj/item/encryptionkey/headset_service + radio_channel = RADIO_CHANNEL_ENGINEERING + bot_type = REPAIR_BOT + additional_access = /datum/id_trim/job/station_engineer + ai_controller = /datum/ai_controller/basic_controller/bot/repairbot + ///our iron stack + var/obj/item/stack/sheet/iron/our_iron + ///our glass stack + var/obj/item/stack/sheet/glass/our_glass + ///our floor stack + var/obj/item/stack/tile/our_tiles + ///our welder + var/obj/item/weldingtool/repairbot/our_welder + ///our crowbar + var/obj/item/crowbar/our_crowbar + ///our screwdriver + var/obj/item/screwdriver/our_screwdriver + ///our iron rods + var/obj/item/stack/rods/our_rods + ///our rcd object we use to deconstruct when emagged + var/obj/item/construction/rcd/repairbot/deconstruction_device + ///possible interactions + var/static/list/possible_stack_interactions = list( + /obj/item/stack/sheet/iron = typecacheof(list(/obj/structure/girder)), + /obj/item/stack/tile = typecacheof(list(/turf/open/space, /turf/open/floor/plating)), + /obj/item/stack/sheet/glass = typecacheof(list(/obj/structure/grille)), + ) + var/static/list/possible_tool_interactions = list( + /obj/item/weldingtool/repairbot = typecacheof(list(/obj/machinery, /obj/structure/window)), + /obj/item/crowbar = typecacheof(list(/turf/open/floor)), + ) + ///our neutral voicelines + var/static/list/neutral_voicelines = list( + REPAIRBOT_VOICED_BRICK = 'sound/voice/repairbot/brick.ogg', + REPAIRBOT_VOICED_ENTROPY = 'sound/voice/repairbot/entropy.ogg', + REPAIRBOT_VOICED_FIX_IT = 'sound/voice/repairbot/fixit.ogg', + REPAIRBOT_VOICED_FIX_TOUCH = 'sound/voice/repairbot/fixtouch.ogg', + REPAIRBOT_VOICED_HOLE = 'sound/voice/repairbot/patchingholes.ogg', + REPAIRBOT_VOICED_PAY = 'sound/voice/repairbot/pay.ogg', + ) + ///our emagged voicelines + var/static/list/emagged_voicelines = list( + REPAIRBOT_VOICED_ENTROPY = 'sound/voice/repairbot/entropy.ogg', + REPAIRBOT_VOICED_STRINGS = 'sound/voice/repairbot/strings.ogg', + REPAIRBOT_VOICED_PASSION = 'sound/voice/repairbot/passionproject.ogg', + ) + ///types we can retrieve from our ui + var/static/list/retrievable_types = list( + /obj/item/stack/sheet/iron, + /obj/item/stack/sheet/glass, + /obj/item/stack/tile, + ) + + ///our flags + var/repairbot_flags = REPAIRBOT_FIX_BREACHES | REPAIRBOT_FIX_GIRDERS | REPAIRBOT_REPLACE_WINDOWS | REPAIRBOT_REPLACE_TILES | REPAIRBOT_BUILD_GIRDERS + ///our color + var/toolbox_color = "#445eb3" + ///toolbox type we drop on death + var/toolbox = /obj/item/storage/toolbox + +/mob/living/basic/bot/repairbot/Initialize(mapload) + . = ..() + ai_controller.set_blackboard_key(BB_REPAIRBOT_EMAGGED_SPEECH, emagged_voicelines) + ai_controller.set_blackboard_key(BB_REPAIRBOT_NORMAL_SPEECH, neutral_voicelines) + var/static/list/abilities = list( + /datum/action/cooldown/mob_cooldown/bot/build_girder = BB_GIRDER_BUILD_ABILITY, + ) + grant_actions_by_list(abilities) + add_traits(list(TRAIT_SPACEWALK, TRAIT_NEGATES_GRAVITY, TRAIT_MOB_MERGE_STACKS, TRAIT_FIREDOOR_OPENER), INNATE_TRAIT) + our_welder = new(src) + our_welder.switched_on(src) + our_crowbar = new(src) + our_screwdriver = new(src) + our_rods = new(src, our_rods::max_amount) + set_color(toolbox_color) + START_PROCESSING(SSobj, src) + +/mob/living/basic/bot/repairbot/proc/set_color(new_color) + add_atom_colour(new_color, FIXED_COLOUR_PRIORITY) + toolbox_color = new_color + +/mob/living/basic/bot/repairbot/attackby(obj/item/potential_stack, mob/living/carbon/human/user, list/modifiers) + if(!istype(potential_stack, /obj/item/stack)) + return ..() + attempt_merge(potential_stack, user) + +/mob/living/basic/bot/repairbot/proc/attempt_merge(obj/item/stack/potential_stack, mob/living/user) + var/static/list/our_contents = list(/obj/item/stack/sheet/iron, /obj/item/stack/sheet/glass, /obj/item/stack/tile, /obj/item/stack/rods) + for(var/obj/item/stack/content as anything in our_contents) + if(!istype(potential_stack, content)) + continue + var/obj/item/stack/our_sheet = locate(content) in src + if(isnull(our_sheet)) + potential_stack.forceMove(src) + return + if(our_sheet.amount >= our_sheet.max_amount) + user?.balloon_alert(user, "full!") + return + if(!our_sheet.can_merge(potential_stack)) + return + var/atom/movable/to_move = potential_stack.split_stack(user, min(our_sheet.max_amount - our_sheet.amount, potential_stack.amount)) + to_move.forceMove(src) + return + +/mob/living/basic/bot/repairbot/Entered(atom/movable/arrived, atom/old_loc, list/atom/old_locs) + . = ..() + if(istype(arrived, /obj/item/stack/sheet/iron) && isnull(our_iron)) //show iron tiles and glass in our hands + our_iron = arrived + update_appearance() + if(istype(arrived, /obj/item/stack/sheet/glass) && isnull(our_glass)) + our_glass = arrived + update_appearance() + if(istype(arrived, /obj/item/stack/tile) && isnull(our_tiles)) + our_tiles = arrived + if(istype(arrived, /obj/item/stack/rods) && isnull(our_rods)) + our_rods = arrived + +/mob/living/basic/bot/repairbot/UnarmedAttack(atom/target, proximity_flag, list/modifiers) + . = ..() + + if(!. || !proximity_flag) + return + + if(bot_access_flags & BOT_COVER_EMAGGED) + emagged_interactions(target, modifiers) + return + + if(istype(target, /obj/item/stack)) + attempt_merge(target, src) + return + + //priority interactions + if(istype(target, /turf/open/space)) + var/turf/open/space/space_target = target + if(!space_target.has_valid_support() && !(locate(/obj/structure/lattice) in space_target)) + our_rods?.melee_attack_chain(src, space_target) + + if(istype(target, /obj/structure/grille)) + var/obj/structure/grille/grille_target = target + if(grille_target.broken) + our_rods?.melee_attack_chain(src, grille_target) + + if(istype(target, /turf/open)) + var/turf/open/open_target = target + if(open_target.broken || open_target.burnt) + our_welder?.melee_attack_chain(src, open_target) + + if(istype(target, /obj/structure/window)) + var/obj/structure/window/target_window = target + if(!target_window.anchored) + our_screwdriver?.melee_attack_chain(src, target_window) + + //stack interactions + for(var/type in possible_stack_interactions) + var/obj/item/target_stack = locate(type) in src + if(isnull(target_stack)) + continue + if(!is_type_in_typecache(target, possible_stack_interactions[type])) + continue + target_stack.melee_attack_chain(src, target) + return + + //tool interactions + var/list/our_tools = list(our_welder, our_crowbar) + for(var/obj/item/tool in our_tools) + if(is_type_in_typecache(target, possible_tool_interactions[tool.type]) && !combat_mode) + tool.melee_attack_chain(src, target) + return + +/mob/living/basic/bot/repairbot/proc/emagged_interactions(atom/target, modifiers) + if(!istype(target, /mob/living/silicon/robot)) + deconstruction_device.interact_with_atom_secondary(target, src, modifiers) + return + if(HAS_TRAIT(target, TRAIT_MOB_TIPPED)) + return + var/old_combat_mode = combat_mode + set_combat_mode(TRUE) + target.attack_hand_secondary(src, modifiers) //tip the guy! + set_combat_mode(old_combat_mode) + +/mob/living/basic/bot/repairbot/start_pulling(atom/movable/movable_pulled, state, force, supress_message) + . = ..() + if(pulling) + setGrabState(GRAB_AGGRESSIVE) //automatically aggro grab everything! + +/mob/living/basic/bot/repairbot/Destroy() + . = ..() + QDEL_NULL(our_iron) + QDEL_NULL(our_glass) + QDEL_NULL(our_tiles) + QDEL_NULL(our_welder) + QDEL_NULL(our_screwdriver) + QDEL_NULL(our_crowbar) + QDEL_NULL(our_rods) + QDEL_NULL(deconstruction_device) + +/mob/living/basic/bot/repairbot/Exited(atom/movable/gone, direction) + if(gone == our_crowbar) + our_crowbar = null + if(gone == our_screwdriver) + our_screwdriver = null + if(gone == our_welder) + our_welder = null + if(gone == our_tiles) + our_tiles = null + if(gone == our_iron) + our_iron = null + if(gone == our_glass) + our_glass = null + if(gone == our_rods) + our_rods = null + update_appearance() + return ..() + +/mob/living/basic/bot/repairbot/process(seconds_per_tick) //generate 1 iron rod every 2 seconds + if(isnull(our_rods) || our_rods.amount < our_rods.max_amount) + new /obj/item/stack/rods(src) + +/mob/living/basic/bot/repairbot/turn_on() + . = ..() + if(!.) + return + START_PROCESSING(SSobj, src) + +/mob/living/basic/bot/repairbot/turn_off() + . = ..() + STOP_PROCESSING(SSobj, src) + +/mob/living/basic/bot/repairbot/update_overlays() + . = ..() + . += mutable_appearance(icon, "repairbot[bot_mode_flags & BOT_MODE_ON]", appearance_flags = RESET_COLOR) + if(our_glass) + var/mutable_appearance/glass = mutable_appearance(icon, "repairbot_glass_overlay", BELOW_MOB_LAYER - 0.02, appearance_flags = RESET_COLOR) + glass.pixel_x = -6 + glass.pixel_y = -5 + . += glass + if(our_iron) + var/mutable_appearance/iron = mutable_appearance(icon, "repairbot_iron_overlay", BELOW_MOB_LAYER - 0.02, appearance_flags = RESET_COLOR) + iron.pixel_y = -5 + iron.pixel_x = 7 + . += iron + +/mob/living/basic/bot/repairbot/update_icon_state() + . = ..() + icon_state = base_icon_state + +/mob/living/basic/bot/repairbot/generate_speak_list() + return neutral_voicelines + emagged_voicelines + +/mob/living/basic/bot/repairbot/Bumped(atom/movable/bumped_object) + . = ..() + if(istype(bumped_object, /obj/machinery/door/firedoor) && bumped_object.density) + our_crowbar.melee_attack_chain(src, bumped_object) + +/mob/living/basic/bot/repairbot/ui_data(mob/user) + var/list/data = ..() + data["repairbot_materials"] = list() + if((bot_access_flags & BOT_COVER_LOCKED) && !issilicon(user) && !isAdminGhostAI(user)) + return data + data["custom_controls"]["fix_breaches"] = repairbot_flags & REPAIRBOT_FIX_BREACHES + data["custom_controls"]["replace_windows"] = repairbot_flags & REPAIRBOT_REPLACE_WINDOWS + data["custom_controls"]["replace_tiles"] = repairbot_flags & REPAIRBOT_REPLACE_TILES + data["custom_controls"]["fix_girders"] = repairbot_flags & REPAIRBOT_FIX_GIRDERS + data["custom_controls"]["build_girders"] = repairbot_flags & REPAIRBOT_BUILD_GIRDERS + + for(var/data_path in retrievable_types) + var/atom/to_retrieve = locate(data_path) in src + if(isnull(to_retrieve)) + continue + + data["repairbot_materials"] += list(list( + "material_ref" = REF(to_retrieve), + "material_icon" = to_retrieve::icon, + "material_icon_state" = to_retrieve::icon_state, + )) + + return data + +/mob/living/basic/bot/repairbot/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state) + . = ..() + if(. || !isliving(ui.user) || (bot_access_flags & BOT_COVER_LOCKED) && !(HAS_SILICON_ACCESS(ui.user))) + return + switch(action) + if("fix_breaches") + repairbot_flags ^= REPAIRBOT_FIX_BREACHES + if("replace_windows") + repairbot_flags ^= REPAIRBOT_REPLACE_WINDOWS + if("replace_tiles") + repairbot_flags ^= REPAIRBOT_REPLACE_TILES + if("fix_girders") + repairbot_flags ^= REPAIRBOT_FIX_GIRDERS + if("build_girders") + repairbot_flags ^= REPAIRBOT_BUILD_GIRDERS + if("remove_item") + var/item_params = params["item_reference"] + if(isnull(item_params)) + return TRUE + var/obj/item/retrieved = locate(item_params) in contents + if(isnull(retrieved) || !is_type_in_list(retrieved, retrievable_types)) + return TRUE + var/mob/living/user = ui.user + user.put_in_hands(retrieved) + return TRUE + + +/mob/living/basic/bot/repairbot/emag_act(mob/user, obj/item/card/emag/emag_card) + . = ..() + if(!(bot_access_flags & BOT_COVER_EMAGGED) || !isnull(deconstruction_device)) + return + deconstruction_device = new(src) + +/obj/item/weldingtool/repairbot + max_fuel = INFINITY + starting_fuel = TRUE + change_icons = FALSE + +/obj/item/construction/rcd/repairbot + matter = INFINITY + has_ammobar = FALSE + +/mob/living/basic/bot/repairbot/mob_pickup(mob/living/user) + var/obj/item/carried_repairbot/carried = new(get_turf(src)) + carried.set_bot(src) + carried.add_atom_colour(toolbox_color, FIXED_COLOUR_PRIORITY) + user.visible_message(span_warning("[user] scoops up [src]!")) + user.put_in_hands(carried) + +/obj/item/carried_repairbot + desc = "A most robust bot!" + attack_verb_continuous = list("robusts") + attack_verb_simple = list("robust") + hitsound = 'sound/items/weapons/smash.ogg' + drop_sound = 'sound/items/handling/toolbox/toolbox_drop.ogg' + pickup_sound = 'sound/items/handling/toolbox/toolbox_pickup.ogg' + ///the bot we own + var/atom/movable/our_bot + +/obj/item/carried_repairbot/proc/set_bot(mob/living/basic/bot/repairbot/repairbot) + var/obj/item/bot_toolbox = repairbot.toolbox + icon = bot_toolbox::icon + icon_state = bot_toolbox::icon_state + lefthand_file = bot_toolbox::lefthand_file + righthand_file = bot_toolbox::righthand_file + inhand_icon_state = bot_toolbox::inhand_icon_state + force = bot_toolbox::force + repairbot.forceMove(src) + +/obj/item/carried_repairbot/dropped() + . = ..() + if(isturf(loc)) + release_bot() + +/obj/item/carried_repairbot/proc/release_bot(bypass_delete = FALSE) + if(!isnull(our_bot)) + our_bot.forceMove(drop_location()) + our_bot.balloon_alert_to_viewers("plops down") + if(!bypass_delete) + qdel(src) + +/obj/item/carried_repairbot/Destroy() + . = ..() + release_bot(bypass_delete = TRUE) + +/obj/item/carried_repairbot/Entered(atom/movable/arrived, atom/old_loc, list/atom/old_locs) + . = ..() + if(isliving(arrived)) + our_bot = arrived + +/obj/item/carried_repairbot/Exited(atom/movable/gone, direction) + if(gone == our_bot) + our_bot = null + return ..() diff --git a/code/modules/mob/living/basic/bots/repairbot/repairbot_abilities.dm b/code/modules/mob/living/basic/bots/repairbot/repairbot_abilities.dm new file mode 100644 index 0000000000000..fa8d49706345e --- /dev/null +++ b/code/modules/mob/living/basic/bots/repairbot/repairbot_abilities.dm @@ -0,0 +1,43 @@ +#define BUILDING_WALL_ABILITY "building wall ability" + +/datum/action/cooldown/mob_cooldown/bot/build_girder + name = "Build Girder" + desc = "Use iron rods to build a girder!" + cooldown_time = 3 SECONDS + click_to_activate = TRUE + +/datum/action/cooldown/mob_cooldown/bot/build_girder/IsAvailable(feedback) + . = ..() + if(!.) + return FALSE + var/obj/item/stack/rods/our_rods = locate() in owner + if(isnull(our_rods) || our_rods.amount < 2) + return FALSE + return TRUE + +/datum/action/cooldown/mob_cooldown/bot/build_girder/Activate(atom/target) + if(DOING_INTERACTION(owner, BUILDING_WALL_ABILITY)) + return TRUE + if(!isopenturf(target) || isgroundlessturf(target)) + owner.balloon_alert(owner, "cant build here!") + return TRUE + var/obj/item/stack/rods/our_rods = locate() in owner + var/turf/turf_target = target + if(turf_target.is_blocked_turf()) + owner.balloon_alert(owner, "blocked!") + return TRUE + var/obj/effect/constructing_effect/effect = new(turf_target, 3 SECONDS) + + if(!do_after(owner, 3 SECONDS, target = turf_target, interaction_key = BUILDING_WALL_ABILITY) || isnull(turf_target) || turf_target.is_blocked_turf()) + qdel(effect) + return TRUE + + playsound(turf_target, 'sound/machines/click.ogg', 50, TRUE) + new /obj/structure/girder(turf_target) + var/atom/stack_to_delete = our_rods.split_stack(owner, 2) + qdel(stack_to_delete) + StartCooldown() + qdel(effect) + return TRUE + +#undef BUILDING_WALL_ABILITY diff --git a/code/modules/mob/living/basic/bots/repairbot/repairbot_ai.dm b/code/modules/mob/living/basic/bots/repairbot/repairbot_ai.dm new file mode 100644 index 0000000000000..1793f0b65c2ed --- /dev/null +++ b/code/modules/mob/living/basic/bots/repairbot/repairbot_ai.dm @@ -0,0 +1,320 @@ +#define REPAIRBOT_SPEECH_TIMER 30 SECONDS + +/datum/ai_controller/basic_controller/bot/repairbot + planning_subtrees = list( + /datum/ai_planning_subtree/repairbot_speech, + /datum/ai_planning_subtree/manage_unreachable_list, + /datum/ai_planning_subtree/mug_robot, + /datum/ai_planning_subtree/refill_materials, + /datum/ai_planning_subtree/repairbot_deconstruction, + /datum/ai_planning_subtree/respond_to_summon, + /datum/ai_planning_subtree/replace_floors/breaches, + /datum/ai_planning_subtree/wall_girder, + /datum/ai_planning_subtree/build_girder, + /datum/ai_planning_subtree/replace_window, + /datum/ai_planning_subtree/replace_floors, + /datum/ai_planning_subtree/fix_window, + /datum/ai_planning_subtree/salute_authority, + /datum/ai_planning_subtree/find_patrol_beacon, + ) + reset_keys = list( + BB_TILELESS_FLOOR, + BB_GIRDER_TARGET, + BB_GIRDER_TO_WALL_TARGET, + BB_BEACON_TARGET, + BB_PREVIOUS_BEACON_TARGET, + BB_WELDER_TARGET, + BB_WINDOW_FRAMETARGET, + ) + ai_traits = PAUSE_DURING_DO_AFTER + minimum_distance = 1 + +///subtree to refill our stacks +/datum/ai_planning_subtree/refill_materials + +/datum/ai_planning_subtree/refill_materials/SelectBehaviors(datum/ai_controller/basic_controller/bot/controller, seconds_per_tick) + var/static/list/refillable_items = typecacheof(list( + /obj/item/stack/sheet/iron, + /obj/item/stack/sheet/glass, + /obj/item/stack/tile, + )) + if(!controller.blackboard_key_exists(BB_REFILLABLE_TARGET)) + controller.queue_behavior(/datum/ai_behavior/bot_search/refillable_target, BB_REFILLABLE_TARGET, refillable_items) + return + controller.queue_behavior(/datum/ai_behavior/bot_interact, BB_REFILLABLE_TARGET) + return SUBTREE_RETURN_FINISH_PLANNING + +/datum/ai_behavior/bot_search/refillable_target + action_cooldown = 10 SECONDS + +/datum/ai_behavior/bot_search/refillable_target/valid_target(datum/ai_controller/basic_controller/bot/controller, atom/my_target) + var/static/list/desired_types = list( + /obj/item/stack/sheet/iron, + /obj/item/stack/sheet/glass, + /obj/item/stack/tile, + ) + for(var/object_type in desired_types) + if(!istype(my_target, object_type)) + continue + var/obj/item/stack/sheet_type = locate(object_type) in controller.pawn + if(isnull(sheet_type)) + return TRUE //we dont have any of it! + if(sheet_type.amount < sheet_type.max_amount && sheet_type.can_merge(my_target)) + return TRUE + return FALSE + +/datum/ai_planning_subtree/mug_robot + +/datum/ai_planning_subtree/mug_robot/SelectBehaviors(datum/ai_controller/basic_controller/bot/controller, seconds_per_tick) + var/mob/living/basic/bot/living_bot = controller.pawn + if(!(living_bot.bot_access_flags & BOT_COVER_EMAGGED)) + return + var/static/list/robot_targets = typecacheof( + /mob/living/silicon/robot, + ) + if(!controller.blackboard_key_exists(BB_ROBOT_TARGET)) + controller.queue_behavior(/datum/ai_behavior/bot_search/valid_robot, BB_ROBOT_TARGET, robot_targets) + return + if(!living_bot.pulling) + controller.queue_behavior(/datum/ai_behavior/drag_target, BB_ROBOT_TARGET) + else + controller.queue_behavior(/datum/ai_behavior/bot_interact/tip_robot, BB_ROBOT_TARGET) + return SUBTREE_RETURN_FINISH_PLANNING + +/datum/ai_behavior/bot_search/valid_robot + +/datum/ai_behavior/bot_search/valid_robot/valid_target(datum/ai_controller/basic_controller/bot/controller, atom/my_target) + return (!HAS_TRAIT(my_target, TRAIT_MOB_TIPPED)) && can_see(controller.pawn, my_target) + +/datum/ai_behavior/bot_interact/tip_robot + +/datum/ai_behavior/bot_interact/tip_robot/finish_action(datum/ai_controller/controller, succeeded, target_key) + . = ..() + if(succeeded) + var/mob/living/living_pawn = controller.pawn + living_pawn.stop_pulling() + +///subtree to deconstruct things when we're emagged +/datum/ai_planning_subtree/repairbot_deconstruction + +/datum/ai_planning_subtree/repairbot_deconstruction/SelectBehaviors(datum/ai_controller/basic_controller/bot/controller, seconds_per_tick) + var/mob/living/basic/bot/living_bot = controller.pawn + if(!(living_bot.bot_access_flags & BOT_COVER_EMAGGED)) + return + var/static/list/things_to_deconstruct = typecacheof(list( + /obj/structure/window, + /turf/open/floor, + /turf/closed/wall, + )) + if(!controller.blackboard_key_exists(BB_DECONSTRUCT_TARGET)) + controller.queue_behavior(/datum/ai_behavior/bot_search/deconstructable, BB_DECONSTRUCT_TARGET, things_to_deconstruct) + return SUBTREE_RETURN_FINISH_PLANNING + controller.queue_behavior(/datum/ai_behavior/bot_interact, BB_DECONSTRUCT_TARGET) + return SUBTREE_RETURN_FINISH_PLANNING + +/datum/ai_behavior/bot_search/deconstructable + +/datum/ai_behavior/bot_search/deconstructable/valid_target(datum/ai_controller/basic_controller/bot/controller, atom/my_target) + return (!(my_target.resistance_flags & INDESTRUCTIBLE) && !isgroundlessturf(my_target)) + +///subtree to control bot speech +/datum/ai_planning_subtree/repairbot_speech + +/datum/ai_planning_subtree/repairbot_speech/SelectBehaviors(datum/ai_controller/basic_controller/bot/controller, seconds_per_tick) + if(controller.blackboard[BB_REPAIRBOT_SPEECH_COOLDOWN] > world.time) + return + var/static/list/keys_to_look = list( + BB_WELDER_TARGET, + BB_WINDOW_FRAMETARGET, + BB_TILELESS_FLOOR, + BB_BREACHED_FLOOR, + BB_GIRDER_TO_WALL_TARGET, + BB_GIRDER_TARGET, + BB_DECONSTRUCT_TARGET, + ) + for(var/key in keys_to_look) + if(controller.blackboard_key_exists(key)) + controller.queue_behavior(/datum/ai_behavior/repairbot_speech, key) + return + +/datum/ai_behavior/repairbot_speech + behavior_flags = AI_BEHAVIOR_CAN_PLAN_DURING_EXECUTION + +/datum/ai_behavior/repairbot_speech/perform(seconds_per_tick, datum/ai_controller/controller, target_key) + var/datum/action/cooldown/bot_announcement/announcement = controller.blackboard[BB_ANNOUNCE_ABILITY] + var/list/speech_to_pick_from = (target_key == BB_DECONSTRUCT_TARGET) ? controller.blackboard[BB_REPAIRBOT_EMAGGED_SPEECH] : controller.blackboard[BB_REPAIRBOT_NORMAL_SPEECH] + if(!length(speech_to_pick_from)) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED + announcement.announce(pick(speech_to_pick_from)) + controller.set_blackboard_key(BB_REPAIRBOT_SPEECH_COOLDOWN, world.time + REPAIRBOT_SPEECH_TIMER) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED + +///subtree to replace iron platings +/datum/ai_planning_subtree/replace_floors + ///flag we check before executing + var/required_flag = REPAIRBOT_REPLACE_TILES + ///key of our floor target + var/floor_key = BB_TILELESS_FLOOR + ///type of tile we need to replace floors + var/needed_tile_type = /obj/item/stack/tile + ///type of floors we can replace + var/list/type_of_turf = list(/turf/open/floor/plating) + ///our searching behavior + var/search_behavior = /datum/ai_behavior/bot_search/valid_plateless_turf + +/datum/ai_planning_subtree/replace_floors/New() + . = ..() + type_of_turf = typecacheof(type_of_turf) + +/datum/ai_planning_subtree/replace_floors/SelectBehaviors(datum/ai_controller/basic_controller/bot/controller, seconds_per_tick) + var/mob/living/basic/bot/repairbot/bot_pawn = controller.pawn + if(!(bot_pawn.repairbot_flags & required_flag)) + return + if(!locate(needed_tile_type) in bot_pawn) + return + if(controller.blackboard_key_exists(floor_key)) + controller.queue_behavior(/datum/ai_behavior/bot_interact, floor_key) + return SUBTREE_RETURN_FINISH_PLANNING + + controller.queue_behavior(search_behavior, floor_key, type_of_turf, 5, 10, FALSE, TRUE) + +/datum/ai_behavior/bot_search/valid_plateless_turf + +/datum/ai_behavior/bot_search/valid_plateless_turf/valid_target(datum/ai_controller/basic_controller/bot/controller, turf/open/my_target) + var/static/list/blacklist_objects = typecacheof(list( + /obj/structure/window, + /obj/structure/grille, + )) + for(var/atom/possible_blacklisted as anything in my_target) + if(is_type_in_typecache(possible_blacklisted, blacklist_objects)) + return FALSE + if(istype(my_target, /turf/open/floor/plating) && !can_see(controller.pawn, my_target, 5)) + return FALSE + return !istype(get_area(my_target), /area/space) + +///subtree to fix hull breaches +/datum/ai_planning_subtree/replace_floors/breaches + floor_key = BB_BREACHED_FLOOR + needed_tile_type = /obj/item/stack/tile/iron + type_of_turf = list(/turf/open/space) + required_flag = REPAIRBOT_FIX_BREACHES + search_behavior = /datum/ai_behavior/bot_search/valid_plateless_turf/breached + +///exists as to not conflict with the base turf searching behavior cause of how the queue system works... +/datum/ai_behavior/bot_search/valid_plateless_turf/breached + +///subtree to build girders +/datum/ai_planning_subtree/build_girder + +/datum/ai_planning_subtree/build_girder/SelectBehaviors(datum/ai_controller/basic_controller/bot/controller, seconds_per_tick) + var/mob/living/basic/bot/repairbot/bot_pawn = controller.pawn + if(!(bot_pawn.repairbot_flags & REPAIRBOT_BUILD_GIRDERS)) + return + var/obj/item/stack/rods/my_rods = locate() in bot_pawn + if(isnull(my_rods) || my_rods.amount < 2) + return + var/datum/action/cooldown/ability = controller.blackboard[BB_GIRDER_BUILD_ABILITY] + if(!ability?.IsAvailable()) + return + if(controller.blackboard_key_exists(BB_GIRDER_TARGET)) + controller.queue_behavior(/datum/ai_behavior/targeted_mob_ability/build_girder, BB_GIRDER_BUILD_ABILITY, BB_GIRDER_TARGET) + return SUBTREE_RETURN_FINISH_PLANNING + + var/static/list/searchable_turfs = typecacheof(list(/turf/open)) + controller.queue_behavior(/datum/ai_behavior/bot_search/valid_wall_target, BB_GIRDER_TARGET, searchable_turfs, 5, 10, FALSE, TRUE) + +/datum/ai_behavior/bot_search/valid_wall_target + action_cooldown = 5 SECONDS + +/datum/ai_behavior/bot_search/valid_wall_target/valid_target(datum/ai_controller/basic_controller/bot/controller, turf/my_target) + if(istype(get_area(my_target), /area/space) || isgroundlessturf(my_target) || my_target.is_blocked_turf()) + return FALSE + var/static/list/blacklist_objects = list( + /obj/machinery/door, + /obj/structure/grille, + ) + + for(var/atom/contents in my_target) + if(is_type_in_typecache(contents, blacklist_objects)) + return FALSE + + var/turf/adjacent_turfs = get_adjacent_open_turfs(my_target) + for(var/turf/possible_spaced_turf as anything in adjacent_turfs) + if(isspaceturf(possible_spaced_turf) && istype(get_area(possible_spaced_turf), /area/space)) + return TRUE + return FALSE + +/datum/ai_behavior/targeted_mob_ability/build_girder + behavior_flags = AI_BEHAVIOR_REQUIRE_MOVEMENT | AI_BEHAVIOR_REQUIRE_REACH | AI_BEHAVIOR_CAN_PLAN_DURING_EXECUTION + +/datum/ai_behavior/targeted_mob_ability/build_girder/setup(datum/ai_controller/controller, ability_key, target_key) + . = ..() + var/atom/target = controller.blackboard[target_key] + if(QDELETED(target)) + return FALSE + set_movement_target(controller, target) + +/datum/ai_behavior/targeted_mob_ability/build_girder/finish_action(datum/ai_controller/controller, succeeded, ability_key, target_key) + . = ..() + var/atom/target = controller.blackboard[target_key] + controller.clear_blackboard_key(target_key) + if(!succeeded && !isnull(target)) + controller.set_blackboard_key_assoc_lazylist(BB_TEMPORARY_IGNORE_LIST, target, TRUE) + + +///subtree to place glass on windows +/datum/ai_planning_subtree/replace_window + +/datum/ai_planning_subtree/replace_window/SelectBehaviors(datum/ai_controller/controller, seconds_per_tick) + var/mob/living/basic/bot/repairbot/living_pawn = controller.pawn + if(!(living_pawn.repairbot_flags & REPAIRBOT_REPLACE_WINDOWS)) + return + if(!locate(/obj/item/stack/sheet/glass) in living_pawn) + return + if(controller.blackboard_key_exists(BB_WINDOW_FRAMETARGET)) + controller.queue_behavior(/datum/ai_behavior/bot_interact, BB_WINDOW_FRAMETARGET) + return SUBTREE_RETURN_FINISH_PLANNING + var/static/list/searchable_grilles = typecacheof(list(/obj/structure/grille)) + controller.queue_behavior(/datum/ai_behavior/bot_search/valid_grille_target, BB_WINDOW_FRAMETARGET, searchable_grilles) + +/datum/ai_behavior/bot_search/valid_grille_target/valid_target(datum/ai_controller/basic_controller/bot/controller, obj/structure/my_target) + if(locate(/obj/structure/window) in get_turf(my_target)) + return FALSE + return (!istype(get_area(my_target), /area/space)) + + +///subtree to place iron on girders +/datum/ai_planning_subtree/wall_girder + +/datum/ai_planning_subtree/wall_girder/SelectBehaviors(datum/ai_controller/controller, seconds_per_tick) + var/mob/living/basic/bot/repairbot/living_pawn = controller.pawn + if(!(living_pawn.repairbot_flags & REPAIRBOT_FIX_GIRDERS)) + return + var/obj/item/stack/sheet/iron/my_iron = locate() in living_pawn + if(isnull(my_iron) || my_iron.amount < 2) + return + if(controller.blackboard_key_exists(BB_GIRDER_TO_WALL_TARGET)) + controller.queue_behavior(/datum/ai_behavior/bot_interact, BB_GIRDER_TO_WALL_TARGET) + return SUBTREE_RETURN_FINISH_PLANNING + var/static/list/searchable_girder = typecacheof(list(/obj/structure/girder)) + controller.queue_behavior(/datum/ai_behavior/bot_search/valid_girder, BB_GIRDER_TO_WALL_TARGET, searchable_girder) + +/datum/ai_behavior/bot_search/valid_girder/valid_target(datum/ai_controller/basic_controller/bot/controller, obj/my_target) + return isfloorturf(my_target.loc) + +///subtree to repair machines with welders +/datum/ai_planning_subtree/fix_window + +/datum/ai_planning_subtree/fix_window/SelectBehaviors(datum/ai_controller/controller, seconds_per_tick) + if(controller.blackboard_key_exists(BB_WELDER_TARGET)) + controller.queue_behavior(/datum/ai_behavior/bot_interact, BB_WELDER_TARGET) + return SUBTREE_RETURN_FINISH_PLANNING + var/static/list/searchable_objects = typecacheof(list(/obj/structure/window)) + controller.queue_behavior(/datum/ai_behavior/bot_search/valid_window_fix, BB_WELDER_TARGET, searchable_objects) + +/datum/ai_behavior/bot_search/valid_window_fix + +/datum/ai_behavior/bot_search/valid_window_fix/valid_target(datum/ai_controller/basic_controller/bot/controller, obj/my_target) + return (my_target.get_integrity() < my_target.max_integrity || !my_target.anchored) + +#undef REPAIRBOT_SPEECH_TIMER diff --git a/code/modules/mob/living/basic/drone/_drone.dm b/code/modules/mob/living/basic/drone/_drone.dm index fe5dbb4d2d5a3..7412551d5984f 100644 --- a/code/modules/mob/living/basic/drone/_drone.dm +++ b/code/modules/mob/living/basic/drone/_drone.dm @@ -348,6 +348,9 @@ to_chat(src, span_warning("Using [machine] could break your laws.")) return COMPONENT_CANT_INTERACT_WIRES +/mob/living/basic/drone/proc/init_shy_in_room_component(list/drone_bad_areas) + if(CONFIG_GET(flag/drone_area_interaction_restrict)) + LoadComponent(/datum/component/shy_in_room, drone_bad_areas, "Touching anything in %ROOM could break your laws.") /mob/living/basic/drone/proc/set_shy(new_shy) shy = new_shy @@ -366,8 +369,8 @@ REMOVE_TRAIT(src, TRAIT_CAN_STRIP, DRONE_SHY_TRAIT) // To shy to touch someone elses hat ADD_TRAIT(src, TRAIT_PACIFISM, DRONE_SHY_TRAIT) LoadComponent(/datum/component/shy, mob_whitelist=not_shy_of, shy_range=3, message="Your laws prevent this action near %TARGET.", keyless_shy=FALSE, clientless_shy=TRUE, dead_shy=FALSE, dead_shy_immediate=TRUE, machine_whitelist=shy_machine_whitelist) - LoadComponent(/datum/component/shy_in_room, drone_bad_areas, "Touching anything in %ROOM could break your laws.") - LoadComponent(/datum/component/technoshy, 1 MINUTES, "%TARGET was touched by a being recently, using it could break your laws.") + init_shy_in_room_component(drone_bad_areas) + LoadComponent(/datum/component/technoshy, 20 SECONDS, "%TARGET was touched by a being recently, using it could break your laws.") LoadComponent(/datum/component/itempicky, drone_good_items, "Using %TARGET could break your laws.") RegisterSignal(src, COMSIG_TRY_USE_MACHINE, PROC_REF(blacklist_on_try_use_machine)) RegisterSignal(src, COMSIG_TRY_WIRES_INTERACT, PROC_REF(blacklist_on_try_wires_interact)) diff --git a/code/modules/mob/living/basic/farm_animals/gorilla/gorilla.dm b/code/modules/mob/living/basic/farm_animals/gorilla/gorilla.dm index 363243a283388..7e572c2d92f63 100644 --- a/code/modules/mob/living/basic/farm_animals/gorilla/gorilla.dm +++ b/code/modules/mob/living/basic/farm_animals/gorilla/gorilla.dm @@ -177,6 +177,19 @@ paralyze_chance = 0 initial_size = 0.9 +/mob/living/basic/gorilla/hostile + name = "Feral Gorilla" + maxHealth = 180 + health = 180 + desc = "A gorilla created via \"advanced genetic science\". While not quite as strong as their wildborne brethren, this simian still packs a punch." + melee_damage_lower = 15 + melee_damage_upper = 18 + obj_damage = 25 + speed = 0.1 + paralyze_chance = 0 + initial_size = 0.9 + faction = list(FACTION_HOSTILE) + /mob/living/basic/gorilla/genetics/Initialize(mapload) . = ..() qdel(GetComponent(/datum/component/amputating_limbs)) diff --git a/code/modules/mob/living/basic/jungle/seedling/seedling_ai.dm b/code/modules/mob/living/basic/jungle/seedling/seedling_ai.dm index 440cfc2861b69..ee93a9c12366f 100644 --- a/code/modules/mob/living/basic/jungle/seedling/seedling_ai.dm +++ b/code/modules/mob/living/basic/jungle/seedling/seedling_ai.dm @@ -37,6 +37,7 @@ hunt_range = 7 /datum/ai_behavior/find_and_set/treatable_hydro + action_cooldown = 5 SECONDS /datum/ai_behavior/find_and_set/treatable_hydro/search_tactic(datum/ai_controller/controller, locate_path, search_range) var/list/possible_trays = list() @@ -97,6 +98,9 @@ return FALSE set_movement_target(controller, target) +/datum/ai_behavior/find_and_set/beamable_hydroplants + action_cooldown = 15 SECONDS + /datum/ai_behavior/find_and_set/beamable_hydroplants/search_tactic(datum/ai_controller/controller, locate_path, search_range) var/list/possible_trays = list() @@ -136,7 +140,8 @@ return can_see(source, water_source, radius) /datum/ai_behavior/hunt_target/interact_with_target/water_source - behavior_flags = AI_BEHAVIOR_REQUIRE_MOVEMENT | AI_BEHAVIOR_REQUIRE_REACH | AI_BEHAVIOR_CAN_PLAN_DURING_EXECUTION + behavior_flags = AI_BEHAVIOR_REQUIRE_MOVEMENT | AI_BEHAVIOR_REQUIRE_REACH + always_reset_target = TRUE hunt_cooldown = 5 SECONDS /datum/ai_controller/basic_controller/seedling/meanie diff --git a/code/modules/mob/living/basic/jungle/seedling/seedling_projectiles.dm b/code/modules/mob/living/basic/jungle/seedling/seedling_projectiles.dm index 303776384d1f6..4e9e045958732 100644 --- a/code/modules/mob/living/basic/jungle/seedling/seedling_projectiles.dm +++ b/code/modules/mob/living/basic/jungle/seedling/seedling_projectiles.dm @@ -17,7 +17,7 @@ var/mob/living/living_target = target if(FACTION_JUNGLE in living_target.faction) - return + return BULLET_ACT_BLOCK return ..() diff --git a/code/modules/mob/living/basic/lavaland/watcher/watcher.dm b/code/modules/mob/living/basic/lavaland/watcher/watcher.dm index c7648aa38b259..5c4183b48ee6c 100644 --- a/code/modules/mob/living/basic/lavaland/watcher/watcher.dm +++ b/code/modules/mob/living/basic/lavaland/watcher/watcher.dm @@ -13,6 +13,9 @@ speed = 3 maxHealth = 160 health = 160 + melee_damage_lower = 15 + melee_damage_upper = 15 + attack_sound = 'sound/items/weapons/bladeslice.ogg' attack_verb_continuous = "buffets" attack_verb_simple = "buffet" crusher_loot = /obj/item/crusher_trophy/watcher_wing diff --git a/code/modules/mob/living/basic/pets/cat/kitten_ai.dm b/code/modules/mob/living/basic/pets/cat/kitten_ai.dm index 4136aa0aa0151..cdb7ac542e1a7 100644 --- a/code/modules/mob/living/basic/pets/cat/kitten_ai.dm +++ b/code/modules/mob/living/basic/pets/cat/kitten_ai.dm @@ -61,8 +61,7 @@ for(var/mob/living/carbon/human/human_target in oview(search_range, controller.pawn)) if(human_target.stat != CONSCIOUS || isnull(human_target.mind)) continue - if(!length(typecache_filter_list(human_target.held_items, locate_items))) - continue - return human_target - + for (var/obj/item/held_item in human_target.held_items) + if (is_type_in_typecache(held_item, locate_items)) + return human_target return null diff --git a/code/modules/mob/living/basic/slime/ai/behaviours.dm b/code/modules/mob/living/basic/slime/ai/behaviours.dm index fe8102eee112f..934404d88dd53 100644 --- a/code/modules/mob/living/basic/slime/ai/behaviours.dm +++ b/code/modules/mob/living/basic/slime/ai/behaviours.dm @@ -25,6 +25,7 @@ return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED /datum/ai_behavior/find_hunt_target/find_slime_food + action_cooldown = 7.5 SECONDS // Check if the slime can drain the target /datum/ai_behavior/find_hunt_target/find_slime_food/valid_dinner(mob/living/basic/slime/hunter, mob/living/dinner, radius, datum/ai_controller/controller, seconds_per_tick) diff --git a/code/modules/mob/living/basic/slime/ai/controller.dm b/code/modules/mob/living/basic/slime/ai/controller.dm index 41466b2973498..1d5f00e6c4381 100644 --- a/code/modules/mob/living/basic/slime/ai/controller.dm +++ b/code/modules/mob/living/basic/slime/ai/controller.dm @@ -4,7 +4,6 @@ BB_TARGETING_STRATEGY = /datum/targeting_strategy/basic/not_friends, BB_SLIME_RABID = FALSE, BB_SLIME_HUNGER_DISABLED = FALSE, - BB_CURRENT_HUNTING_TARGET = null, // people whose energy we want to drain ) ai_movement = /datum/ai_movement/basic_avoidance @@ -13,13 +12,12 @@ /datum/ai_planning_subtree/change_slime_face, /datum/ai_planning_subtree/use_mob_ability/evolve, /datum/ai_planning_subtree/use_mob_ability/reproduce, - /datum/ai_planning_subtree/target_retaliate, /datum/ai_planning_subtree/pet_planning, + /datum/ai_planning_subtree/target_retaliate, /datum/ai_planning_subtree/find_and_hunt_target/find_slime_food, /datum/ai_planning_subtree/basic_melee_attack_subtree/slime, /datum/ai_planning_subtree/random_speech/slime, ) - can_idle = FALSE /datum/ai_controller/basic_controller/slime/CancelActions() ..() diff --git a/code/modules/mob/living/basic/space_fauna/revenant/revenant_harvest.dm b/code/modules/mob/living/basic/space_fauna/revenant/revenant_harvest.dm index c162ecf2c213e..366cb1c5065ba 100644 --- a/code/modules/mob/living/basic/space_fauna/revenant/revenant_harvest.dm +++ b/code/modules/mob/living/basic/space_fauna/revenant/revenant_harvest.dm @@ -111,7 +111,7 @@ return FALSE var/datum/beam/draining_beam = Beam(target, icon_state = "drain_life") - if(!do_after(src, 4.6 SECONDS, target, timed_action_flags = (IGNORE_HELD_ITEM | IGNORE_INCAPACITATED))) //As one cannot prove the existance of ghosts, ghosts cannot prove the existance of the target they were draining. + if(!do_after(src, 4.6 SECONDS, target, timed_action_flags = (IGNORE_HELD_ITEM | IGNORE_INCAPACITATED))) //As one cannot prove the existence of ghosts, ghosts cannot prove the existence of the target they were draining. to_chat(src, span_revenwarning("[target ? "[target]'s soul has" : "[target_They_have]"] been drawn out of your grasp. The link has been broken.")) if(target) target.visible_message( diff --git a/code/modules/mob/living/brain/brain_item.dm b/code/modules/mob/living/brain/brain_item.dm index 39ec361ac9db5..f53c30d947b89 100644 --- a/code/modules/mob/living/brain/brain_item.dm +++ b/code/modules/mob/living/brain/brain_item.dm @@ -50,15 +50,6 @@ // Brain size logic transform = transform.Scale(brain_size) -/obj/item/organ/brain/examine() - . = ..() - if (smooth_brain) - . += span_notice("All the pesky wrinkles are gone. Now it just needs a good drying...") - if(brain_size < 1) - . += span_notice("It is a bit on the smaller side...") - if(brain_size > 1) - . += span_notice("It is bigger than average...") - /obj/item/organ/brain/mob_insert(mob/living/carbon/brain_owner, special = FALSE, movement_flags) . = ..() if(!.) @@ -140,7 +131,7 @@ organ_owner.clear_mood_event("brain_damage") /obj/item/organ/brain/update_icon_state() - icon_state = "[initial(icon_state)][smooth_brain ? "-smooth_brain" : ""]" + icon_state = "[initial(icon_state)][smooth_brain ? "-smooth" : ""]" return ..() /obj/item/organ/brain/proc/transfer_identity(mob/living/L) @@ -241,6 +232,8 @@ if(length(skillchips)) . += span_info("It has a skillchip embedded in it.") . += brain_damage_examine() + if (smooth_brain) + . += span_notice("All the pesky wrinkles are gone. Now it just needs a good drying...") if(brain_size < 1) . += span_notice("It is a bit on the smaller side...") if(brain_size > 1) @@ -625,7 +618,7 @@ /obj/item/organ/brain/proc/get_attacking_limb(mob/living/carbon/human/target) var/obj/item/bodypart/arm/active_hand = owner.get_active_hand() if(target.body_position == LYING_DOWN && owner.usable_legs) - var/obj/item/bodypart/found_bodypart = owner.get_bodypart((active_hand.held_index % 2) ? BODY_ZONE_L_LEG : BODY_ZONE_R_LEG) + var/obj/item/bodypart/found_bodypart = owner.get_bodypart(IS_LEFT_INDEX(active_hand.held_index) ? BODY_ZONE_L_LEG : BODY_ZONE_R_LEG) return found_bodypart || active_hand return active_hand diff --git a/code/modules/mob/living/carbon/alien/adult/adult.dm b/code/modules/mob/living/carbon/alien/adult/adult.dm index d2c41e61a12fb..45e9dea454dce 100644 --- a/code/modules/mob/living/carbon/alien/adult/adult.dm +++ b/code/modules/mob/living/carbon/alien/adult/adult.dm @@ -56,14 +56,16 @@ GLOBAL_LIST_INIT(strippable_alien_humanoid_items, create_strippable_list(list( ..() //For alien evolution/promotion/queen finder procs. Checks for an active alien of that type -/proc/get_alien_type(alienpath) - for(var/mob/living/carbon/alien/adult/A in GLOB.alive_mob_list) - if(!istype(A, alienpath)) +/proc/get_alien_type(alien_path, mob/ignored) + for(var/mob/living/carbon/alien/alien in GLOB.carbon_list) + if(alien == ignored) continue - if(!A.key || A.stat == DEAD) //Only living aliens with a ckey are valid. + if(!istype(alien, alien_path)) continue - return A - return FALSE + if(!alien.key || alien.stat == DEAD) //Only living aliens with a ckey are valid. + continue + return alien + return null /mob/living/carbon/alien/adult/check_breath(datum/gas_mixture/breath) if(breath?.total_moles() > 0 && !HAS_TRAIT(src, TRAIT_SNEAK)) diff --git a/code/modules/mob/living/carbon/alien/adult/queen.dm b/code/modules/mob/living/carbon/alien/adult/queen.dm index 8cbd55719774c..cfe6f45320a73 100644 --- a/code/modules/mob/living/carbon/alien/adult/queen.dm +++ b/code/modules/mob/living/carbon/alien/adult/queen.dm @@ -44,18 +44,6 @@ alien_speed = 2 /mob/living/carbon/alien/adult/royal/queen/Initialize(mapload) - //there should only be one queen - for(var/mob/living/carbon/alien/adult/royal/queen/Q in GLOB.carbon_list) - if(Q == src) - continue - if(Q.stat == DEAD) - continue - if(Q.client) - name = "alien princess ([rand(1, 999)])" //if this is too cutesy feel free to change it/remove it. - break - - real_name = src.name - var/static/list/innate_actions = list( /datum/action/cooldown/alien/promote, /datum/action/cooldown/spell/aoe/repulse/xeno, @@ -72,6 +60,11 @@ organs += new /obj/item/organ/alien/eggsac return ..() +/mob/living/carbon/alien/adult/royal/queen/set_name() + if(get_alien_type(/mob/living/carbon/alien/adult/royal/queen, ignored = src)) + name = "alien princess" + return ..() + //Queen verbs /datum/action/cooldown/alien/make_structure/lay_egg name = "Lay Egg" diff --git a/code/modules/mob/living/carbon/alien/alien.dm b/code/modules/mob/living/carbon/alien/alien.dm index 120633acdfe4a..124711098674d 100644 --- a/code/modules/mob/living/carbon/alien/alien.dm +++ b/code/modules/mob/living/carbon/alien/alien.dm @@ -22,7 +22,7 @@ gib_type = /obj/effect/decal/cleanable/xenoblood/xgibs unique_name = TRUE - var/static/regex/alien_name_regex = new("alien (larva|sentinel|drone|hunter|praetorian|queen)( \\(\\d+\\))?") + var/static/regex/alien_name_regex = new("alien (larva|sentinel|drone|hunter|praetorian|princess|queen)( \\(\\d+\\))?") var/static/list/xeno_allowed_items = typecacheof(list( /obj/item/clothing/mask/facehugger, /obj/item/toy/basketball, // playing ball against a xeno is rigged since they cannot be disarmed, their game is out of this world diff --git a/code/modules/mob/living/carbon/alien/death.dm b/code/modules/mob/living/carbon/alien/death.dm index 85092244510a7..8671a66c98aec 100644 --- a/code/modules/mob/living/carbon/alien/death.dm +++ b/code/modules/mob/living/carbon/alien/death.dm @@ -7,5 +7,10 @@ /mob/living/carbon/alien/gib_animation() new /obj/effect/temp_visual/gib_animation(loc, "gibbed-a") -/mob/living/carbon/alien/spawn_dust() - new /obj/effect/decal/remains/xeno(loc) +/mob/living/carbon/alien/spawn_dust(just_ash) + if(just_ash) + return ..() + + var/obj/effect/decal/remains/xeno/bones = new(loc) + bones.pixel_z = -6 + bones.pixel_w = rand(-1, 1) diff --git a/code/modules/mob/living/carbon/alien/larva/death.dm b/code/modules/mob/living/carbon/alien/larva/death.dm index f33ee4efdf17d..3c4500518de89 100644 --- a/code/modules/mob/living/carbon/alien/larva/death.dm +++ b/code/modules/mob/living/carbon/alien/larva/death.dm @@ -15,5 +15,10 @@ /mob/living/carbon/alien/larva/gib_animation() new /obj/effect/temp_visual/gib_animation(loc, "gibbed-l") -/mob/living/carbon/alien/larva/spawn_dust() - new /obj/effect/decal/remains/xeno(loc) +/mob/living/carbon/alien/larva/spawn_dust(just_ash) + if(just_ash) + return ..() + + var/obj/effect/decal/remains/xeno/bones = new(loc) + bones.pixel_z = -6 + bones.pixel_w = rand(-1, 1) diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm index 83861fe86f202..5abbe2018778b 100644 --- a/code/modules/mob/living/carbon/carbon.dm +++ b/code/modules/mob/living/carbon/carbon.dm @@ -572,7 +572,11 @@ set_health(round(maxHealth - getOxyLoss() - getToxLoss() - total_burn - total_brute, DAMAGE_PRECISION)) update_stat() update_stamina() - if(((maxHealth - total_burn) < HEALTH_THRESHOLD_DEAD*2) && stat == DEAD ) + + /// The amount of burn damage needed to be done for this mob to be husked + var/husk_threshold = get_bodypart(BODY_ZONE_CHEST).max_damage * -1 + + if(((maxHealth - total_burn) < husk_threshold) && stat == DEAD ) become_husk(BURN) med_hud_set_health() if(stat == SOFT_CRIT) diff --git a/code/modules/mob/living/carbon/carbon_update_icons.dm b/code/modules/mob/living/carbon/carbon_update_icons.dm index abf88d91733de..ed380a66d4192 100644 --- a/code/modules/mob/living/carbon/carbon_update_icons.dm +++ b/code/modules/mob/living/carbon/carbon_update_icons.dm @@ -272,7 +272,7 @@ break var/icon_file = I.lefthand_file - if(get_held_index_of_item(I) % 2 == 0) + if(IS_RIGHT_INDEX(get_held_index_of_item(I))) icon_file = I.righthand_file hands += I.build_worn_icon(default_layer = HANDS_LAYER, default_icon_file = icon_file, isinhands = TRUE) diff --git a/code/modules/mob/living/carbon/human/death.dm b/code/modules/mob/living/carbon/human/death.dm index b3b88d8721905..130e3c1ca8bb3 100644 --- a/code/modules/mob/living/carbon/human/death.dm +++ b/code/modules/mob/living/carbon/human/death.dm @@ -18,11 +18,17 @@ GLOBAL_LIST_EMPTY(dead_players_during_shift) else new /obj/effect/gibspawner/human/bodypartless(drop_location(), src, get_static_viruses()) -/mob/living/carbon/human/spawn_dust(just_ash = FALSE) +/mob/living/carbon/human/spawn_dust(just_ash) if(just_ash) - new /obj/effect/decal/cleanable/ash(loc) - else - new /obj/effect/decal/remains/human(loc) + return ..() + + var/bone_type = /obj/effect/decal/remains/human + if(isplasmaman(src)) + bone_type = /obj/effect/decal/remains/plasma + + var/obj/effect/decal/remains/human/bones = new bone_type(loc) + bones.pixel_z = -6 + bones.pixel_w = rand(-1, 1) /mob/living/carbon/human/death(gibbed) if(stat == DEAD) diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index 5b0e64547a016..bd72ff464a958 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -1192,7 +1192,7 @@ race = /datum/species/snail /mob/living/carbon/human/species/vampire - race = /datum/species/vampire + race = /datum/species/human/vampire /mob/living/carbon/human/species/zombie race = /datum/species/zombie diff --git a/code/modules/mob/living/carbon/human/human_defense.dm b/code/modules/mob/living/carbon/human/human_defense.dm index 13700dd5aad29..8df7c758e2b1e 100644 --- a/code/modules/mob/living/carbon/human/human_defense.dm +++ b/code/modules/mob/living/carbon/human/human_defense.dm @@ -378,9 +378,12 @@ else if(wear_suit.siemens_coefficient <= 0) siemens_coeff -= 0.95 siemens_coeff = max(siemens_coeff, 0) - else if(!(flags & SHOCK_NOGLOVES)) //This gets the siemens_coeff for all non tesla shocks - if(gloves) - siemens_coeff *= gloves.siemens_coefficient + if(flags & SHOCK_NOGLOVES) //This gets the siemens_coeff for all non tesla shocks + if(wear_suit) + siemens_coeff *= wear_suit.siemens_coefficient + else if(gloves) + siemens_coeff *= gloves.siemens_coefficient + siemens_coeff *= physiology.siemens_coeff siemens_coeff *= dna.species.siemens_coeff . = ..() diff --git a/code/modules/mob/living/carbon/human/human_helpers.dm b/code/modules/mob/living/carbon/human/human_helpers.dm index 278c72ed535cf..5406fae39e8d5 100644 --- a/code/modules/mob/living/carbon/human/human_helpers.dm +++ b/code/modules/mob/living/carbon/human/human_helpers.dm @@ -130,7 +130,7 @@ /mob/living/carbon/human/proc/check_chunky_fingers() if(HAS_TRAIT_NOT_FROM(src, TRAIT_CHUNKYFINGERS, RIGHT_ARM_TRAIT) && HAS_TRAIT_NOT_FROM(src, TRAIT_CHUNKYFINGERS, LEFT_ARM_TRAIT)) return TRUE - return (active_hand_index % 2) ? HAS_TRAIT_FROM(src, TRAIT_CHUNKYFINGERS, LEFT_ARM_TRAIT) : HAS_TRAIT_FROM(src, TRAIT_CHUNKYFINGERS, RIGHT_ARM_TRAIT) + return IS_LEFT_INDEX(active_hand_index) ? HAS_TRAIT_FROM(src, TRAIT_CHUNKYFINGERS, LEFT_ARM_TRAIT) : HAS_TRAIT_FROM(src, TRAIT_CHUNKYFINGERS, RIGHT_ARM_TRAIT) /mob/living/carbon/human/get_policy_keywords() . = ..() diff --git a/code/modules/mob/living/carbon/human/human_update_icons.dm b/code/modules/mob/living/carbon/human/human_update_icons.dm index a13c2aa11be5b..96dddf334f28d 100644 --- a/code/modules/mob/living/carbon/human/human_update_icons.dm +++ b/code/modules/mob/living/carbon/human/human_update_icons.dm @@ -631,8 +631,8 @@ There are several things that need to be remembered: t_state = worn_item.icon_state var/mutable_appearance/hand_overlay - var/icon_file = held_index % 2 == 0 ? worn_item.righthand_file : worn_item.lefthand_file - hand_overlay = worn_item.build_worn_icon(default_layer = HANDS_LAYER, default_icon_file = icon_file, isinhands = TRUE, humie = src) /// DOPPLER SHIFT EDIT + var/icon_file = IS_RIGHT_INDEX(held_index) ? worn_item.righthand_file : worn_item.lefthand_file + hand_overlay = worn_item.build_worn_icon(default_layer = HANDS_LAYER, default_icon_file = icon_file, isinhands = TRUE) var/obj/item/bodypart/arm/held_in_hand = hand_bodyparts[held_index] held_in_hand?.held_hand_offset?.apply_offset(hand_overlay) diff --git a/code/modules/mob/living/carbon/human/inventory.dm b/code/modules/mob/living/carbon/human/inventory.dm index 02f627459cb93..219060012fc39 100644 --- a/code/modules/mob/living/carbon/human/inventory.dm +++ b/code/modules/mob/living/carbon/human/inventory.dm @@ -424,7 +424,7 @@ hand_bodyparts.len = amt for(var/i in old_limbs+1 to amt) var/path = /obj/item/bodypart/arm/left - if(!(i % 2)) + if(IS_RIGHT_INDEX(i)) path = /obj/item/bodypart/arm/right var/obj/item/bodypart/BP = new path () diff --git a/code/modules/mob/living/carbon/human/species_types/vampire.dm b/code/modules/mob/living/carbon/human/species_types/vampire.dm index d0b052a888865..44b5d9590387a 100644 --- a/code/modules/mob/living/carbon/human/species_types/vampire.dm +++ b/code/modules/mob/living/carbon/human/species_types/vampire.dm @@ -4,7 +4,7 @@ ///maximum a vampire will drain, they will drain less if they hit their cap #define VAMP_DRAIN_AMOUNT 50 -/datum/species/vampire +/datum/species/human/vampire name = "Vampire" id = SPECIES_VAMPIRE examine_limb_id = SPECIES_HUMAN @@ -18,33 +18,30 @@ ) inherent_biotypes = MOB_UNDEAD|MOB_HUMANOID changesource_flags = MIRROR_BADMIN | MIRROR_PRIDE | WABBAJACK | ERT_SPAWN - exotic_bloodtype = "U" + exotic_bloodtype = "V" blood_deficiency_drain_rate = BLOOD_DEFICIENCY_MODIFIER // vampires already passively lose blood, so this just makes them lose it slightly more quickly when they have blood deficiency. mutantheart = /obj/item/organ/heart/vampire mutanttongue = /obj/item/organ/tongue/vampire - mutantstomach = null - mutantlungs = null - skinned_type = /obj/item/stack/sheet/animalhide/human ///some starter text sent to the vampire initially, because vampires have shit to do to stay alive var/info_text = "You are a Vampire. You will slowly but constantly lose blood if outside of a coffin. If inside a coffin, you will slowly heal. You may gain more blood by grabbing a live victim and using your drain ability." -/datum/species/vampire/check_roundstart_eligible() +/datum/species/human/vampire/check_roundstart_eligible() if(check_holidays(HALLOWEEN)) return TRUE return ..() -/datum/species/vampire/on_species_gain(mob/living/carbon/human/new_vampire, datum/species/old_species) +/datum/species/human/vampire/on_species_gain(mob/living/carbon/human/new_vampire, datum/species/old_species) . = ..() to_chat(new_vampire, "[info_text]") new_vampire.skin_tone = "albino" new_vampire.update_body(0) RegisterSignal(new_vampire, COMSIG_MOB_APPLY_DAMAGE_MODIFIERS, PROC_REF(damage_weakness)) -/datum/species/vampire/on_species_loss(mob/living/carbon/human/C, datum/species/new_species, pref_load) +/datum/species/human/vampire/on_species_loss(mob/living/carbon/human/C, datum/species/new_species, pref_load) . = ..() UnregisterSignal(C, COMSIG_MOB_APPLY_DAMAGE_MODIFIERS) -/datum/species/vampire/spec_life(mob/living/carbon/human/vampire, seconds_per_tick, times_fired) +/datum/species/human/vampire/spec_life(mob/living/carbon/human/vampire, seconds_per_tick, times_fired) . = ..() if(istype(vampire.loc, /obj/structure/closet/crate/coffin)) var/need_mob_update = FALSE @@ -66,27 +63,27 @@ vampire.adjust_fire_stacks(3 * seconds_per_tick) vampire.ignite_mob() -/datum/species/vampire/proc/damage_weakness(datum/source, list/damage_mods, damage_amount, damagetype, def_zone, sharpness, attack_direction, obj/item/attacking_item) +/datum/species/human/vampire/proc/damage_weakness(datum/source, list/damage_mods, damage_amount, damagetype, def_zone, sharpness, attack_direction, obj/item/attacking_item) SIGNAL_HANDLER if(istype(attacking_item, /obj/item/nullrod/whip)) damage_mods += 2 -/datum/species/vampire/get_physical_attributes() +/datum/species/human/vampire/get_physical_attributes() return "Vampires are afflicted with the Thirst, needing to sate it by draining the blood out of another living creature. However, they do not need to breathe or eat normally. \ They will instantly turn into dust if they run out of blood or enter a holy area. However, coffins stabilize and heal them, and they can transform into bats!" -/datum/species/vampire/get_species_description() +/datum/species/human/vampire/get_species_description() return "A classy Vampire! They descend upon Space Station Thirteen Every year to spook the crew! \"Bleeg!!\"" -/datum/species/vampire/get_species_lore() +/datum/species/human/vampire/get_species_lore() return list( "Vampires are unholy beings blessed and cursed with The Thirst. \ The Thirst requires them to feast on blood to stay alive, and in return it gives them many bonuses. \ Because of this, Vampires have split into two clans, one that embraces their powers as a blessing and one that rejects it.", ) -/datum/species/vampire/create_pref_unique_perks() +/datum/species/human/vampire/create_pref_unique_perks() var/list/to_add = list() to_add += list( @@ -115,7 +112,7 @@ return to_add // Vampire blood is special, so it needs to be handled with its own entry. -/datum/species/vampire/create_pref_blood_perks() +/datum/species/human/vampire/create_pref_blood_perks() var/list/to_add = list() to_add += list(list( @@ -132,7 +129,7 @@ return to_add // There isn't a "Minor Undead" biotype, so we have to explain it in an override (see: dullahans) -/datum/species/vampire/create_pref_biotypes_perks() +/datum/species/human/vampire/create_pref_biotypes_perks() var/list/to_add = list() to_add += list(list( diff --git a/code/modules/mob/living/carbon/life.dm b/code/modules/mob/living/carbon/life.dm index 93d6f9ce2e19f..e80ba0c95be0d 100644 --- a/code/modules/mob/living/carbon/life.dm +++ b/code/modules/mob/living/carbon/life.dm @@ -124,9 +124,9 @@ //Tries to play the carbon a breathing sound when using internals, also invokes check_breath /mob/living/carbon/proc/try_breathing_sound(breath) var/should_be_on = canon_client?.prefs?.read_preference(/datum/preference/toggle/sound_breathing) - if(should_be_on && !breathing_loop.timer_id) + if(should_be_on && !breathing_loop.timer_id && canon_client?.mob.can_hear()) breathing_loop.start() - else if(!should_be_on && breathing_loop.timer_id) + else if((!should_be_on && breathing_loop.timer_id) || !canon_client?.mob.can_hear()) breathing_loop.stop() /mob/living/carbon/proc/has_smoke_protection() diff --git a/code/modules/mob/living/death.dm b/code/modules/mob/living/death.dm index 8688e256022ba..6616736a61064 100644 --- a/code/modules/mob/living/death.dm +++ b/code/modules/mob/living/death.dm @@ -98,7 +98,7 @@ ghostize() QDEL_IN(src, DUST_ANIMATION_TIME) // since this is sometimes called in the middle of movement, allow half a second for movement to finish, ghosting to happen and animation to play. Looks much nicer and doesn't cause multiple runtimes. -/// Animates turning into dust +/// Animates turning into dust. /// Does not delete src afterwards, BUT it will become invisible (and grey), so ensure you handle that yourself /atom/movable/proc/dust_animation(atom/anim_loc = src.loc) if(isnull(anim_loc)) // the effect breaks if we have a null loc @@ -130,8 +130,19 @@ #undef DUST_ANIMATION_TIME +/** + * Spawns dust / ash or remains where the mob was + * + * just_ash: If TRUE, just ash will spawn where the mob was, as opposed to remains + */ /mob/living/proc/spawn_dust(just_ash = FALSE) - new /obj/effect/decal/cleanable/ash(loc) + var/ash_type = /obj/effect/decal/cleanable/ash + if(mob_size >= MOB_SIZE_LARGE) + ash_type = /obj/effect/decal/cleanable/ash/large + + var/obj/effect/decal/cleanable/ash/ash = new ash_type(loc) + ash.pixel_z = -5 + ash.pixel_w = rand(-1, 1) /* * Called when the mob dies. Can also be called manually to kill a mob. diff --git a/code/modules/mob/living/emote.dm b/code/modules/mob/living/emote.dm index 395b1d71792ad..8adfe4e888d27 100644 --- a/code/modules/mob/living/emote.dm +++ b/code/modules/mob/living/emote.dm @@ -140,22 +140,27 @@ /datum/emote/living/flap/run_emote(mob/user, params, type_override, intentional) . = ..() - if(ishuman(user)) - var/mob/living/carbon/human/human_user = user - var/open = FALSE - var/obj/item/organ/wings/functional/wings = human_user.get_organ_slot(ORGAN_SLOT_EXTERNAL_WINGS) - - // open/close functional wings - if(istype(wings)) - if(wings.wings_open) - open = TRUE - wings.close_wings() - else - wings.open_wings() - addtimer(CALLBACK(wings, open ? TYPE_PROC_REF(/obj/item/organ/wings/functional, open_wings) : TYPE_PROC_REF(/obj/item/organ/wings/functional, close_wings)), wing_time) + if(!ishuman(user)) + return + var/mob/living/carbon/human/human_user = user + var/obj/item/organ/wings/wings = human_user.get_organ_slot(ORGAN_SLOT_EXTERNAL_WINGS) - // play a flapping noise if the wing has this implemented - wings.make_flap_sound(human_user) + // play a flapping noise if the wing has this implemented + if(!istype(wings)) + return + wings.make_flap_sound(human_user) + + // open/close functional wings + var/obj/item/organ/wings/functional/wings_functional = wings + if(!istype(wings_functional)) + return + var/open = FALSE + if(wings_functional.wings_open) + open = TRUE + wings_functional.close_wings() + else + wings_functional.open_wings() + addtimer(CALLBACK(wings_functional, open ? TYPE_PROC_REF(/obj/item/organ/wings/functional, open_wings) : TYPE_PROC_REF(/obj/item/organ/wings/functional, close_wings)), wing_time) /datum/emote/living/flap/aflap key = "aflap" diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index c0d2e1d4785c0..dca88762970f4 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -388,7 +388,7 @@ if(pulling) // Are we trying to pull something we are already pulling? Then just stop here, no need to continue. if(AM == pulling) - return + return FALSE stop_pulling() changeNext_move(CLICK_CD_GRABBING) @@ -456,6 +456,7 @@ update_pull_movespeed() set_pull_offsets(M, state) + return TRUE /mob/living/proc/set_pull_offsets(mob/living/M, grab_state = GRAB_PASSIVE) if(M.buckled) diff --git a/code/modules/mob/living/silicon/death.dm b/code/modules/mob/living/silicon/death.dm index 85e749d276541..67083168eb30e 100644 --- a/code/modules/mob/living/silicon/death.dm +++ b/code/modules/mob/living/silicon/death.dm @@ -1,8 +1,13 @@ /mob/living/silicon/spawn_gibs() new /obj/effect/gibspawner/robot(drop_location(), src) -/mob/living/silicon/spawn_dust() - new /obj/effect/decal/remains/robot(loc) +/mob/living/silicon/spawn_dust(just_ash) + if(just_ash) + return ..() + + var/obj/effect/decal/remains/robot/robones = new(loc) + robones.pixel_z = -6 + robones.pixel_w = rand(-1, 1) /mob/living/silicon/death(gibbed) diag_hud_set_status() diff --git a/code/modules/mob/living/silicon/robot/death.dm b/code/modules/mob/living/silicon/robot/death.dm index 91627b5099fe5..99c5686aa5325 100644 --- a/code/modules/mob/living/silicon/robot/death.dm +++ b/code/modules/mob/living/silicon/robot/death.dm @@ -7,9 +7,6 @@ QDEL_NULL(mmi) return ..() -/mob/living/silicon/robot/spawn_dust() - new /obj/effect/decal/remains/robot(loc) - /mob/living/silicon/robot/death(gibbed) if(stat == DEAD) return diff --git a/code/modules/mob/living/silicon/robot/robot_defense.dm b/code/modules/mob/living/silicon/robot/robot_defense.dm index d9caad422927e..323420cb8ae7f 100644 --- a/code/modules/mob/living/silicon/robot/robot_defense.dm +++ b/code/modules/mob/living/silicon/robot/robot_defense.dm @@ -456,7 +456,7 @@ GLOBAL_LIST_INIT(blacklisted_borg_hats, typecacheof(list( //Hats that don't real if(EXPLODE_DEVASTATE) investigate_log("has been gibbed by an explosion.", INVESTIGATE_DEATHS) gib(DROP_ALL_REMAINS) - return + return TRUE if(EXPLODE_HEAVY) if (stat != DEAD) adjustBruteLoss(60) diff --git a/code/modules/mob/living/simple_animal/bot/construction.dm b/code/modules/mob/living/simple_animal/bot/construction.dm index 80e2b8c0c8343..6a60620914476 100644 --- a/code/modules/mob/living/simple_animal/bot/construction.dm +++ b/code/modules/mob/living/simple_animal/bot/construction.dm @@ -190,67 +190,63 @@ to_chat(user, span_notice("You complete the ED-209.")) qdel(src) -//Floorbot assemblies -/obj/item/bot_assembly/floorbot +//Repairbot assemblies +/obj/item/bot_assembly/repairbot desc = "It's a toolbox with tiles sticking out the top." - name = "tiles and toolbox" - icon_state = "toolbox_tiles" + name = "Repairbot Chasis" + icon_state = "repairbot_base" throwforce = 10 - created_name = "Floorbot" + created_name = "Repairbot" var/toolbox = /obj/item/storage/toolbox/mechanical var/toolbox_color = "" //Blank for blue, r for red, y for yellow, etc. -/obj/item/bot_assembly/floorbot/Initialize(mapload) +/obj/item/bot_assembly/repairbot/Initialize(mapload) . = ..() update_appearance() -/obj/item/bot_assembly/floorbot/update_name() - . = ..() - switch(build_step) - if(ASSEMBLY_SECOND_STEP) - name = "incomplete floorbot assembly" - else - name = initial(name) +/obj/item/bot_assembly/repairbot/proc/set_color(new_color) + add_atom_colour(new_color, FIXED_COLOUR_PRIORITY) + toolbox_color = new_color -/obj/item/bot_assembly/floorbot/update_desc() +/obj/item/bot_assembly/repairbot/update_desc() . = ..() switch(build_step) - if(ASSEMBLY_SECOND_STEP) - desc = "It's a toolbox with tiles sticking out the top and a sensor attached." + if(ASSEMBLY_FIRST_STEP) + desc = "It's a toolbox with a giant monitor sticking out!." else desc = initial(desc) -/obj/item/bot_assembly/floorbot/update_icon_state() +/obj/item/bot_assembly/repairbot/update_overlays() . = ..() - switch(build_step) - if(ASSEMBLY_FIRST_STEP) - icon_state = "[toolbox_color]toolbox_tiles" - if(ASSEMBLY_SECOND_STEP) - icon_state = "[toolbox_color]toolbox_tiles_sensor" + if(build_step >= ASSEMBLY_FIRST_STEP) + . += mutable_appearance(icon, "repairbot_base_sensor", appearance_flags = RESET_COLOR) + if(build_step >= ASSEMBLY_SECOND_STEP) + . += mutable_appearance(icon, "repairbot_base_arms", appearance_flags = RESET_COLOR) -/obj/item/bot_assembly/floorbot/attackby(obj/item/W, mob/user, params) +/obj/item/bot_assembly/repairbot/attackby(obj/item/item, mob/user, params) ..() switch(build_step) if(ASSEMBLY_FIRST_STEP) - if(isprox(W)) - if(!user.temporarilyRemoveItemFromInventory(W)) - return - to_chat(user, span_notice("You add [W] to [src].")) - qdel(W) - build_step++ - update_appearance() - + if(!istype(item, /obj/item/bodypart/arm/left/robot) && !istype(item, /obj/item/bodypart/arm/right/robot)) + return + if(!can_finish_build(item, user)) + return + build_step++ + to_chat(user, span_notice("You add [item] to [src]. Boop beep!")) + qdel(item) + update_appearance() if(ASSEMBLY_SECOND_STEP) - if(istype(W, /obj/item/bodypart/arm/left/robot) || istype(W, /obj/item/bodypart/arm/right/robot)) - if(!can_finish_build(W, user)) - return - var/mob/living/simple_animal/bot/floorbot/A = new(drop_location(), toolbox_color) - A.name = created_name - A.robot_arm = W.type - A.toolbox = toolbox - to_chat(user, span_notice("You add [W] to [src]. Boop beep!")) - qdel(W) - qdel(src) + if(!istype(item, /obj/item/stack/conveyor)) + return + if(!can_finish_build(item, user)) + return + var/mob/living/basic/bot/repairbot/repair = new(drop_location()) + repair.name = created_name + repair.toolbox = toolbox + repair.set_color(toolbox_color) + to_chat(user, span_notice("You add [item] to [src]. Boop beep!")) + qdel(item) + qdel(src) //Medbot Assembly diff --git a/code/modules/mob/living/simple_animal/bot/floorbot.dm b/code/modules/mob/living/simple_animal/bot/floorbot.dm deleted file mode 100644 index ae17e58686c65..0000000000000 --- a/code/modules/mob/living/simple_animal/bot/floorbot.dm +++ /dev/null @@ -1,448 +0,0 @@ -#define HULL_BREACH 1 -#define LINE_SPACE_MODE 2 -#define FIX_TILE 3 -#define AUTO_TILE 4 -#define PLACE_TILE 5 -#define REPLACE_TILE 6 -#define TILE_EMAG 7 - -//Floorbot -/mob/living/simple_animal/bot/floorbot - name = "\improper Floorbot" - desc = "A little floor repairing robot, he looks so excited!" - icon = 'icons/mob/silicon/aibots.dmi' - icon_state = "floorbot0" - density = FALSE - health = 25 - maxHealth = 25 - - req_one_access = list(ACCESS_ROBOTICS, ACCESS_CONSTRUCTION) - radio_key = /obj/item/encryptionkey/headset_eng - radio_channel = RADIO_CHANNEL_ENGINEERING - bot_type = FLOOR_BOT - hackables = "floor construction protocols" - path_image_color = "#FFA500" - possessed_message = "You are a floorbot! Repair the hull to the best of your ability!" - - var/process_type //Determines what to do when process_scan() receives a target. See process_scan() for details. - var/targetdirection - var/replacetiles = FALSE - var/placetiles = FALSE - var/maxtiles = 100 - var/obj/item/stack/tile/tilestack - var/fixfloors = TRUE - var/autotile = FALSE - var/turf/target - var/toolbox = /obj/item/storage/toolbox/mechanical - var/toolbox_color = "" - -/mob/living/simple_animal/bot/floorbot/Initialize(mapload, new_toolbox_color) - . = ..() - ADD_TRAIT(src, TRAIT_SPACEWALK, INNATE_TRAIT) - toolbox_color = new_toolbox_color - update_appearance(UPDATE_ICON) - - // Doing this hurts my soul, but simplebot access reworks are for another day. - var/datum/id_trim/job/engi_trim = SSid_access.trim_singletons_by_path[/datum/id_trim/job/station_engineer] - access_card.add_access(engi_trim.access + engi_trim.wildcard_access) - prev_access = access_card.access.Copy() - - if(toolbox_color == "s") - health = 100 - maxHealth = 100 - -/mob/living/simple_animal/bot/floorbot/Exited(atom/movable/gone, direction) - if(tilestack == gone) - if(tilestack && tilestack.max_amount < tilestack.amount) //split the stack if it exceeds its normal max_amount - var/iterations = round(tilestack.amount/tilestack.max_amount) //round() without second arg floors the value - for(var/a in 1 to iterations) - if(a == iterations) - tilestack.split_stack(null, tilestack.amount - tilestack.max_amount) - else - tilestack.split_stack(null, tilestack.max_amount) - tilestack = null - -/mob/living/simple_animal/bot/floorbot/turn_on() - . = ..() - update_appearance() - -/mob/living/simple_animal/bot/floorbot/turn_off() - ..() - update_appearance() - -/mob/living/simple_animal/bot/floorbot/bot_reset() - ..() - target = null - toggle_magnet(FALSE) - -/mob/living/simple_animal/bot/floorbot/attackby(obj/item/W , mob/user, params) - if(istype(W, /obj/item/stack/tile/iron)) - to_chat(user, span_notice("The floorbot can produce normal tiles itself.")) - return - if(istype(W, /obj/item/stack/tile)) - var/old_amount = tilestack ? tilestack.amount : 0 - var/obj/item/stack/tile/tiles = W - if(tilestack) - if(!tiles.can_merge(tilestack)) - to_chat(user, span_warning("Different custom tiles are already inside the floorbot.")) - return - if(tilestack.amount >= maxtiles) - to_chat(user, span_warning("The floorbot can't hold any more custom tiles.")) - return - tiles.merge(tilestack, maxtiles) - else - if(tiles.amount > maxtiles) - tilestack = tilestack.split_stack(null, maxtiles) - else - tilestack = W - tilestack.forceMove(src) - to_chat(user, span_notice("You load [tilestack.amount - old_amount] tiles into the floorbot. It now contains [tilestack.amount] tiles.")) - return - else - ..() - -/mob/living/simple_animal/bot/floorbot/emag_act(mob/user, obj/item/card/emag/emag_card) - . = ..() - if(!(bot_cover_flags & BOT_COVER_EMAGGED)) - return - balloon_alert(user, "safeties disabled") - audible_message(span_danger("[src] buzzes oddly!")) - return TRUE - -///mobs should use move_resist instead of anchored. -/mob/living/simple_animal/bot/floorbot/proc/toggle_magnet(engage = TRUE, change_icon = TRUE) - if(engage) - ADD_TRAIT(src, TRAIT_IMMOBILIZED, BUSY_FLOORBOT_TRAIT) - move_resist = INFINITY - if(change_icon) - icon_state = "[toolbox_color]floorbot-c" - else - REMOVE_TRAIT(src, TRAIT_IMMOBILIZED, BUSY_FLOORBOT_TRAIT) - move_resist = initial(move_resist) - if(change_icon) - update_icon() - -// Variables sent to TGUI -/mob/living/simple_animal/bot/floorbot/ui_data(mob/user) - var/list/data = ..() - if(!(bot_cover_flags & BOT_COVER_LOCKED) || HAS_SILICON_ACCESS(user)) - data["custom_controls"]["tile_hull"] = autotile - data["custom_controls"]["place_tiles"] = placetiles - data["custom_controls"]["place_custom"] = replacetiles - data["custom_controls"]["repair_damage"] = fixfloors - data["custom_controls"]["traction_magnets"] = !!HAS_TRAIT_FROM(src, TRAIT_IMMOBILIZED, BUSY_FLOORBOT_TRAIT) - data["custom_controls"]["tile_stack"] = 0 - data["custom_controls"]["line_mode"] = FALSE - if(tilestack) - data["custom_controls"]["tile_stack"] = tilestack.amount - if(targetdirection) - data["custom_controls"]["line_mode"] = dir2text(targetdirection) - return data - -// Actions received from TGUI -/mob/living/simple_animal/bot/floorbot/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state) - . = ..() - var/mob/user = ui.user - if(. || (bot_cover_flags & BOT_COVER_LOCKED && !HAS_SILICON_ACCESS(user))) - return - - switch(action) - if("place_custom") - replacetiles = !replacetiles - if("place_tiles") - placetiles = !placetiles - if("repair_damage") - fixfloors = !fixfloors - if("tile_hull") - autotile = !autotile - if("traction_magnets") - toggle_magnet(!HAS_TRAIT_FROM(src, TRAIT_IMMOBILIZED, BUSY_FLOORBOT_TRAIT), FALSE) - if("eject_tiles") - if(tilestack) - tilestack.forceMove(drop_location()) - if("line_mode") - var/setdir = tgui_input_list(user, "Select construction direction", "Direction", list("north", "east", "south", "west", "disable")) - if(isnull(setdir) || QDELETED(ui) || ui.status != UI_INTERACTIVE) - return - switch(setdir) - if("north") - targetdirection = 1 - if("south") - targetdirection = 2 - if("east") - targetdirection = 4 - if("west") - targetdirection = 8 - if("disable") - targetdirection = null - -/mob/living/simple_animal/bot/floorbot/handle_automated_action() - if(!..()) - return - - if(mode == BOT_REPAIRING) - return - - if(prob(5)) - audible_message("[src] makes an excited booping beeping sound!") - - var/list/tiles_scanned = list() - //Normal scanning procedure. We have tiles loaded, are not emagged. - if(!target && !(bot_cover_flags & BOT_COVER_EMAGGED)) - if(targetdirection != null) //The bot is in line mode. - var/turf/T = get_step(src, targetdirection) - if(isspaceturf(T)) //Check for space - target = T - process_type = LINE_SPACE_MODE - if(isfloorturf(T)) //Check for floor - target = T - if(!target) - process_type = HULL_BREACH //Ensures the floorbot does not try to "fix" space areas or shuttle docking zones. - - tiles_scanned += list(/turf/open/space) - - if(!target && placetiles) //Finds a floor without a tile and gives it one. - process_type = PLACE_TILE //The target must be the floor and not a tile. The floor must not already have a floortile. - tiles_scanned += list(/turf/open/floor) - - if(!target && fixfloors) //Repairs damaged floors and tiles. - process_type = FIX_TILE - tiles_scanned += list(/turf/open/floor) - - if(!target && replacetiles && tilestack) //Replace a floor tile with custom tile - process_type = REPLACE_TILE //The target must be a tile. The floor must already have a floortile. - tiles_scanned += list(/turf/open/floor) - - if(!target && bot_cover_flags & BOT_COVER_EMAGGED) //We are emagged! Time to rip up the floors! - process_type = TILE_EMAG - tiles_scanned += list(/turf/open/floor) - - target = scan(tiles_scanned) - - if (!target) - if(bot_mode_flags & BOT_MODE_AUTOPATROL) - switch(mode) - if(BOT_IDLE, BOT_START_PATROL) - start_patrol() - if(BOT_PATROL) - bot_patrol() - return - - if(loc == target || loc == get_turf(target)) - if(check_bot(target)) //Target is not defined at the parent - if(prob(50)) //50% chance to still try to repair so we dont end up with 2 floorbots failing to fix the last breach - target = null - path = list() - return - if(isturf(target) && !(bot_cover_flags & BOT_COVER_EMAGGED)) - repair(target) - else if(bot_cover_flags & BOT_COVER_EMAGGED && isfloorturf(target)) - var/turf/open/floor/floor = target - toggle_magnet() - mode = BOT_REPAIRING - if(isplatingturf(floor)) - floor.attempt_lattice_replacement() - else - floor.ScrapeAway(flags = CHANGETURF_INHERIT_AIR) - audible_message(span_danger("[src] makes an excited booping sound.")) - addtimer(CALLBACK(src, PROC_REF(go_idle)), 0.5 SECONDS) - path = list() - return - - if(!length(path)) - if(!isturf(target)) - var/turf/TL = get_turf(target) - path = get_path_to(src, TL, max_distance=30, access=access_card.GetAccess(), simulated_only = FALSE) - else - path = get_path_to(src, target, max_distance=30, access=access_card.GetAccess(), simulated_only = FALSE) - - if(!bot_move(target)) - add_to_ignore(target) - target = null - mode = BOT_IDLE - else if(!bot_move(target)) - target = null - mode = BOT_IDLE - -/mob/living/simple_animal/bot/floorbot/proc/go_idle() - if (QDELETED(src)) - return - toggle_magnet(FALSE) - mode = BOT_IDLE - target = null - -/mob/living/simple_animal/bot/floorbot/proc/is_hull_breach(turf/t) //Ignore space tiles not considered part of a structure, also ignores shuttle docking areas. - var/area/t_area = get_area(t) - if(t_area && (t_area.name == "Space" || findtext(t_area.name, "huttle"))) - return FALSE - else - return TRUE - -//Floorbots, having several functions, need sort out special conditions here. -/mob/living/simple_animal/bot/floorbot/process_scan(scan_target) - var/result - var/turf/open/floor/floor - move_resist = initial(move_resist) - switch(process_type) - if(HULL_BREACH) //The most common job, patching breaches in the station's hull. - if(is_hull_breach(scan_target)) //Ensure that the targeted space turf is actually part of the station, and not random space. - result = scan_target - move_resist = INFINITY //Prevent the floorbot being blown off-course while trying to reach a hull breach. - if(LINE_SPACE_MODE) //Space turfs in our chosen direction are considered. - if(get_dir(src, scan_target) == targetdirection) - result = scan_target - move_resist = INFINITY - if(PLACE_TILE) - floor = scan_target - if(isplatingturf(floor)) //The floor must not already have a tile. - result = floor - if(REPLACE_TILE) - floor = scan_target - if(isfloorturf(floor) && !isplatingturf(floor)) //The floor must already have a tile. - result = floor - if(FIX_TILE) //Selects only damaged floors. - floor = scan_target - if(istype(floor) && (floor.broken || floor.burnt)) - result = floor - if(TILE_EMAG) //Emag mode! Rip up the floor and cause breaches to space! - floor = scan_target - if(!isplatingturf(floor)) - result = floor - else //If no special processing is needed, simply return the result. - result = scan_target - return result - -/mob/living/simple_animal/bot/floorbot/proc/repair(turf/target_turf) - if(check_bot_working(target_turf)) - add_to_ignore(target_turf) - target = null - playsound(src, 'sound/mobs/non-humanoids/floorbot/whistlereset.ogg', 50, TRUE) - return - if(isspaceturf(target_turf)) - //Must be a hull breach or in line mode to continue. - if(!is_hull_breach(target_turf) && !targetdirection) - target = null - return - else if(!isfloorturf(target_turf)) - return - if(isspaceturf(target_turf)) //If we are fixing an area not part of pure space, it is - toggle_magnet() - visible_message(span_notice("[targetdirection ? "[src] begins installing a bridge plating." : "[src] begins to repair the hole."] ")) - mode = BOT_REPAIRING - if(!do_after(src, 5 SECONDS, target = target_turf) && mode == BOT_REPAIRING) - go_idle() - return - - if(!autotile) - target_turf.place_on_top(/turf/open/floor/plating, flags = CHANGETURF_INHERIT_AIR) - go_idle() - return - - if(replacetiles && tilestack) - target_turf.place_on_top(/turf/open/floor/plating, flags = CHANGETURF_INHERIT_AIR) //make sure a hull is actually below the floor tile - tilestack.place_tile(target_turf, src) - if(!tilestack) - speak("Requesting refill of custom floor tiles to continue replacing.") - else - target_turf.place_on_top(/turf/open/floor/plating, flags = CHANGETURF_INHERIT_AIR) //make sure a hull is actually below the floor tile - target_turf.place_on_top(/turf/open/floor/iron, flags = CHANGETURF_INHERIT_AIR) - go_idle() - return - - var/turf/open/floor/floor = target_turf - var/was_replacing = replacetiles - - if(floor.broken || floor.burnt || isplatingturf(floor)) - toggle_magnet() - mode = BOT_REPAIRING - visible_message(span_notice("[src] begins [(floor.broken || floor.burnt) ? "repairing the floor" : "placing a floor tile"].")) - if(!do_after(src, 5 SECONDS, target = floor) && mode == BOT_REPAIRING) - go_idle() - return - else if(replacetiles && tilestack && floor.type != tilestack.turf_type) - toggle_magnet() - mode = BOT_REPAIRING - visible_message(span_notice("[src] begins replacing the floor tiles.")) - if(do_after(src, 5 SECONDS, target = target_turf) && mode == BOT_REPAIRING && tilestack) - go_idle() - return - - var/area/is_this_maints = get_area(floor) - if(was_replacing && tilestack) //turn the tile into plating (if needed), then replace it - floor = floor.make_plating(TRUE) || floor - tilestack.place_tile(floor, src) - if(!tilestack) - speak("Requesting refill of custom floor tiles to continue replacing.") - go_idle() - return - - if(floor.broken || floor.burnt) //repair the tile and reset it to be undamaged (rather than replacing it) - floor.broken = FALSE - floor.burnt = FALSE - floor.update_appearance() - go_idle() - return - - if(istype(is_this_maints, /area/station/maintenance)) //place catwalk if it's plating and we're in maints - floor.place_on_top(/turf/open/floor/catwalk_floor, flags = CHANGETURF_INHERIT_AIR) - go_idle() - return - - //place normal tile if it's plating anywhere else - floor = floor.make_plating(TRUE) || floor - floor.place_on_top(/turf/open/floor/iron, flags = CHANGETURF_INHERIT_AIR) - go_idle() - -/mob/living/simple_animal/bot/floorbot/update_icon_state() - . = ..() - icon_state = "[toolbox_color]floorbot[get_bot_flag(bot_mode_flags, BOT_MODE_ON)]" - -/mob/living/simple_animal/bot/floorbot/explode() - target = null - var/atom/Tsec = drop_location() - - drop_part(toolbox, Tsec) - - new /obj/item/assembly/prox_sensor(Tsec) - - if(tilestack) - tilestack.forceMove(drop_location()) - - new /obj/item/stack/tile/iron/base(Tsec, 1) - return ..() - -/mob/living/simple_animal/bot/floorbot/UnarmedAttack(atom/target, proximity_flag, list/modifiers) - if(!can_unarmed_attack()) - return - - if (!isturf(target)) - return ..() - - if(!(bot_cover_flags & BOT_COVER_EMAGGED) || !isfloorturf(target)) - repair(target) - return - - var/turf/open/floor/floor = target - if(isplatingturf(floor)) - floor.attempt_lattice_replacement() - else - floor.ScrapeAway(flags = CHANGETURF_INHERIT_AIR) - audible_message(span_danger("[src] makes an excited booping sound.")) - -/** - * Checks a given turf to see if another floorbot is there, working as well. - */ -/mob/living/simple_animal/bot/floorbot/proc/check_bot_working(turf/active_turf) - if(isturf(active_turf)) - for(var/mob/living/simple_animal/bot/floorbot/robot in active_turf) - if(robot.mode == BOT_REPAIRING) - return TRUE - return FALSE - -#undef HULL_BREACH -#undef LINE_SPACE_MODE -#undef FIX_TILE -#undef AUTO_TILE -#undef PLACE_TILE -#undef REPLACE_TILE -#undef TILE_EMAG diff --git a/code/modules/mob/living/simple_animal/hostile/mining_mobs/curse_blob.dm b/code/modules/mob/living/simple_animal/hostile/mining_mobs/curse_blob.dm index 03d79c108d60d..f57ea3e058203 100644 --- a/code/modules/mob/living/simple_animal/hostile/mining_mobs/curse_blob.dm +++ b/code/modules/mob/living/simple_animal/hostile/mining_mobs/curse_blob.dm @@ -121,7 +121,7 @@ IGNORE_PROC_IF_NOT_TARGET(attack_animal) /mob/living/simple_animal/hostile/asteroid/curseblob/bullet_act(obj/projectile/Proj) if(Proj.firer != set_target) - return + return BULLET_ACT_BLOCK return ..() /mob/living/simple_animal/hostile/asteroid/curseblob/attacked_by(obj/item/I, mob/living/L) diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm index aae9434191ce3..2b3810e0a50c2 100644 --- a/code/modules/mob/mob.dm +++ b/code/modules/mob/mob.dm @@ -917,9 +917,8 @@ return if(!selected_hand) - selected_hand = (active_hand_index % held_items.len)+1 - - if(istext(selected_hand)) + selected_hand = active_hand_index + else if(istext(selected_hand)) selected_hand = LOWER_TEXT(selected_hand) if(selected_hand == "right" || selected_hand == "r") selected_hand = 2 @@ -928,8 +927,9 @@ if(selected_hand != active_hand_index) swap_hand(selected_hand) - else - mode() + + // _queue_verb requires a client, so when we don't have it (AI controlled mob) we don't use it + client ? mode() : execute_mode() /mob/proc/assess_threat(judgement_criteria, lasercolor = "", datum/callback/weaponcheck=null) //For sec bot threat assessment return 0 diff --git a/code/modules/mod/mod_activation.dm b/code/modules/mod/mod_activation.dm index ee4725075aadc..ecc3eaaedc241 100644 --- a/code/modules/mod/mod_activation.dm +++ b/code/modules/mod/mod_activation.dm @@ -26,7 +26,7 @@ return var/parts_to_check = parts - part if(part.loc == src) - if(!deploy(user, part) || (active && !delayed_seal_part(part))) + if(!deploy(user, part)) return SEND_SIGNAL(src, COMSIG_MOD_DEPLOYED, user) for(var/obj/item/checking_part as anything in parts_to_check) @@ -35,7 +35,7 @@ choose_deploy(user) break else - if((active && !delayed_seal_part(part, silent = TRUE)) || !retract(user, part)) + if(!retract(user, part)) return SEND_SIGNAL(src, COMSIG_MOD_RETRACTED, user) for(var/obj/item/checking_part as anything in parts_to_check) @@ -64,12 +64,7 @@ if(deploy && part.loc == src) if(!deploy(null, part)) continue - if(active && !delayed_seal_part(part)) - retract(null, part) - return else if(!deploy && part.loc != src) - if(active && !delayed_seal_part(part)) - return retract(null, part) if(deploy) SEND_SIGNAL(src, COMSIG_MOD_DEPLOYED, user) @@ -78,7 +73,7 @@ return TRUE /// Deploys a part of the suit onto the user. -/obj/item/mod/control/proc/deploy(mob/user, obj/item/part) +/obj/item/mod/control/proc/deploy(mob/user, obj/item/part, instant = FALSE) var/datum/mod_part/part_datum = get_part_datum(part) if(!wearer) playsound(src, 'sound/machines/scanner/scanbuzz.ogg', 25, TRUE, SILENCED_SOUND_EXTRARANGE) @@ -86,7 +81,7 @@ if(part.loc != src) if(!user) return FALSE - balloon_alert(user, "[part.name] already deployed!") + balloon_alert(user, "already deployed!") playsound(src, 'sound/machines/scanner/scanbuzz.ogg', 25, TRUE, SILENCED_SOUND_EXTRARANGE) if(part_datum.can_overslot) var/obj/item/overslot = wearer.get_item_by_slot(part.slot_flags) @@ -97,14 +92,21 @@ if(wearer.equip_to_slot_if_possible(part, part.slot_flags, qdel_on_fail = FALSE, disable_warning = TRUE)) ADD_TRAIT(part, TRAIT_NODROP, MOD_TRAIT) wearer.update_clothing(slot_flags) - if(!user) + SEND_SIGNAL(src, COMSIG_MOD_PART_DEPLOYED, user, part_datum) + if(user) + wearer.visible_message(span_notice("[wearer]'s [part.name] deploy[part.p_s()] with a mechanical hiss."), + span_notice("[part] deploy[part.p_s()] with a mechanical hiss."), + span_hear("You hear a mechanical hiss.")) + playsound(src, 'sound/vehicles/mecha/mechmove03.ogg', 25, TRUE, SHORT_RANGE_SOUND_EXTRARANGE) + if(!active || part_datum.sealed) return TRUE - wearer.visible_message(span_notice("[wearer]'s [part.name] deploy[part.p_s()] with a mechanical hiss."), - span_notice("[part] deploy[part.p_s()] with a mechanical hiss."), - span_hear("You hear a mechanical hiss.")) - playsound(src, 'sound/vehicles/mecha/mechmove03.ogg', 25, TRUE, SHORT_RANGE_SOUND_EXTRARANGE) - SEND_SIGNAL(src, COMSIG_MOD_PART_DEPLOYED, user, part) - return TRUE + if(instant) + seal_part(part, is_sealed = TRUE) + return TRUE + else if(delayed_seal_part(part)) + return TRUE + balloon_alert(user, "can't seal, retracting!") + retract(user, part, instant = TRUE) else if(part_datum.overslotting) var/obj/item/overslot = part_datum.overslotting @@ -117,14 +119,21 @@ return FALSE /// Retract a part of the suit from the user. -/obj/item/mod/control/proc/retract(mob/user, obj/item/part) +/obj/item/mod/control/proc/retract(mob/user, obj/item/part, instant = FALSE) var/datum/mod_part/part_datum = get_part_datum(part) if(part.loc == src) if(!user) return FALSE - balloon_alert(user, "[part.name] already retracted!") + balloon_alert(user, "already retracted!") playsound(src, 'sound/machines/scanner/scanbuzz.ogg', 25, TRUE, SILENCED_SOUND_EXTRARANGE) return FALSE + if(active && part_datum.sealed) + if(instant) + seal_part(part, is_sealed = FALSE) + else if(!delayed_seal_part(part)) + balloon_alert(user, "can't unseal!") + playsound(src, 'sound/machines/scanner/scanbuzz.ogg', 25, TRUE, SILENCED_SOUND_EXTRARANGE) + return FALSE REMOVE_TRAIT(part, TRAIT_NODROP, MOD_TRAIT) wearer.transferItemToLoc(part, src, force = TRUE) if(part_datum.overslotting) @@ -132,7 +141,7 @@ if(!QDELING(wearer) && !wearer.equip_to_slot_if_possible(overslot, overslot.slot_flags, qdel_on_fail = FALSE, disable_warning = TRUE)) wearer.dropItemToGround(overslot, force = TRUE, silent = TRUE) wearer.update_clothing(slot_flags) - SEND_SIGNAL(src, COMSIG_MOD_PART_RETRACTED, user, part) + SEND_SIGNAL(src, COMSIG_MOD_PART_RETRACTED, user, part_datum) if(!user) return TRUE wearer.visible_message(span_notice("[wearer]'s [part.name] retract[part.p_s()] back into [src] with a mechanical hiss."), @@ -145,7 +154,7 @@ /obj/item/mod/control/proc/toggle_activate(mob/user, force_deactivate = FALSE) if(!wearer) if(!force_deactivate) - balloon_alert(user, "equip suit first!") + balloon_alert(user, "not equipped!") playsound(src, 'sound/machines/scanner/scanbuzz.ogg', 25, TRUE, SILENCED_SOUND_EXTRARANGE) return FALSE if(!force_deactivate && (SEND_SIGNAL(src, COMSIG_MOD_ACTIVATE, user) & MOD_CANCEL_ACTIVATE)) @@ -156,16 +165,16 @@ playsound(src, 'sound/machines/scanner/scanbuzz.ogg', 25, TRUE, SILENCED_SOUND_EXTRARANGE) return FALSE if(!get_charge() && !force_deactivate) - balloon_alert(user, "suit not powered!") + balloon_alert(user, "no power source!") playsound(src, 'sound/machines/scanner/scanbuzz.ogg', 25, TRUE, SILENCED_SOUND_EXTRARANGE) return FALSE if(open && !force_deactivate) - balloon_alert(user, "close the suit panel!") + balloon_alert(user, "panel open!") playsound(src, 'sound/machines/scanner/scanbuzz.ogg', 25, TRUE, SILENCED_SOUND_EXTRARANGE) return FALSE if(activating) if(!force_deactivate) - balloon_alert(user, "suit already [active ? "shutting down" : "starting up"]!") + balloon_alert(user, "already [active ? "shutting down" : "starting up"]!") playsound(src, 'sound/machines/scanner/scanbuzz.ogg', 25, TRUE, SILENCED_SOUND_EXTRARANGE) return FALSE for(var/obj/item/mod/module/module as anything in modules) @@ -221,13 +230,12 @@ SEND_SIGNAL(src, COMSIG_MOD_TOGGLED, user) return TRUE -/obj/item/mod/control/proc/delayed_seal_part(obj/item/clothing/part, silent = FALSE) +/obj/item/mod/control/proc/delayed_seal_part(obj/item/clothing/part) . = FALSE var/datum/mod_part/part_datum = get_part_datum(part) if(do_after(wearer, activation_step_time, wearer, MOD_ACTIVATION_STEP_FLAGS, extra_checks = CALLBACK(src, PROC_REF(get_wearer)), hidden = TRUE)) - if(!silent) - to_chat(wearer, span_notice("[part] [!part_datum.sealed ? part_datum.sealed_message : part_datum.unsealed_message].")) - playsound(src, 'sound/vehicles/mecha/mechmove03.ogg', 25, TRUE, SHORT_RANGE_SOUND_EXTRARANGE) + to_chat(wearer, span_notice("[part] [!part_datum.sealed ? part_datum.sealed_message : part_datum.unsealed_message].")) + playsound(src, 'sound/vehicles/mecha/mechmove03.ogg', 25, TRUE, SHORT_RANGE_SOUND_EXTRARANGE) seal_part(part, is_sealed = !part_datum.sealed) return TRUE @@ -262,6 +270,7 @@ wearer.update_obscured_slots(part.visor_flags_inv) if((part.clothing_flags & (MASKINTERNALS|HEADINTERNALS)) && wearer.invalid_internals()) wearer.cutoff_internals() + SEND_SIGNAL(src, COMSIG_MOD_PART_SEALED, part_datum) if(is_sealed) if (!active) return @@ -308,12 +317,8 @@ /// Quickly deploys all the suit parts and if successful, seals them and turns on the suit. Intended mostly for outfits. /obj/item/mod/control/proc/quick_activation() - for(var/obj/item/part as anything in get_parts()) - deploy(null, part) - for(var/obj/item/part as anything in get_parts()) - if(part.loc == src) - continue - seal_part(part, is_sealed = TRUE) control_activation(is_on = TRUE) + for(var/obj/item/part as anything in get_parts()) + deploy(null, part, instant = TRUE) #undef MOD_ACTIVATION_STEP_FLAGS diff --git a/code/modules/mod/mod_ai.dm b/code/modules/mod/mod_ai.dm index 1336ff1707449..62e9188fddd1a 100644 --- a/code/modules/mod/mod_ai.dm +++ b/code/modules/mod/mod_ai.dm @@ -3,19 +3,19 @@ if(!.) return if(!open) //mod must be open - balloon_alert(user, "suit must be open to transfer!") + balloon_alert(user, "panel closed!") return switch(interaction) if(AI_TRANS_TO_CARD) if(!ai_assistant) - balloon_alert(user, "no ai in suit!") + balloon_alert(user, "no ai in unit!") return balloon_alert(user, "transferring to card...") if(!do_after(user, 5 SECONDS, target = src)) balloon_alert(user, "interrupted!") return if(!ai_assistant) - balloon_alert(user, "no ai in suit!") + balloon_alert(user, "no ai in unit!") return balloon_alert(user, "ai transferred to card") ai_exit_mod(card) @@ -33,13 +33,13 @@ if(intAI.stat || !intAI.client) balloon_alert(user, "ai unresponsive!") return - balloon_alert(user, "transferring to suit...") + balloon_alert(user, "transferring to unit...") if(!do_after(user, 5 SECONDS, target = src)) balloon_alert(user, "interrupted!") return if(ai_assistant) return - balloon_alert(user, "ai transferred to suit") + balloon_alert(user, "ai transferred to unit") ai_enter_mod(intAI) card.AI = null @@ -74,14 +74,14 @@ if (isnull(card.pai?.mind)) balloon_alert(user, "pAI unresponsive!") return FALSE - balloon_alert(user, "transferring to suit...") + balloon_alert(user, "transferring to unit...") if (!do_after(user, 5 SECONDS, target = src)) balloon_alert(user, "interrupted!") return FALSE if (!user.transferItemToLoc(card, src)) balloon_alert(user, "transfer failed!") return FALSE - balloon_alert(user, "pAI transferred to suit") + balloon_alert(user, "pAI transferred to unit") var/mob/living/silicon/pai/pai_assistant = card.pai pai_assistant.can_transmit = TRUE pai_assistant.can_receive = TRUE @@ -99,14 +99,14 @@ return FALSE if (!forced) if (!open) - balloon_alert(user, "suit panel closed!") + balloon_alert(user, "panel closed!") return FALSE balloon_alert(user, "uninstalling card...") if (!do_after(user, 5 SECONDS, target = src)) balloon_alert(user, "interrupted!") return FALSE - balloon_alert(user, "pAI removed from suit") + balloon_alert(user, "pAI removed") var/mob/living/silicon/pai/pai_helper = ai_assistant pai_helper.can_holo = TRUE pai_helper.card.forceMove(get_turf(src)) @@ -115,7 +115,7 @@ /// Called when a new ai assistant is inserted /obj/item/mod/control/proc/on_gained_assistant(mob/living/silicon/new_helper) ai_assistant = new_helper - balloon_alert(new_helper, "transferred to a suit") + balloon_alert(new_helper, "transferred to a mod unit") for(var/datum/action/action as anything in actions) action.Grant(new_helper) @@ -134,7 +134,10 @@ #define AI_FALL_TIME (1 SECONDS) /obj/item/mod/control/relaymove(mob/user, direction) - if((!active && wearer) || get_charge() < CHARGE_PER_STEP || user != ai_assistant || !COOLDOWN_FINISHED(src, cooldown_mod_move) || (wearer?.pulledby?.grab_state > GRAB_PASSIVE)) + if((!active && wearer) || get_charge() < CHARGE_PER_STEP || user != ai_assistant || !COOLDOWN_FINISHED(src, cooldown_mod_move) || (wearer?.pulledby?.grab_state > GRAB_PASSIVE)) + return FALSE + var/datum/mod_part/legs_to_move = get_part_datum_from_slot(ITEM_SLOT_FEET) + if(wearer && (!legs_to_move || !legs_to_move.sealed)) return FALSE var/timemodifier = MOVE_DELAY * (ISDIAGONALDIR(direction) ? sqrt(2) : 1) * (wearer ? WEARER_DELAY : LONE_DELAY) if(wearer && !wearer.Process_Spacemove(direction)) @@ -147,7 +150,7 @@ if(ismovable(wearer?.loc)) return wearer.loc.relaymove(wearer, direction) else if(wearer) - ADD_TRAIT(wearer, TRAIT_FORCED_STANDING, MOD_TRAIT) + ADD_TRAIT(wearer, TRAIT_FORCED_STANDING, REF(src)) addtimer(CALLBACK(src, PROC_REF(ai_fall)), AI_FALL_TIME, TIMER_UNIQUE | TIMER_OVERRIDE) var/atom/movable/mover = wearer || src return mover.try_step_multiz(direction) @@ -160,7 +163,7 @@ /obj/item/mod/control/proc/ai_fall() if(!wearer) return - REMOVE_TRAIT(wearer, TRAIT_FORCED_STANDING, MOD_TRAIT) + REMOVE_TRAIT(wearer, TRAIT_FORCED_STANDING, REF(src)) /obj/item/mod/ai_minicard name = "AI mini-card" diff --git a/code/modules/mod/mod_construction.dm b/code/modules/mod/mod_construction.dm index 16ce70df94563..3581c04e606a9 100644 --- a/code/modules/mod/mod_construction.dm +++ b/code/modules/mod/mod_construction.dm @@ -162,7 +162,7 @@ if(!istype(part, /obj/item/mod/core)) return if(!user.transferItemToLoc(part, src)) - balloon_alert(user, "core stuck to your hand!") + balloon_alert(user, "it's stuck!") return playsound(src, 'sound/machines/click.ogg', 30, TRUE) balloon_alert(user, "core inserted") @@ -181,7 +181,7 @@ if(SCREWED_CORE_STEP) if(istype(part, /obj/item/mod/construction/helmet)) //Construct if(!user.transferItemToLoc(part, src)) - balloon_alert(user, "helmet stuck to your hand!") + balloon_alert(user, "it's stuck!") return playsound(src, 'sound/machines/click.ogg', 30, TRUE) balloon_alert(user, "helmet added") @@ -194,7 +194,7 @@ if(HELMET_STEP) if(istype(part, /obj/item/mod/construction/chestplate)) //Construct if(!user.transferItemToLoc(part, src)) - balloon_alert(user, "chestplate stuck to your hand!") + balloon_alert(user, "it's stuck!") return playsound(src, 'sound/machines/click.ogg', 30, TRUE) balloon_alert(user, "chestplate added") @@ -209,7 +209,7 @@ if(CHESTPLATE_STEP) if(istype(part, /obj/item/mod/construction/gauntlets)) //Construct if(!user.transferItemToLoc(part, src)) - balloon_alert(user, "gauntlets stuck to your hand!") + balloon_alert(user, "it's stuck!") return playsound(src, 'sound/machines/click.ogg', 30, TRUE) balloon_alert(user, "gauntlets added") @@ -224,10 +224,10 @@ if(GAUNTLETS_STEP) if(istype(part, /obj/item/mod/construction/boots)) //Construct if(!user.transferItemToLoc(part, src)) - balloon_alert(user, "boots added") + balloon_alert(user, "it's stuck!") return playsound(src, 'sound/machines/click.ogg', 30, TRUE) - balloon_alert(user, "fit [part.name]") + balloon_alert(user, "boots added") boots = part step = BOOTS_STEP else if(part.tool_behaviour == TOOL_CROWBAR) //Deconstruct @@ -260,13 +260,14 @@ if(istype(part, /obj/item/mod/construction/plating)) //Construct var/obj/item/mod/construction/plating/external_plating = part if(!user.transferItemToLoc(part, src)) + balloon_alert(user, "it's stuck!") return playsound(src, 'sound/machines/click.ogg', 30, TRUE) var/obj/item/mod = new /obj/item/mod/control(drop_location(), external_plating.theme, null, core) core = null qdel(src) user.put_in_hands(mod) - mod.balloon_alert(user, "suit finished") + mod.balloon_alert(user, "unit finished") else if(part.tool_behaviour == TOOL_SCREWDRIVER) //Construct if(part.use_tool(src, user, 0, volume=30)) balloon_alert(user, "assembly unscrewed") diff --git a/code/modules/mod/mod_control.dm b/code/modules/mod/mod_control.dm index 0f521e40691f4..436c9e7c20d88 100644 --- a/code/modules/mod/mod_control.dm +++ b/code/modules/mod/mod_control.dm @@ -97,7 +97,6 @@ theme.set_up_parts(src, new_skin) for(var/obj/item/part as anything in get_parts()) RegisterSignal(part, COMSIG_ATOM_DESTRUCTION, PROC_REF(on_part_destruction)) - RegisterSignal(part, COMSIG_QDELETING, PROC_REF(on_part_deletion)) set_wires(new /datum/wires/mod(src)) if(length(req_access)) locked = TRUE @@ -118,14 +117,19 @@ QDEL_NULL(core) QDEL_NULL(mod_link) for(var/datum/mod_part/part_datum as anything in get_part_datums(all = TRUE)) + var/obj/item/part_item = part_datum.part_item part_datum.part_item = null part_datum.overslotting = null + mod_parts -= part_datum + if(!QDELING(part_item)) + qdel(part_item) return ..() /obj/item/mod/control/atom_destruction(damage_flag) + var/atom/visible_atom = wearer || src if(wearer) - wearer.visible_message(span_danger("[src] fall[p_s()] apart, completely destroyed!"), vision_distance = COMBAT_MESSAGE_RANGE) clean_up() + visible_atom.visible_message(span_bolddanger("[src] fall[p_s()] apart, completely destroyed!"), vision_distance = COMBAT_MESSAGE_RANGE) for(var/obj/item/mod/module/module as anything in modules) uninstall(module) if(ai_assistant) @@ -220,12 +224,12 @@ if(user != wearer) return ..() if(active) - balloon_alert(wearer, "deactivate the suit first!") + balloon_alert(wearer, "unit active!") playsound(src, 'sound/machines/scanner/scanbuzz.ogg', 25, FALSE, SILENCED_SOUND_EXTRARANGE) return for(var/obj/item/part as anything in get_parts()) if(part.loc != src) - balloon_alert(user, "retract parts first!") + balloon_alert(user, "parts extended!") playsound(src, 'sound/machines/scanner/scanbuzz.ogg', 25, FALSE, SILENCED_SOUND_EXTRARANGE) return FALSE @@ -233,12 +237,12 @@ if(user != wearer || !istype(over_object, /atom/movable/screen/inventory/hand)) return if(active) - balloon_alert(wearer, "deactivate the suit first!") + balloon_alert(wearer, "unit active!") playsound(src, 'sound/machines/scanner/scanbuzz.ogg', 25, FALSE, SILENCED_SOUND_EXTRARANGE) return for(var/obj/item/part as anything in get_parts()) if(part.loc != src) - balloon_alert(wearer, "retract parts first!") + balloon_alert(wearer, "parts extended!") playsound(src, 'sound/machines/scanner/scanbuzz.ogg', 25, FALSE, SILENCED_SOUND_EXTRARANGE) return if(!wearer.incapacitated) @@ -266,14 +270,15 @@ /obj/item/mod/control/screwdriver_act(mob/living/user, obj/item/screwdriver) if(active || activating || ai_controller) - balloon_alert(user, "deactivate suit first!") + balloon_alert(user, "unit active!") playsound(src, 'sound/machines/scanner/scanbuzz.ogg', 25, TRUE, SILENCED_SOUND_EXTRARANGE) return ITEM_INTERACT_BLOCKING balloon_alert(user, "[open ? "closing" : "opening"] cover...") screwdriver.play_tool_sound(src, 100) if(screwdriver.use_tool(src, user, 1 SECONDS)) if(active || activating) - balloon_alert(user, "deactivate suit first!") + balloon_alert(user, "unit active!") + return ITEM_INTERACT_SUCCESS screwdriver.play_tool_sound(src, 100) balloon_alert(user, "cover [open ? "closed" : "opened"]") open = !open @@ -283,7 +288,7 @@ /obj/item/mod/control/crowbar_act(mob/living/user, obj/item/crowbar) if(!open) - balloon_alert(user, "open the cover first!") + balloon_alert(user, "cover closed!") playsound(src, 'sound/machines/scanner/scanbuzz.ogg', 25, TRUE, SILENCED_SOUND_EXTRARANGE) return ITEM_INTERACT_BLOCKING if(!allowed(user)) @@ -315,14 +320,14 @@ /obj/item/mod/control/tool_act(mob/living/user, obj/item/tool, list/modifiers) if(istype(tool, /obj/item/pai_card)) if(!open) - balloon_alert(user, "open the cover first!") + balloon_alert(user, "cover closed!") return NONE // shoves the card in the storage anyways insert_pai(user, tool) return ITEM_INTERACT_SUCCESS if(istype(tool, /obj/item/mod/paint)) var/obj/item/mod/paint/paint_kit = tool if(active || activating) - balloon_alert(user, "suit is active!") + balloon_alert(user, "unit active!") return ITEM_INTERACT_BLOCKING if(LAZYACCESS(modifiers, RIGHT_CLICK)) // Right click if(paint_kit.editing_mod == src) @@ -341,7 +346,7 @@ return ITEM_INTERACT_SUCCESS if(istype(tool, /obj/item/mod/module)) if(!open) - balloon_alert(user, "open the cover first!") + balloon_alert(user, "cover closed!") playsound(src, 'sound/machines/scanner/scanbuzz.ogg', 25, TRUE, SILENCED_SOUND_EXTRARANGE) return ITEM_INTERACT_BLOCKING install(tool, user) @@ -349,11 +354,11 @@ return ITEM_INTERACT_SUCCESS if(istype(tool, /obj/item/mod/core)) if(!open) - balloon_alert(user, "open the cover first!") + balloon_alert(user, "cover closed!") playsound(src, 'sound/machines/scanner/scanbuzz.ogg', 25, TRUE, SILENCED_SOUND_EXTRARANGE) return ITEM_INTERACT_BLOCKING if(core) - balloon_alert(user, "core already installed!") + balloon_alert(user, "already has core!") playsound(src, 'sound/machines/scanner/scanbuzz.ogg', 25, TRUE, SILENCED_SOUND_EXTRARANGE) return ITEM_INTERACT_BLOCKING var/obj/item/mod/core/attacking_core = tool @@ -385,7 +390,7 @@ /obj/item/mod/control/emag_act(mob/user, obj/item/card/emag/emag_card) locked = !locked - balloon_alert(user, "suit access [locked ? "locked" : "unlocked"]") + balloon_alert(user, "access [locked ? "locked" : "unlocked"]") return TRUE /obj/item/mod/control/emp_act(severity) @@ -445,12 +450,11 @@ CRASH("get_part_datum called with incorrect item [part] passed.") /obj/item/mod/control/proc/get_part_from_slot(slot) - slot = "[slot]" - for(var/part_slot in mod_parts) - if(slot != part_slot) - continue - var/datum/mod_part/part = mod_parts[part_slot] - return part.part_item + var/datum/mod_part/part = mod_parts["[slot]"] + return part?.part_item + +/obj/item/mod/control/proc/get_part_datum_from_slot(slot) + return mod_parts["[slot]"] /obj/item/mod/control/proc/set_wearer(mob/living/carbon/human/user) if(wearer == user) @@ -511,7 +515,7 @@ for(var/obj/item/part as anything in get_parts()) seal_part(part, is_sealed = FALSE) for(var/obj/item/part as anything in get_parts()) - retract(null, part) + INVOKE_ASYNC(src, PROC_REF(retract), wearer, part, /* instant = */ TRUE) // async to appease spaceman DMM because the branch we don't run has a do_after if(active) control_activation(is_on = FALSE) mod_link?.end_call() @@ -579,24 +583,24 @@ for(var/obj/item/mod/module/old_module as anything in modules) if(is_type_in_list(new_module, old_module.incompatible_modules) || is_type_in_list(old_module, new_module.incompatible_modules)) if(user) - balloon_alert(user, "[new_module] incompatible with [old_module]!") + balloon_alert(user, "incompatible with [old_module]!") playsound(src, 'sound/machines/scanner/scanbuzz.ogg', 25, TRUE, SILENCED_SOUND_EXTRARANGE) return var/complexity_with_module = complexity complexity_with_module += new_module.complexity if(complexity_with_module > complexity_max) if(user) - balloon_alert(user, "[new_module] would make [src] too complex!") + balloon_alert(user, "above complexity max!") playsound(src, 'sound/machines/scanner/scanbuzz.ogg', 25, TRUE, SILENCED_SOUND_EXTRARANGE) return if(!new_module.has_required_parts(mod_parts)) if(user) - balloon_alert(user, "[new_module] incompatible with [src]'s parts!") + balloon_alert(user, "lacking required parts!") playsound(src, 'sound/machines/scanner/scanbuzz.ogg', 25, TRUE, SILENCED_SOUND_EXTRARANGE) return if(!new_module.can_install(src)) if(user) - balloon_alert(user, "[new_module] cannot be installed into [src]!") + balloon_alert(user, "can't install!") playsound(src, 'sound/machines/scanner/scanbuzz.ogg', 25, TRUE, SILENCED_SOUND_EXTRARANGE) return new_module.forceMove(src) @@ -661,6 +665,12 @@ /obj/item/mod/control/proc/check_charge(amount) return core?.check_charge(amount) || FALSE +/obj/item/mod/control/proc/get_chargebar_color() + return core?.get_chargebar_color() || "transparent" + +/obj/item/mod/control/proc/get_chargebar_string() + return core?.get_chargebar_string() || "No Core Detected" + /** * Updates the wearer's hud according to the current state of the MODsuit */ @@ -706,6 +716,9 @@ uninstall(part) return if(part in get_parts()) + if(QDELING(part) && !QDELING(src)) + qdel(src) + return var/datum/mod_part/part_datum = get_part_datum(part) if(part_datum.sealed) seal_part(part, is_sealed = FALSE) @@ -714,7 +727,7 @@ if(!wearer) part.forceMove(src) return - retract(wearer, part) + INVOKE_ASYNC(src, PROC_REF(retract), wearer, part, /* instant = */ TRUE) // async to appease spaceman DMM because the branch we don't run has a do_after /obj/item/mod/control/proc/on_part_destruction(obj/item/part, damage_flag) SIGNAL_HANDLER @@ -723,14 +736,6 @@ return atom_destruction(damage_flag) -/obj/item/mod/control/proc/on_part_deletion(obj/item/part) - SIGNAL_HANDLER - - if(QDELING(src)) - return - part.moveToNullspace() - qdel(src) - /obj/item/mod/control/proc/on_overslot_exit(obj/item/part, atom/movable/overslot, direction) SIGNAL_HANDLER diff --git a/code/modules/mod/mod_core.dm b/code/modules/mod/mod_core.dm index 79a8eff5e290a..01e0902b6b03c 100644 --- a/code/modules/mod/mod_core.dm +++ b/code/modules/mod/mod_core.dm @@ -25,30 +25,45 @@ mod.update_charge_alert() mod = null +/// Returns the item responsible for charging the suit, like a power cell, an ethereal's stomach, the core itself, etc. /obj/item/mod/core/proc/charge_source() return +/// Returns the amount of charge in the core. /obj/item/mod/core/proc/charge_amount() return 0 +/// Returns the max amount of charge stored in the core. /obj/item/mod/core/proc/max_charge_amount() return 1 +/// Adds a set amount of charge to the core. /obj/item/mod/core/proc/add_charge(amount) return FALSE +/// Subtracts a set amount of charge from the core. /obj/item/mod/core/proc/subtract_charge(amount) return FALSE +/// Checks if there's enough charge in the core to use an amount of energy. /obj/item/mod/core/proc/check_charge(amount) return FALSE -/** - * Gets what icon state to display on the HUD for the charge level of this core - */ +/// Returns what icon state to display on the HUD for the charge level of this core /obj/item/mod/core/proc/get_charge_icon_state() return "0" +/// Gets what the UI should use for the charge bar color. +/obj/item/mod/core/proc/get_chargebar_color() + return "bad" + +/// Gets what the UI should use for the charge bar text. +/obj/item/mod/core/proc/get_chargebar_string() + var/charge_amount = charge_amount() + var/max_charge_amount = max_charge_amount() + return "[display_energy(charge_amount)] of [display_energy(max_charge_amount())] \ + ([round((100 * charge_amount) / max_charge_amount, 1)]%)" + /obj/item/mod/core/infinite name = "MOD infinite core" icon_state = "mod-core-infinite" @@ -76,6 +91,12 @@ /obj/item/mod/core/infinite/get_charge_icon_state() return "high" +/obj/item/mod/core/infinite/get_chargebar_color() + return "teal" + +/obj/item/mod/core/infinite/get_chargebar_string() + return "Infinite" + /obj/item/mod/core/standard name = "MOD standard core" icon_state = "mod-core-standard" @@ -163,6 +184,22 @@ return "empty" +/obj/item/mod/core/standard/get_chargebar_color() + if(isnull(charge_source())) + return "transparent" + switch(round(charge_amount() / max_charge_amount(), 0.01)) + if(-INFINITY to 0.33) + return "bad" + if(0.33 to 0.66) + return "average" + if(0.66 to INFINITY) + return "good" + +/obj/item/mod/core/standard/get_chargebar_string() + if(isnull(charge_source())) + return "Power Cell Missing" + return ..() + /obj/item/mod/core/standard/proc/install_cell(new_cell) cell = new_cell cell.forceMove(src) @@ -222,11 +259,11 @@ if(!istype(attacking_item, /obj/item/stock_parts/power_store/cell)) return FALSE if(!mod.open) - mod.balloon_alert(user, "open the cover first!") + mod.balloon_alert(user, "cover closed!") playsound(mod, 'sound/machines/scanner/scanbuzz.ogg', 25, TRUE, SILENCED_SOUND_EXTRARANGE) return FALSE if(cell) - mod.balloon_alert(user, "cell already installed!") + mod.balloon_alert(user, "already has cell!") playsound(mod, 'sound/machines/scanner/scanbuzz.ogg', 25, TRUE, SILENCED_SOUND_EXTRARANGE) return FALSE install_cell(attacking_item) @@ -260,7 +297,9 @@ name = "MOD ethereal core" icon_state = "mod-core-ethereal" desc = "A reverse engineered core of a Modular Outerwear Device. Using natural liquid electricity from Ethereals, \ - preventing the need to use external sources to convert electric charge." + preventing the need to use external sources to convert electric charge. As the suits are naturally charged by \ + liquid electricity, this core makes it much more efficient, running all soft, hard, and wetware with several \ + times less energy usage." /// A modifier to all charge we use, ethereals don't need to spend as much energy as normal suits. var/charge_modifier = 0.1 @@ -279,22 +318,41 @@ /obj/item/mod/core/ethereal/add_charge(amount) var/obj/item/organ/stomach/ethereal/charge_source = charge_source() - if(!charge_source) + if(isnull(charge_source)) return FALSE - charge_source.adjust_charge(amount*charge_modifier) + charge_source.adjust_charge(amount * charge_modifier) return TRUE /obj/item/mod/core/ethereal/subtract_charge(amount) var/obj/item/organ/stomach/ethereal/charge_source = charge_source() - if(!charge_source) + if(isnull(charge_source)) return FALSE - return -charge_source.adjust_charge(-amount*charge_modifier) + return -charge_source.adjust_charge(-amount * charge_modifier) /obj/item/mod/core/ethereal/check_charge(amount) - return charge_amount() >= amount*charge_modifier + return charge_amount() >= amount * charge_modifier /obj/item/mod/core/ethereal/get_charge_icon_state() - return charge_source() ? "0" : "missing" + return isnull(charge_source()) ? "missing" : "0" + +/obj/item/mod/core/ethereal/get_chargebar_color() + if(isnull(charge_source())) + return "transparent" + switch(charge_amount()) + if(-INFINITY to ETHEREAL_CHARGE_LOWPOWER) + return "bad" + if(ETHEREAL_CHARGE_LOWPOWER to ETHEREAL_CHARGE_NORMAL) + return "average" + if(ETHEREAL_CHARGE_NORMAL to ETHEREAL_CHARGE_FULL) + return "good" + if(ETHEREAL_CHARGE_FULL to INFINITY) + return "teal" + +/obj/item/mod/core/ethereal/get_chargebar_string() + var/obj/item/organ/stomach/ethereal/charge_source = charge_source() + if(isnull(charge_source()) || isnull(charge_source.cell)) + return "Biological Battery Missing" + return ..() #define PLASMA_CORE_ORE_CHARGE (1.5 * STANDARD_CELL_CHARGE) #define PLASMA_CORE_SHEET_CHARGE (2 * STANDARD_CELL_CHARGE) @@ -355,6 +413,13 @@ return "empty" +/obj/item/mod/core/plasma/get_chargebar_color() + switch(round(charge_amount() / max_charge_amount(), 0.01)) + if(-INFINITY to 0.33) + return "bad" + if(0.33 to INFINITY) + return "purple" + /obj/item/mod/core/plasma/proc/on_mod_interaction(datum/source, mob/living/user, obj/item/thing) SIGNAL_HANDLER diff --git a/code/modules/mod/mod_link.dm b/code/modules/mod/mod_link.dm index e7a5a20d9f370..a93ebec8b570c 100644 --- a/code/modules/mod/mod_link.dm +++ b/code/modules/mod/mod_link.dm @@ -213,7 +213,7 @@ if(!user.transferItemToLoc(attacked_by, src)) return cell = attacked_by - balloon_alert(user, "installed [cell.name]") + balloon_alert(user, "cell installed") /obj/item/clothing/neck/link_scryer/update_name(updates) . = ..() @@ -227,7 +227,7 @@ /obj/item/clothing/neck/link_scryer/attack_hand_secondary(mob/user, list/modifiers) if(!cell) return SECONDARY_ATTACK_CONTINUE_CHAIN - balloon_alert(user, "removed [cell.name]") + balloon_alert(user, "cell removed") user.put_in_hands(cell) return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN @@ -409,7 +409,7 @@ if(!link_user) return if(HAS_TRAIT(link_user, TRAIT_IN_CALL)) - holder.balloon_alert(user, "user already in call!") + holder.balloon_alert(user, "already calling!") return var/mob/living/link_target = called.get_user_callback.Invoke() if(!link_target) @@ -511,6 +511,7 @@ desc = "Someone is calling you! Left-click this to accept the call. Right-click to deny it." icon_state = "called" timeout = 10 SECONDS + clickable_glow = TRUE var/end_message = "call timed out!" /// A weak reference to the MODlink that is calling. var/datum/weakref/caller_ref diff --git a/code/modules/mod/mod_paint.dm b/code/modules/mod/mod_paint.dm index e3e42e55f613c..2f658e9df2470 100644 --- a/code/modules/mod/mod_paint.dm +++ b/code/modules/mod/mod_paint.dm @@ -153,10 +153,10 @@ return NONE var/obj/item/mod/control/mod = attacked_atom if(mod.active || mod.activating) - balloon_alert(user, "suit is active!") + balloon_alert(user, "unit active!") return ITEM_INTERACT_BLOCKING if(!(skin in mod.theme.variants)) - balloon_alert(user, "incompatible theme!") + balloon_alert(user, "wrong theme for skin!") return ITEM_INTERACT_BLOCKING mod.theme.set_skin(mod, skin) balloon_alert(user, "skin applied") diff --git a/code/modules/mod/mod_ui.dm b/code/modules/mod/mod_ui.dm index 2a8ccf7b4bf94..9a8e77f7e8e76 100644 --- a/code/modules/mod/mod_ui.dm +++ b/code/modules/mod/mod_ui.dm @@ -9,8 +9,10 @@ // Suit information var/suit_status = list( "core_name" = core?.name, - "cell_charge_current" = get_charge(), - "cell_charge_max" = get_max_charge(), + "charge_current" = get_charge(), + "charge_max" = get_max_charge(), + "chargebar_color" = get_chargebar_color(), + "chargebar_string" = get_chargebar_string(), "active" = active, "ai_name" = ai_assistant?.name, "has_pai" = ispAI(ai_assistant), @@ -56,23 +58,25 @@ "configuration_data" = module.get_configuration(user), )) data["module_custom_status"] = module_custom_status - data["module_info"] = module_info - return data - -/obj/item/mod/control/ui_static_data(mob/user) - var/data = list() - data["ui_theme"] = ui_theme data["control"] = name - data["complexity_max"] = complexity_max + data["module_info"] = module_info var/part_info = list() for(var/obj/item/part as anything in get_parts()) part_info += list(list( "slot" = english_list(parse_slot_flags(part.slot_flags)), "name" = part.name, + "deployed" = part.loc != src, + "ref" = REF(part), )) data["parts"] = part_info return data +/obj/item/mod/control/ui_static_data(mob/user) + var/data = list() + data["ui_theme"] = ui_theme + data["complexity_max"] = complexity_max + return data + /obj/item/mod/control/ui_state(mob/user) if(user == ai_assistant) return GLOB.contained_state @@ -89,7 +93,7 @@ if("lock") if(!locked || allowed(ui.user)) locked = !locked - balloon_alert(ui.user, "[locked ? "locked" : "unlocked"]!") + balloon_alert(ui.user, "[locked ? "locked" : "unlocked"]") else balloon_alert(ui.user, "access insufficent!") playsound(src, 'sound/machines/scanner/scanbuzz.ogg', 25, TRUE, SILENCED_SOUND_EXTRARANGE) @@ -115,6 +119,14 @@ if(!module) return module.pin(ui.user) + if("deploy") + var/obj/item/mod_part = locate(params["ref"]) in get_parts() + if(!mod_part) + return + if(mod_part.loc == src) + deploy(ui.user, mod_part) + else + retract(ui.user, mod_part) if("eject_pai") if (!ishuman(ui.user)) return diff --git a/code/modules/mod/modules/_module.dm b/code/modules/mod/modules/_module.dm index 28a588609a783..565919c07ecd5 100644 --- a/code/modules/mod/modules/_module.dm +++ b/code/modules/mod/modules/_module.dm @@ -300,7 +300,7 @@ /obj/item/mod/module/proc/add_ui_data() return list() -/// Creates a list of configuring options for this module +/// Creates a list of configuring options for this module, possible configs include number, bool, color, list, button. /obj/item/mod/module/proc/get_configuration(mob/user) return list() @@ -418,7 +418,7 @@ /obj/item/mod/module/anomaly_locked name = "MOD anomaly locked module" desc = "A form of a module, locked behind an anomalous core to function." - incompatible_modules = list(/obj/item/mod/module/anomaly_locked) + incompatible_modules = list() /// The core item the module runs off. var/obj/item/assembly/signaler/anomaly/core /// Accepted types of anomaly cores. @@ -491,7 +491,7 @@ balloon_alert(user, "no core!") return if(!core_removable) - balloon_alert(user, "can't remove core!") + balloon_alert(user, "already has core!") return balloon_alert(user, "removing core...") if(!do_after(user, 3 SECONDS, target = src)) diff --git a/code/modules/mod/modules/module_kinesis.dm b/code/modules/mod/modules/module_kinesis.dm index 3c9ae3310b755..733e5ab40d97b 100644 --- a/code/modules/mod/modules/module_kinesis.dm +++ b/code/modules/mod/modules/module_kinesis.dm @@ -17,7 +17,7 @@ accepted_anomalies = list(/obj/item/assembly/signaler/anomaly/grav) required_slots = list(ITEM_SLOT_GLOVES) /// Range of the knesis grab. - var/grab_range = 5 + var/grab_range = 8 /// Time between us hitting objects with kinesis. var/hit_cooldown_time = 1 SECONDS /// Stat required for us to grab a mob. diff --git a/code/modules/mod/modules/module_pathfinder.dm b/code/modules/mod/modules/module_pathfinder.dm index f0a92e3a05153..487844bc2a04f 100644 --- a/code/modules/mod/modules/module_pathfinder.dm +++ b/code/modules/mod/modules/module_pathfinder.dm @@ -117,19 +117,19 @@ /obj/item/implant/mod/proc/recall() if(!module?.mod) - balloon_alert(imp_in, "no connected suit!") + balloon_alert(imp_in, "no connected unit!") return FALSE if(module.mod.open) - balloon_alert(imp_in, "suit is open!") + balloon_alert(imp_in, "cover open!") return FALSE if(module.mod.ai_controller) - balloon_alert(imp_in, "already in transit!") + balloon_alert(imp_in, "already moving!") return FALSE if(ismob(get_atom_on_turf(module.mod))) balloon_alert(imp_in, "already on someone!") return FALSE if(module.z != z || get_dist(imp_in, module.mod) > MOD_AI_RANGE) - balloon_alert(imp_in, "too far away!") + balloon_alert(imp_in, "too far!") return FALSE var/datum/ai_controller/mod_ai = new /datum/ai_controller/mod(module.mod) module.mod.ai_controller = mod_ai diff --git a/code/modules/mod/modules/modules_antag.dm b/code/modules/mod/modules/modules_antag.dm index 0401dbfdbe969..ec550f3cfde3a 100644 --- a/code/modules/mod/modules/modules_antag.dm +++ b/code/modules/mod/modules/modules_antag.dm @@ -52,9 +52,10 @@ playsound(src, 'sound/vehicles/mecha/mechmove03.ogg', 25, TRUE, SHORT_RANGE_SOUND_EXTRARANGE) balloon_alert(mod.wearer, "armor boosted, EVA lost") actual_speed_added = max(0, min(mod.slowdown_active, speed_added)) - var/obj/item/clothing/head_cover = mod.get_part_from_slot(ITEM_SLOT_HEAD) || mod.get_part_from_slot(ITEM_SLOT_MASK) || mod.get_part_from_slot(ITEM_SLOT_EYES) - if(istype(head_cover)) - ADD_TRAIT(mod.wearer, TRAIT_HEAD_INJURY_BLOCKED, MOD_TRAIT) + var/datum/mod_part/head_cover = mod.get_part_datum_from_slot(ITEM_SLOT_HEAD) || mod.get_part_datum_from_slot(ITEM_SLOT_MASK) || mod.get_part_datum_from_slot(ITEM_SLOT_EYES) + if(head_cover) + RegisterSignal(mod, COMSIG_MOD_PART_SEALED, PROC_REF(seal_helmet)) + seal_helmet(mod, head_cover) var/list/mod_parts = mod.get_parts(all = TRUE) for(var/obj/item/part as anything in mod.get_parts(all = TRUE)) part.set_armor(part.get_armor().add_other_armor(armor_mod)) @@ -71,9 +72,10 @@ if(!deleting) playsound(src, 'sound/vehicles/mecha/mechmove03.ogg', 25, TRUE, SHORT_RANGE_SOUND_EXTRARANGE) balloon_alert(mod.wearer, "armor retracts, EVA ready") - var/obj/item/clothing/head_cover = mod.get_part_from_slot(ITEM_SLOT_HEAD) || mod.get_part_from_slot(ITEM_SLOT_MASK) || mod.get_part_from_slot(ITEM_SLOT_EYES) - if(istype(head_cover)) - REMOVE_TRAIT(mod.wearer, TRAIT_HEAD_INJURY_BLOCKED, MOD_TRAIT) + var/datum/mod_part/head_cover = mod.get_part_datum_from_slot(ITEM_SLOT_HEAD) || mod.get_part_datum_from_slot(ITEM_SLOT_MASK) || mod.get_part_datum_from_slot(ITEM_SLOT_EYES) + if(head_cover) + UnregisterSignal(mod, COMSIG_MOD_PART_SEALED) + REMOVE_TRAIT(mod.wearer, TRAIT_HEAD_INJURY_BLOCKED, REF(src)) var/list/mod_parts = mod.get_parts(all = TRUE) for(var/obj/item/part as anything in mod.get_parts(all = TRUE)) part.set_armor(part.get_armor().subtract_other_armor(armor_mod)) @@ -91,6 +93,15 @@ overlay_state_active = "[initial(overlay_state_active)]-[mod.skin]" return ..() +/obj/item/mod/module/armor_booster/proc/seal_helmet(datum/source, datum/mod_part/part) + var/datum/mod_part/head_cover = mod.get_part_datum_from_slot(ITEM_SLOT_HEAD) || mod.get_part_datum_from_slot(ITEM_SLOT_MASK) || mod.get_part_datum_from_slot(ITEM_SLOT_EYES) + if(part != head_cover) + return + if(part.sealed) + ADD_TRAIT(mod.wearer, TRAIT_HEAD_INJURY_BLOCKED, REF(src)) + else + REMOVE_TRAIT(mod.wearer, TRAIT_HEAD_INJURY_BLOCKED, REF(src)) + ///Energy Shield - Gives you a rechargeable energy shield that nullifies attacks. /obj/item/mod/module/energy_shield name = "MOD energy shield module" @@ -184,10 +195,10 @@ required_slots = list(ITEM_SLOT_BACK) /obj/item/mod/module/anti_magic/on_part_activation() - mod.wearer.add_traits(list(TRAIT_ANTIMAGIC, TRAIT_HOLY), MOD_TRAIT) + mod.wearer.add_traits(list(TRAIT_ANTIMAGIC, TRAIT_HOLY), REF(src)) /obj/item/mod/module/anti_magic/on_part_deactivation(deleting = FALSE) - mod.wearer.remove_traits(list(TRAIT_ANTIMAGIC, TRAIT_HOLY), MOD_TRAIT) + mod.wearer.remove_traits(list(TRAIT_ANTIMAGIC, TRAIT_HOLY), REF(src)) /obj/item/mod/module/anti_magic/wizard name = "MOD magic neutralizer module" @@ -199,10 +210,10 @@ required_slots = list() /obj/item/mod/module/anti_magic/wizard/on_part_activation() - mod.wearer.add_traits(list(TRAIT_ANTIMAGIC, TRAIT_ANTIMAGIC_NO_SELFBLOCK), MOD_TRAIT) + mod.wearer.add_traits(list(TRAIT_ANTIMAGIC, TRAIT_ANTIMAGIC_NO_SELFBLOCK), REF(src)) /obj/item/mod/module/anti_magic/wizard/on_part_deactivation(deleting = FALSE) - mod.wearer.remove_traits(list(TRAIT_ANTIMAGIC, TRAIT_ANTIMAGIC_NO_SELFBLOCK), MOD_TRAIT) + mod.wearer.remove_traits(list(TRAIT_ANTIMAGIC, TRAIT_ANTIMAGIC_NO_SELFBLOCK), REF(src)) ///Insignia - Gives you a skin specific stripe. /obj/item/mod/module/insignia @@ -262,24 +273,20 @@ required_slots = list(ITEM_SLOT_FEET) /obj/item/mod/module/noslip/on_part_activation() - ADD_TRAIT(mod.wearer, TRAIT_NO_SLIP_WATER, MOD_TRAIT) + ADD_TRAIT(mod.wearer, TRAIT_NO_SLIP_WATER, REF(src)) /obj/item/mod/module/noslip/on_part_deactivation(deleting = FALSE) - REMOVE_TRAIT(mod.wearer, TRAIT_NO_SLIP_WATER, MOD_TRAIT) + REMOVE_TRAIT(mod.wearer, TRAIT_NO_SLIP_WATER, REF(src)) //Bite of 87 Springlock - Equips faster, disguised as DNA lock. /obj/item/mod/module/springlock/bite_of_87 + name = /obj/item/mod/module/dna_lock::name + desc = /obj/item/mod/module/dna_lock::desc + icon_state = /obj/item/mod/module/dna_lock::icon_state + complexity = /obj/item/mod/module/dna_lock::complexity + use_energy_cost = /obj/item/mod/module/dna_lock::use_energy_cost step_change = 0.1 -/obj/item/mod/module/springlock/bite_of_87/Initialize(mapload) - . = ..() - var/obj/item/mod/module/dna_lock/the_dna_lock_behind_the_slaughter = /obj/item/mod/module/dna_lock - name = initial(the_dna_lock_behind_the_slaughter.name) - desc = initial(the_dna_lock_behind_the_slaughter.desc) - icon_state = initial(the_dna_lock_behind_the_slaughter.icon_state) - complexity = initial(the_dna_lock_behind_the_slaughter.complexity) - use_energy_cost = initial(the_dna_lock_behind_the_slaughter.use_energy_cost) - /obj/item/mod/module/springlock/bite_of_87/on_part_activation() ..() if(check_holidays(APRIL_FOOLS) || prob(1)) @@ -404,7 +411,7 @@ /obj/item/mod/module/chameleon/used() if(mod.active || mod.activating) - balloon_alert(mod.wearer, "suit active!") + balloon_alert(mod.wearer, "unit active!") return FALSE return ..() @@ -514,7 +521,7 @@ mod.item_flags &= ~EXAMINE_SKIP /obj/item/mod/module/infiltrator/on_part_activation() - mod.wearer.add_traits(traits_to_add, MOD_TRAIT) + mod.wearer.add_traits(traits_to_add, REF(src)) RegisterSignal(mod.wearer, COMSIG_TRY_MODIFY_SPEECH, PROC_REF(on_speech_modification)) var/obj/item/organ/tongue/user_tongue = mod.wearer.get_organ_slot(ORGAN_SLOT_TONGUE) user_tongue.temp_say_mod = "states" @@ -523,7 +530,7 @@ head_cover.flash_protect = FLASH_PROTECTION_WELDER_HYPER_SENSITIVE /obj/item/mod/module/infiltrator/on_part_deactivation(deleting = FALSE) - mod.wearer.remove_traits(traits_to_add, MOD_TRAIT) + mod.wearer.remove_traits(traits_to_add, REF(src)) UnregisterSignal(mod.wearer, COMSIG_TRY_MODIFY_SPEECH) var/obj/item/organ/tongue/user_tongue = mod.wearer.get_organ_slot(ORGAN_SLOT_TONGUE) user_tongue.temp_say_mod = initial(user_tongue.temp_say_mod) @@ -573,7 +580,7 @@ balloon_alert(mod.wearer, "can't reach that!") return if(istype(target, /obj/machinery/power/apc)) //Bit too strong for a module so this is blacklisted - balloon_alert(mod.wearer, "cant disable apc!") + balloon_alert(mod.wearer, "can't disable apc!") return var/list/things_to_disrupt = list(target) diff --git a/code/modules/mod/modules/modules_engineering.dm b/code/modules/mod/modules/modules_engineering.dm index aea9a415cf4e4..9c96d9edd82b9 100644 --- a/code/modules/mod/modules/modules_engineering.dm +++ b/code/modules/mod/modules/modules_engineering.dm @@ -62,12 +62,12 @@ var/list/active_traits = list(TRAIT_NO_SLIP_WATER, TRAIT_NO_SLIP_ICE, TRAIT_NO_SLIP_SLIDE, TRAIT_NEGATES_GRAVITY) /obj/item/mod/module/magboot/on_activation() - mod.wearer.add_traits(active_traits, MOD_TRAIT) + mod.wearer.add_traits(active_traits, REF(src)) mod.slowdown += slowdown_active mod.wearer.update_equipment_speed_mods() /obj/item/mod/module/magboot/on_deactivation(display_message = TRUE, deleting = FALSE) - mod.wearer.remove_traits(active_traits, MOD_TRAIT) + mod.wearer.remove_traits(active_traits, REF(src)) mod.slowdown -= slowdown_active mod.wearer.update_equipment_speed_mods() @@ -104,7 +104,7 @@ /obj/item/mod/module/tether/get_configuration() . = ..() - .["cut_tethers"] = add_ui_configuration("Cut Tethers", "pin", TRUE) + .["cut_tethers"] = add_ui_configuration("Cut Tethers", "button", "scissors") /obj/item/mod/module/tether/configure_edit(key, value) if (key != "cut_tethers") @@ -267,14 +267,14 @@ /obj/item/mod/module/rad_protection/on_part_activation() AddComponent(/datum/component/geiger_sound) - ADD_TRAIT(mod.wearer, TRAIT_BYPASS_EARLY_IRRADIATED_CHECK, MOD_TRAIT) + ADD_TRAIT(mod.wearer, TRAIT_BYPASS_EARLY_IRRADIATED_CHECK, REF(src)) RegisterSignal(mod.wearer, COMSIG_IN_RANGE_OF_IRRADIATION, PROC_REF(on_pre_potential_irradiation)) for(var/obj/item/part in mod.get_parts(all = TRUE)) ADD_TRAIT(part, TRAIT_RADIATION_PROTECTED_CLOTHING, MOD_TRAIT) /obj/item/mod/module/rad_protection/on_part_deactivation(deleting = FALSE) qdel(GetComponent(/datum/component/geiger_sound)) - REMOVE_TRAIT(mod.wearer, TRAIT_BYPASS_EARLY_IRRADIATED_CHECK, MOD_TRAIT) + REMOVE_TRAIT(mod.wearer, TRAIT_BYPASS_EARLY_IRRADIATED_CHECK, REF(src)) UnregisterSignal(mod.wearer, COMSIG_IN_RANGE_OF_IRRADIATION) for(var/obj/item/part in mod.get_parts(all = TRUE)) REMOVE_TRAIT(part, TRAIT_RADIATION_PROTECTED_CLOTHING, MOD_TRAIT) @@ -309,10 +309,10 @@ required_slots = list(ITEM_SLOT_GLOVES) /obj/item/mod/module/constructor/on_part_activation() - ADD_TRAIT(mod.wearer, TRAIT_QUICK_BUILD, MOD_TRAIT) + ADD_TRAIT(mod.wearer, TRAIT_QUICK_BUILD, REF(src)) /obj/item/mod/module/constructor/on_part_deactivation(deleting = FALSE) - REMOVE_TRAIT(mod.wearer, TRAIT_QUICK_BUILD, MOD_TRAIT) + REMOVE_TRAIT(mod.wearer, TRAIT_QUICK_BUILD, REF(src)) /obj/item/mod/module/constructor/on_use() rcd_scan(src, fade_time = 10 SECONDS) @@ -332,10 +332,10 @@ required_slots = list(ITEM_SLOT_HEAD) /obj/item/mod/module/headprotector/on_part_activation() - ADD_TRAIT(mod.wearer, TRAIT_HEAD_INJURY_BLOCKED, MOD_TRAIT) + ADD_TRAIT(mod.wearer, TRAIT_HEAD_INJURY_BLOCKED, REF(src)) /obj/item/mod/module/headprotector/on_part_deactivation(deleting = FALSE) - REMOVE_TRAIT(mod.wearer, TRAIT_HEAD_INJURY_BLOCKED, MOD_TRAIT) + REMOVE_TRAIT(mod.wearer, TRAIT_HEAD_INJURY_BLOCKED, REF(src)) ///Mister - Sprays water over an area. /obj/item/mod/module/mister diff --git a/code/modules/mod/modules/modules_general.dm b/code/modules/mod/modules/modules_general.dm index 42e4c56f55ec1..d1817e5170ba3 100644 --- a/code/modules/mod/modules/modules_general.dm +++ b/code/modules/mod/modules/modules_general.dm @@ -148,9 +148,9 @@ if (!isnull(mod) && !isnull(mod.wearer) && mod.wearer.get_item_by_slot(slot_flags) == src) if (!stabilize) - ADD_TRAIT(mod.wearer, TRAIT_NOGRAV_ALWAYS_DRIFT, MOD_TRAIT) + ADD_TRAIT(mod.wearer, TRAIT_NOGRAV_ALWAYS_DRIFT, REF(src)) else - REMOVE_TRAIT(mod.wearer, TRAIT_NOGRAV_ALWAYS_DRIFT, MOD_TRAIT) + REMOVE_TRAIT(mod.wearer, TRAIT_NOGRAV_ALWAYS_DRIFT, REF(src)) /obj/item/mod/module/jetpack/get_configuration() . = ..() @@ -171,11 +171,11 @@ /obj/item/mod/module/jetpack/on_activation() mod.wearer.add_movespeed_modifier(/datum/movespeed_modifier/jetpack/full_speed) if (!stabilize) - ADD_TRAIT(mod.wearer, TRAIT_NOGRAV_ALWAYS_DRIFT, MOD_TRAIT) + ADD_TRAIT(mod.wearer, TRAIT_NOGRAV_ALWAYS_DRIFT, REF(src)) /obj/item/mod/module/jetpack/on_deactivation(display_message = TRUE, deleting = FALSE) mod.wearer.remove_movespeed_modifier(/datum/movespeed_modifier/jetpack/full_speed) - REMOVE_TRAIT(mod.wearer, TRAIT_NOGRAV_ALWAYS_DRIFT, MOD_TRAIT) + REMOVE_TRAIT(mod.wearer, TRAIT_NOGRAV_ALWAYS_DRIFT, REF(src)) /obj/item/mod/module/jetpack/advanced name = "MOD advanced ion jetpack module" @@ -672,10 +672,10 @@ return ..() /obj/item/mod/module/plasma_stabilizer/on_equip() - ADD_TRAIT(mod.wearer, TRAIT_HEAD_ATMOS_SEALED, MOD_TRAIT) + ADD_TRAIT(mod.wearer, TRAIT_HEAD_ATMOS_SEALED, REF(src)) /obj/item/mod/module/plasma_stabilizer/on_unequip() - REMOVE_TRAIT(mod.wearer, TRAIT_HEAD_ATMOS_SEALED, MOD_TRAIT) + REMOVE_TRAIT(mod.wearer, TRAIT_HEAD_ATMOS_SEALED, REF(src)) //Finally, https://pipe.miroware.io/5b52ba1d94357d5d623f74aa/mspfa/Nuke%20Ops/Panels/0648.gif can be real: @@ -731,10 +731,10 @@ required_slots = list(ITEM_SLOT_GLOVES) /obj/item/mod/module/signlang_radio/on_part_activation() - ADD_TRAIT(mod.wearer, TRAIT_CAN_SIGN_ON_COMMS, MOD_TRAIT) + ADD_TRAIT(mod.wearer, TRAIT_CAN_SIGN_ON_COMMS, REF(src)) /obj/item/mod/module/signlang_radio/on_part_deactivation(deleting = FALSE) - REMOVE_TRAIT(mod.wearer, TRAIT_CAN_SIGN_ON_COMMS, MOD_TRAIT) + REMOVE_TRAIT(mod.wearer, TRAIT_CAN_SIGN_ON_COMMS, REF(src)) ///A module that recharges the suit by an itsy tiny bit whenever the user takes a step. Originally called "magneto module" but the videogame reference sounds cooler. /obj/item/mod/module/joint_torsion @@ -926,7 +926,7 @@ icon_state = "fishing_glove" complexity = 1 overlay_state_inactive = "fishing_glove" - incompatible_modules = (/obj/item/mod/module/fishing_glove) + incompatible_modules = list(/obj/item/mod/module/fishing_glove) required_slots = list(ITEM_SLOT_GLOVES) var/obj/item/fishing_rod/equipped @@ -952,7 +952,7 @@ if(!istype(tool, /obj/item/fishing_rod)) return ..() if(equipped) - balloon_alert(user, "remove current rod first!") + balloon_alert(user, "already has rod!") if(!user.transferItemToLoc(tool, src)) user.balloon_alert(user, "it's stuck!") equipped = tool diff --git a/code/modules/mod/modules/modules_maint.dm b/code/modules/mod/modules/modules_maint.dm index f6b978d05352f..cd5a575302d9f 100644 --- a/code/modules/mod/modules/modules_maint.dm +++ b/code/modules/mod/modules/modules_maint.dm @@ -295,8 +295,8 @@ mod.wearer.AddElement(/datum/element/forced_gravity, NEGATIVE_GRAVITY) RegisterSignal(mod.wearer, COMSIG_MOVABLE_MOVED, PROC_REF(check_upstairs)) RegisterSignal(mod.wearer, COMSIG_MOB_SAY, PROC_REF(on_talk)) - ADD_TRAIT(mod.wearer, TRAIT_SILENT_FOOTSTEPS, MOD_TRAIT) - passtable_on(mod.wearer, MOD_TRAIT) + ADD_TRAIT(mod.wearer, TRAIT_SILENT_FOOTSTEPS, REF(src)) + passtable_on(mod.wearer, REF(src)) check_upstairs() //todo at some point flip your screen around /obj/item/mod/module/atrocinator/deactivate(display_message = TRUE, deleting = FALSE) @@ -312,8 +312,8 @@ UnregisterSignal(mod.wearer, COMSIG_MOVABLE_MOVED) UnregisterSignal(mod.wearer, COMSIG_MOB_SAY) step_count = 0 - REMOVE_TRAIT(mod.wearer, TRAIT_SILENT_FOOTSTEPS, MOD_TRAIT) - passtable_off(mod.wearer, MOD_TRAIT) + REMOVE_TRAIT(mod.wearer, TRAIT_SILENT_FOOTSTEPS, REF(src)) + passtable_off(mod.wearer, REF(src)) var/turf/open/openspace/current_turf = get_turf(mod.wearer) if(istype(current_turf)) current_turf.zFall(mod.wearer, falling_from_move = TRUE) diff --git a/code/modules/mod/modules/modules_medical.dm b/code/modules/mod/modules/modules_medical.dm index 154717cbcc11c..7c0e1c85b0536 100644 --- a/code/modules/mod/modules/modules_medical.dm +++ b/code/modules/mod/modules/modules_medical.dm @@ -77,13 +77,13 @@ /obj/item/mod/module/quick_carry/on_part_activation() . = ..() - ADD_TRAIT(mod.wearer, TRAIT_FASTMED, MOD_TRAIT) - ADD_TRAIT(mod.wearer, quick_carry_trait, MOD_TRAIT) + ADD_TRAIT(mod.wearer, TRAIT_FASTMED, REF(src)) + ADD_TRAIT(mod.wearer, quick_carry_trait, REF(src)) /obj/item/mod/module/quick_carry/on_part_deactivation(deleting = FALSE) . = ..() - REMOVE_TRAIT(mod.wearer, TRAIT_FASTMED, MOD_TRAIT) - REMOVE_TRAIT(mod.wearer, quick_carry_trait, MOD_TRAIT) + REMOVE_TRAIT(mod.wearer, TRAIT_FASTMED, REF(src)) + REMOVE_TRAIT(mod.wearer, quick_carry_trait, REF(src)) /obj/item/mod/module/quick_carry/advanced name = "MOD advanced quick carry module" diff --git a/code/modules/mod/modules/modules_ninja.dm b/code/modules/mod/modules/modules_ninja.dm index c4e8962c4476d..a6ade06a9098c 100644 --- a/code/modules/mod/modules/modules_ninja.dm +++ b/code/modules/mod/modules/modules_ninja.dm @@ -73,11 +73,11 @@ /obj/item/mod/module/stealth/ninja/on_activation() . = ..() - ADD_TRAIT(mod.wearer, TRAIT_SILENT_FOOTSTEPS, MOD_TRAIT) + ADD_TRAIT(mod.wearer, TRAIT_SILENT_FOOTSTEPS, REF(src)) /obj/item/mod/module/stealth/ninja/on_deactivation(display_message = TRUE, deleting = FALSE) . = ..() - REMOVE_TRAIT(mod.wearer, TRAIT_SILENT_FOOTSTEPS, MOD_TRAIT) + REMOVE_TRAIT(mod.wearer, TRAIT_SILENT_FOOTSTEPS, REF(src)) ///Camera Vision - Prevents flashes, blocks tracking. /obj/item/mod/module/welding/camera_vision @@ -173,16 +173,16 @@ var/accepted_type = /obj/item/energy_katana /obj/item/mod/module/weapon_recall/on_part_activation() - mod.wearer.add_traits(list(TRAIT_NOGUNS, TRAIT_TOSS_GUN_HARD), MOD_TRAIT) + mod.wearer.add_traits(list(TRAIT_NOGUNS, TRAIT_TOSS_GUN_HARD), REF(src)) /obj/item/mod/module/weapon_recall/on_part_deactivation(deleting = FALSE) - mod.wearer.remove_traits(list(TRAIT_NOGUNS, TRAIT_TOSS_GUN_HARD), MOD_TRAIT) + mod.wearer.remove_traits(list(TRAIT_NOGUNS, TRAIT_TOSS_GUN_HARD), REF(src)) /obj/item/mod/module/weapon_recall/on_use() if(!linked_weapon) var/obj/item/weapon_to_link = mod.wearer.is_holding_item_of_type(accepted_type) if(!weapon_to_link) - balloon_alert(mod.wearer, "can't locate weapon!") + balloon_alert(mod.wearer, "no linked weapon!") return set_weapon(weapon_to_link) balloon_alert(mod.wearer, "[linked_weapon.name] linked") @@ -191,7 +191,7 @@ balloon_alert(mod.wearer, "already on self!") return var/distance = get_dist(mod.wearer, linked_weapon) - var/in_view = (linked_weapon in view(mod.wearer)) + var/in_view = (linked_weapon in view(mod.wearer)) && !(linked_weapon in get_turf(mod.wearer)) if(!in_view && !drain_power(use_energy_cost * distance)) balloon_alert(mod.wearer, "not enough charge!") return diff --git a/code/modules/mod/modules/modules_science.dm b/code/modules/mod/modules/modules_science.dm index 409b442336636..8cb15d35370aa 100644 --- a/code/modules/mod/modules/modules_science.dm +++ b/code/modules/mod/modules/modules_science.dm @@ -14,10 +14,10 @@ required_slots = list(ITEM_SLOT_HEAD|ITEM_SLOT_EYES|ITEM_SLOT_MASK) /obj/item/mod/module/reagent_scanner/on_activation() - ADD_TRAIT(mod.wearer, TRAIT_REAGENT_SCANNER, MOD_TRAIT) + ADD_TRAIT(mod.wearer, TRAIT_REAGENT_SCANNER, REF(src)) /obj/item/mod/module/reagent_scanner/on_deactivation(display_message = TRUE, deleting = FALSE) - REMOVE_TRAIT(mod.wearer, TRAIT_REAGENT_SCANNER, MOD_TRAIT) + REMOVE_TRAIT(mod.wearer, TRAIT_REAGENT_SCANNER, REF(src)) /obj/item/mod/module/reagent_scanner/advanced name = "MOD advanced reagent scanner module" @@ -31,12 +31,12 @@ /obj/item/mod/module/reagent_scanner/advanced/on_activation() . = ..() - ADD_TRAIT(mod.wearer, TRAIT_RESEARCH_SCANNER, MOD_TRAIT) + ADD_TRAIT(mod.wearer, TRAIT_RESEARCH_SCANNER, REF(src)) RegisterSignal(SSdcs, COMSIG_GLOB_EXPLOSION, PROC_REF(sense_explosion)) /obj/item/mod/module/reagent_scanner/advanced/on_deactivation(display_message = TRUE, deleting = FALSE) . = ..() - REMOVE_TRAIT(mod.wearer, TRAIT_RESEARCH_SCANNER, MOD_TRAIT) + REMOVE_TRAIT(mod.wearer, TRAIT_RESEARCH_SCANNER, REF(src)) UnregisterSignal(SSdcs, COMSIG_GLOB_EXPLOSION) /obj/item/mod/module/reagent_scanner/advanced/proc/sense_explosion(datum/source, turf/epicenter, @@ -55,9 +55,9 @@ desc = "A module that uses a gravitational core to make the user completely weightless." icon_state = "antigrav" module_type = MODULE_TOGGLE - complexity = 3 + complexity = 2 active_power_cost = DEFAULT_CHARGE_DRAIN * 0.7 - incompatible_modules = list(/obj/item/mod/module/anomaly_locked, /obj/item/mod/module/atrocinator) + incompatible_modules = list(/obj/item/mod/module/atrocinator, /obj/item/mod/module/anomaly_locked/antigrav) accepted_anomalies = list(/obj/item/assembly/signaler/anomaly/grav) required_slots = list(ITEM_SLOT_BACK|ITEM_SLOT_BELT) @@ -88,21 +88,34 @@ icon_state = "teleporter" module_type = MODULE_ACTIVE complexity = 3 - use_energy_cost = DEFAULT_CHARGE_DRAIN * 5 - cooldown_time = 5 SECONDS + use_energy_cost = DEFAULT_CHARGE_DRAIN * 25 + cooldown_time = 4 SECONDS + incompatible_modules = list(/obj/item/mod/module/anomaly_locked/teleporter) accepted_anomalies = list(/obj/item/assembly/signaler/anomaly/bluespace) required_slots = list(ITEM_SLOT_BACK|ITEM_SLOT_BELT) /// Time it takes to teleport - var/teleport_time = 3 SECONDS + var/teleport_time = 1 SECONDS + /// Maximum turf range + var/max_range = 9 /obj/item/mod/module/anomaly_locked/teleporter/on_select_use(atom/target) . = ..() if(!.) return var/turf/open/target_turf = get_turf(target) - if(!istype(target_turf) || target_turf.is_blocked_turf_ignore_climbable() || !(target_turf in view(mod.wearer))) + if(get_dist(target_turf, mod.wearer) > max_range) + balloon_alert(mod.wearer, "too far!") + return + if(!istype(target_turf)) balloon_alert(mod.wearer, "invalid target!") return + if(target_turf.is_blocked_turf_ignore_climbable() || !los_check(mod.wearer, target, pass_args = PASSTABLE|PASSGLASS|PASSGRILLE|PASSMOB|PASSMACHINE|PASSSTRUCTURE|PASSFLAPS|PASSWINDOW)) + balloon_alert(mod.wearer, "blocked destination!") + return + // check early so we don't go through the whole loops + if(!check_teleport_valid(mod.wearer, target_turf, channel = TELEPORT_CHANNEL_BLUESPACE, original_destination = target_turf)) + balloon_alert(mod.wearer, "something holds you back!") + return balloon_alert(mod.wearer, "teleporting...") var/matrix/pre_matrix = matrix() pre_matrix.Scale(4, 0.25) diff --git a/code/modules/mod/modules/modules_security.dm b/code/modules/mod/modules/modules_security.dm index c25dd75275574..0903231830486 100644 --- a/code/modules/mod/modules/modules_security.dm +++ b/code/modules/mod/modules/modules_security.dm @@ -123,7 +123,7 @@ balloon_alert(mod.wearer, "nothing to holster!") return if(!istype(holding) || holding.w_class > WEIGHT_CLASS_BULKY) - balloon_alert(mod.wearer, "it doesn't fit!") + balloon_alert(mod.wearer, "doesn't fit!") return if(mod.wearer.transferItemToLoc(holding, src, force = FALSE, silent = TRUE)) holstered = holding @@ -522,11 +522,11 @@ idle_power_cost = 0 if(STORMTROOPER_MODE) idle_power_cost = DEFAULT_CHARGE_DRAIN * 0.4 - mod.wearer.add_traits(list(TRAIT_NO_GUN_AKIMBO, TRAIT_DOUBLE_TAP), MOD_TRAIT) + mod.wearer.add_traits(list(TRAIT_NO_GUN_AKIMBO, TRAIT_DOUBLE_TAP), REF(src)) RegisterSignal(mod.wearer, COMSIG_MOB_FIRED_GUN, PROC_REF(stormtrooper_fired_gun)) if(SHARPSHOOTER_MODE) idle_power_cost = DEFAULT_CHARGE_DRAIN * 0.6 - mod.wearer.add_traits(list(TRAIT_NO_GUN_AKIMBO, TRAIT_NICE_SHOT), MOD_TRAIT) + mod.wearer.add_traits(list(TRAIT_NO_GUN_AKIMBO, TRAIT_NICE_SHOT), REF(src)) RegisterSignal(mod.wearer, COMSIG_MOB_FIRED_GUN, PROC_REF(sharpshooter_fired_gun)) RegisterSignal(mod.wearer, COMSIG_PROJECTILE_FIRER_BEFORE_FIRE, PROC_REF(apply_ricochet)) mod.wearer.add_movespeed_modifier(/datum/movespeed_modifier/shooting_assistant) @@ -535,10 +535,10 @@ switch(selected_mode) if(STORMTROOPER_MODE) UnregisterSignal(mod.wearer, COMSIG_MOB_FIRED_GUN) - mod.wearer.remove_traits(list(TRAIT_NO_GUN_AKIMBO, TRAIT_DOUBLE_TAP), MOD_TRAIT) + mod.wearer.remove_traits(list(TRAIT_NO_GUN_AKIMBO, TRAIT_DOUBLE_TAP), REF(src)) if(SHARPSHOOTER_MODE) UnregisterSignal(mod.wearer, list(COMSIG_MOB_FIRED_GUN, COMSIG_PROJECTILE_FIRER_BEFORE_FIRE)) - mod.wearer.remove_traits(list(TRAIT_NO_GUN_AKIMBO, TRAIT_NICE_SHOT), MOD_TRAIT) + mod.wearer.remove_traits(list(TRAIT_NO_GUN_AKIMBO, TRAIT_NICE_SHOT), REF(src)) mod.wearer.remove_movespeed_modifier(/datum/movespeed_modifier/shooting_assistant) /obj/item/mod/module/shooting_assistant/drain_power(amount) @@ -582,10 +582,10 @@ required_slots = list(ITEM_SLOT_OCLOTHING) /obj/item/mod/module/shove_blocker/on_part_activation() - mod.wearer.add_traits(list(TRAIT_BRAWLING_KNOCKDOWN_BLOCKED, TRAIT_NO_STAGGER, TRAIT_NO_THROW_HITPUSH), MOD_TRAIT) + mod.wearer.add_traits(list(TRAIT_BRAWLING_KNOCKDOWN_BLOCKED, TRAIT_NO_STAGGER, TRAIT_NO_THROW_HITPUSH), REF(src)) /obj/item/mod/module/shove_blocker/on_part_deactivation(deleting = FALSE) - mod.wearer.remove_traits(list(TRAIT_BRAWLING_KNOCKDOWN_BLOCKED, TRAIT_NO_STAGGER, TRAIT_NO_THROW_HITPUSH), MOD_TRAIT) + mod.wearer.remove_traits(list(TRAIT_BRAWLING_KNOCKDOWN_BLOCKED, TRAIT_NO_STAGGER, TRAIT_NO_THROW_HITPUSH), REF(src)) /obj/item/mod/module/shove_blocker/locked name = "superglued MOD bulwark module" @@ -602,8 +602,8 @@ /obj/item/mod/module/quick_cuff/on_part_activation() . = ..() - ADD_TRAIT(mod.wearer, TRAIT_FAST_CUFFING, MOD_TRAIT) + ADD_TRAIT(mod.wearer, TRAIT_FAST_CUFFING, REF(src)) /obj/item/mod/module/quick_cuff/on_part_deactivation(deleting = FALSE) . = ..() - REMOVE_TRAIT(mod.wearer, TRAIT_FAST_CUFFING, MOD_TRAIT) + REMOVE_TRAIT(mod.wearer, TRAIT_FAST_CUFFING, REF(src)) diff --git a/code/modules/mod/modules/modules_service.dm b/code/modules/mod/modules/modules_service.dm index 79d2d3779e0ff..70c11f069f090 100644 --- a/code/modules/mod/modules/modules_service.dm +++ b/code/modules/mod/modules/modules_service.dm @@ -46,7 +46,7 @@ if(!isitem(target)) return if(!isturf(target.loc)) - balloon_alert(mod.wearer, "must be on the floor!") + balloon_alert(mod.wearer, "not in storage!") return var/obj/item/microwave_target = target var/datum/effect_system/spark_spread/spark_effect = new() @@ -80,7 +80,7 @@ var/obj/item/shoes = mod.get_part_from_slot(ITEM_SLOT_FEET) if(shoes) shoes.AddComponent(/datum/component/squeak, list('sound/effects/footstep/clownstep1.ogg'=1,'sound/effects/footstep/clownstep2.ogg'=1), 50, falloff_exponent = 20) //die off quick please - mod.wearer.AddElementTrait(TRAIT_WADDLING, MOD_TRAIT, /datum/element/waddling) + mod.wearer.AddElementTrait(TRAIT_WADDLING, REF(src), /datum/element/waddling) if(is_clown_job(mod.wearer.mind?.assigned_role)) mod.wearer.add_mood_event("clownshoes", /datum/mood_event/clownshoes) @@ -88,6 +88,6 @@ var/obj/item/shoes = mod.get_part_from_slot(ITEM_SLOT_FEET) if(shoes && !deleting) qdel(shoes.GetComponent(/datum/component/squeak)) - REMOVE_TRAIT(mod.wearer, TRAIT_WADDLING, MOD_TRAIT) + REMOVE_TRAIT(mod.wearer, TRAIT_WADDLING, REF(src)) if(is_clown_job(mod.wearer.mind?.assigned_role)) mod.wearer.clear_mood_event("clownshoes") diff --git a/code/modules/mod/modules/modules_supply.dm b/code/modules/mod/modules/modules_supply.dm index 8be66e0b3e38c..bc34cf8781ec4 100644 --- a/code/modules/mod/modules/modules_supply.dm +++ b/code/modules/mod/modules/modules_supply.dm @@ -61,7 +61,7 @@ return stored_crates += picked_crate picked_crate.forceMove(src) - balloon_alert(mod.wearer, "picked up [picked_crate]") + balloon_alert(mod.wearer, "picked up crate") drain_power(use_energy_cost) else if(length(stored_crates)) var/turf/target_turf = get_turf(target) @@ -407,11 +407,11 @@ )) /obj/item/mod/module/ash_accretion/on_part_activation() - mod.wearer.add_traits(list(TRAIT_ASHSTORM_IMMUNE, TRAIT_SNOWSTORM_IMMUNE), MOD_TRAIT) + mod.wearer.add_traits(list(TRAIT_ASHSTORM_IMMUNE, TRAIT_SNOWSTORM_IMMUNE), REF(src)) RegisterSignal(mod.wearer, COMSIG_MOVABLE_MOVED, PROC_REF(on_move)) /obj/item/mod/module/ash_accretion/on_part_deactivation(deleting = FALSE) - mod.wearer.remove_traits(list(TRAIT_ASHSTORM_IMMUNE, TRAIT_SNOWSTORM_IMMUNE), MOD_TRAIT) + mod.wearer.remove_traits(list(TRAIT_ASHSTORM_IMMUNE, TRAIT_SNOWSTORM_IMMUNE), REF(src)) UnregisterSignal(mod.wearer, COMSIG_MOVABLE_MOVED) if(!traveled_tiles) return @@ -496,10 +496,10 @@ mod.wearer.base_pixel_y -= 4 animate(mod.wearer, animate_time, pixel_y = mod.wearer.base_pixel_y, flags = ANIMATION_PARALLEL) mod.wearer.SpinAnimation(1.5) - mod.wearer.add_traits(user_traits, MOD_TRAIT) + mod.wearer.add_traits(user_traits, REF(src)) mod.wearer.RemoveElement(/datum/element/footstep, FOOTSTEP_MOB_HUMAN, 1, -6) mod.wearer.AddElement(/datum/element/footstep, FOOTSTEP_OBJ_ROBOT, 1, -6, sound_vary = TRUE) - mod.wearer.add_movespeed_mod_immunities(MOD_TRAIT, /datum/movespeed_modifier/damage_slowdown) + mod.wearer.add_movespeed_mod_immunities(REF(src), /datum/movespeed_modifier/damage_slowdown) mod.wearer.add_movespeed_modifier(/datum/movespeed_modifier/sphere) RegisterSignal(mod.wearer, COMSIG_MOB_STATCHANGE, PROC_REF(on_statchange)) @@ -509,8 +509,8 @@ mod.wearer.base_pixel_y += 4 animate(mod.wearer, animate_time, pixel_y = mod.wearer.base_pixel_y) addtimer(CALLBACK(mod.wearer, TYPE_PROC_REF(/datum, remove_filter), list("mod_ball", "mod_blur", "mod_outline")), animate_time) - mod.wearer.remove_traits(user_traits, MOD_TRAIT) - mod.wearer.remove_movespeed_mod_immunities(MOD_TRAIT, /datum/movespeed_modifier/damage_slowdown) + mod.wearer.remove_traits(user_traits, REF(src)) + mod.wearer.remove_movespeed_mod_immunities(REF(src), /datum/movespeed_modifier/damage_slowdown) mod.wearer.RemoveElement(/datum/element/footstep, FOOTSTEP_OBJ_ROBOT, 1, -6, sound_vary = TRUE) mod.wearer.AddElement(/datum/element/footstep, FOOTSTEP_MOB_HUMAN, 1, -6) mod.wearer.remove_movespeed_modifier(/datum/movespeed_modifier/sphere) diff --git a/code/modules/mod/modules/modules_timeline.dm b/code/modules/mod/modules/modules_timeline.dm index c14825bf3c70d..bfb22da0c20da 100644 --- a/code/modules/mod/modules/modules_timeline.dm +++ b/code/modules/mod/modules/modules_timeline.dm @@ -133,13 +133,13 @@ ///Signal fired when wearer attempts to trigger modules, if attempting while time is stopped /obj/item/mod/module/timestopper/proc/on_module_triggered(datum/source) SIGNAL_HANDLER - balloon_alert(mod.wearer, "not while channelling timestop!") + balloon_alert(mod.wearer, "not while stopping time!") return MOD_ABORT_USE ///Signal fired when wearer attempts to activate/deactivate suits, if attempting while time is stopped /obj/item/mod/module/timestopper/proc/on_activate_block(datum/source, user) SIGNAL_HANDLER - balloon_alert(user, "not while channelling timestop!") + balloon_alert(user, "not while stopping time!") return MOD_CANCEL_ACTIVATE ///Timeline Jumper - Infinite phasing. needs some special effects diff --git a/code/modules/mod/modules/modules_visor.dm b/code/modules/mod/modules/modules_visor.dm index d4b6154f88620..64ddc69d2edbf 100644 --- a/code/modules/mod/modules/modules_visor.dm +++ b/code/modules/mod/modules/modules_visor.dm @@ -14,12 +14,12 @@ /obj/item/mod/module/visor/on_activation() if(length(visor_traits)) - mod.wearer.add_traits(visor_traits, MOD_TRAIT) + mod.wearer.add_traits(visor_traits, REF(src)) mod.wearer.update_sight() /obj/item/mod/module/visor/on_deactivation(display_message = TRUE, deleting = FALSE) if(length(visor_traits)) - mod.wearer.remove_traits(visor_traits, MOD_TRAIT) + mod.wearer.remove_traits(visor_traits, REF(src)) mod.wearer.update_sight() //Medical Visor - Gives you a medical HUD. diff --git a/code/modules/modular_computers/file_system/programs/maintenance/camera.dm b/code/modules/modular_computers/file_system/programs/maintenance/camera.dm index f851dada495f3..e62aa35a6088c 100644 --- a/code/modules/modular_computers/file_system/programs/maintenance/camera.dm +++ b/code/modules/modular_computers/file_system/programs/maintenance/camera.dm @@ -11,12 +11,18 @@ circuit_comp_type = /obj/item/circuit_component/mod_program/camera /// Camera built-into the tablet. - var/obj/item/camera/internal_camera + var/obj/item/camera/app/internal_camera /// Latest picture taken by the app. var/datum/picture/internal_picture /// How many pictures were taken already, used for the camera's TGUI photo display var/picture_number = 1 +// Special type of camera for this exact usecase to prevent harddels +/obj/item/camera/app + name = "internal camera" + desc = "Specialized internal camera protected from the hellish depths of SSWardrobe. \ + Yell at coders if you somehow manage to see this" + /datum/computer_file/program/maintenance/camera/on_install() . = ..() internal_camera = new(computer) diff --git a/code/modules/modular_computers/file_system/programs/virtual_pet.dm b/code/modules/modular_computers/file_system/programs/virtual_pet.dm index 746824f8d8bf7..ed30fdbd70326 100644 --- a/code/modules/modular_computers/file_system/programs/virtual_pet.dm +++ b/code/modules/modular_computers/file_system/programs/virtual_pet.dm @@ -445,7 +445,7 @@ GLOBAL_LIST_EMPTY(virtual_pets_list) for(var/type_index as anything in hat_selections) if(level >= hat_selections[type_index]) var/obj/item/hat = type_index - var/obj/item/hat_name = initial(hat.name) + var/hat_name = initial(hat.name) if(length(SSachievements.achievements)) // The Achievements subsystem is active. var/datum/award/required_cheevo = cheevo_hats[hat] if(required_cheevo && !user.client.get_award_status(required_cheevo)) diff --git a/code/modules/power/lighting/light.dm b/code/modules/power/lighting/light.dm index 3657bb84db83a..2cc9464653da5 100644 --- a/code/modules/power/lighting/light.dm +++ b/code/modules/power/lighting/light.dm @@ -576,15 +576,13 @@ else if(istype(user) && user.dna.check_mutation(/datum/mutation/human/telekinesis)) to_chat(user, span_notice("You telekinetically remove the light [fitting].")) else - var/obj/item/bodypart/affecting = user.get_bodypart("[(user.active_hand_index % 2 == 0) ? "r" : "l" ]_arm") - if(affecting?.receive_damage( 0, 5 )) // 5 burn damage - user.update_damage_overlays() + var/obj/item/bodypart/affecting = user.get_active_hand() + user.apply_damage(5, BURN, affecting, wound_bonus = CANT_WOUND) if(HAS_TRAIT(user, TRAIT_LIGHTBULB_REMOVER)) - to_chat(user, span_notice("You feel your [affecting] burning, and the light beginning to budge.")) + to_chat(user, span_notice("You feel your [affecting.plaintext_zone] burning, but the light begins to budge...")) if(!do_after(user, 5 SECONDS, target = src)) return - if(affecting?.receive_damage( 0, 10 )) // 10 more burn damage - user.update_damage_overlays() + user.apply_damage(10, BURN, user.get_active_hand(), wound_bonus = CANT_WOUND) to_chat(user, span_notice("You manage to remove the light [fitting], shattering it in process.")) break_light_tube() else @@ -725,7 +723,7 @@ plane = FLOOR_PLANE light_type = /obj/item/light/bulb fitting = "bulb" - nightshift_brightness = 3 + nightshift_brightness = 4 fire_brightness = 4.5 /obj/machinery/light/floor/get_light_offset() diff --git a/code/modules/power/singularity/singularity.dm b/code/modules/power/singularity/singularity.dm index 1993a51e29b46..a53d959c9e31e 100644 --- a/code/modules/power/singularity/singularity.dm +++ b/code/modules/power/singularity/singularity.dm @@ -149,7 +149,7 @@ if(current_size <= STAGE_TWO) investigate_log("has been destroyed by a heavy explosion.", INVESTIGATE_ENGINE) qdel(src) - return + return TRUE energy -= round(((energy + 1) / 2), 1) if(EXPLODE_HEAVY) diff --git a/code/modules/power/tesla/energy_ball.dm b/code/modules/power/tesla/energy_ball.dm index 2e2931c835c0d..ab210fe1986fe 100644 --- a/code/modules/power/tesla/energy_ball.dm +++ b/code/modules/power/tesla/energy_ball.dm @@ -243,7 +243,7 @@ //This also means we have no need to track distance, as the doview() proc does it all for us. //Darkness fucks oview up hard. I've tried dview() but it doesn't seem to work - //I hate existance + //I hate existence for(var/atom/A as anything in typecache_filter_list(oview(zap_range+2, source), things_to_shock)) if(!(zap_flags & ZAP_ALLOW_DUPLICATES) && LAZYACCESS(shocked_targets, A)) continue diff --git a/code/modules/projectiles/guns/energy/kinetic_accelerator.dm b/code/modules/projectiles/guns/energy/kinetic_accelerator.dm index 7e174b544ea29..d542f2299148c 100644 --- a/code/modules/projectiles/guns/energy/kinetic_accelerator.dm +++ b/code/modules/projectiles/guns/energy/kinetic_accelerator.dm @@ -225,7 +225,7 @@ update_appearance() /obj/projectile/kinetic/on_range() - strike_thing() + strike_thing(loc) ..() /obj/projectile/kinetic/on_hit(atom/target, blocked = 0, pierce_hit) @@ -258,6 +258,17 @@ //mecha_kineticgun version of the projectile /obj/projectile/kinetic/mech range = 5 + damage = 80 + +/obj/projectile/kinetic/mech/strike_thing(atom/target) + . = ..() + new /obj/effect/temp_visual/explosion/fast(target) + for(var/turf/closed/mineral/mineral_turf in RANGE_TURFS(1, target) - target) + mineral_turf.gets_drilled(firer, TRUE) + for(var/mob/living/living_mob in range(1, target) - firer - target) + var/armor = living_mob.run_armor_check(def_zone, armor_flag, armour_penetration = armour_penetration) + living_mob.apply_damage(damage, damage_type, def_zone, armor) + to_chat(living_mob, span_userdanger("You're struck by a [name]!")) //Modkits /obj/item/borg/upgrade/modkit diff --git a/code/modules/projectiles/guns/energy/laser.dm b/code/modules/projectiles/guns/energy/laser.dm index 9c69a718986e4..08cce7d73151c 100644 --- a/code/modules/projectiles/guns/energy/laser.dm +++ b/code/modules/projectiles/guns/energy/laser.dm @@ -154,7 +154,7 @@ /obj/projectile/beam/laser/accelerator/Range() ..() damage += 7 - transform = 0 + transform = matrix() transform *= min(1 + (decayedRange - range) * size_per_tile, max_scale) ///X-ray gun diff --git a/code/modules/projectiles/guns/special/medbeam.dm b/code/modules/projectiles/guns/special/medbeam.dm index 0ad5caf2fec82..95da571baf547 100644 --- a/code/modules/projectiles/guns/special/medbeam.dm +++ b/code/modules/projectiles/guns/special/medbeam.dm @@ -83,56 +83,26 @@ last_check = world.time - if(!los_check(loc, current_target)) + if(!los_check(loc, current_target, mid_check = CALLBACK(src, PROC_REF(mid_los_check)))) QDEL_NULL(current_beam)//this will give the target lost message return if(current_target) on_beam_tick(current_target) -/obj/item/gun/medbeam/proc/los_check(atom/movable/user, mob/target) - var/turf/user_turf = user.loc - if(mounted) - user_turf = get_turf(user) - else if(!istype(user_turf)) - return FALSE - var/obj/dummy = new(user_turf) - dummy.pass_flags |= PASSTABLE|PASSGLASS|PASSGRILLE //Grille/Glass so it can be used through common windows - var/turf/previous_step = user_turf - var/first_step = TRUE - for(var/turf/next_step as anything in (get_line(user_turf, target) - user_turf)) - if(first_step) - for(var/obj/blocker in user_turf) - if(!blocker.density || !(blocker.flags_1 & ON_BORDER_1)) - continue - if(blocker.CanPass(dummy, get_dir(user_turf, next_step))) - continue - return FALSE // Could not leave the first turf. - first_step = FALSE - if(mounted && next_step == user_turf) - - continue //Mechs are dense and thus fail the check - if(next_step.density) +/obj/item/gun/medbeam/proc/mid_los_check(atom/movable/user, mob/target, pass_args = PASSTABLE|PASSGLASS|PASSGRILLE, turf/next_step, obj/dummy) + for(var/obj/effect/ebeam/medical/B in next_step)// Don't cross the str-beams! + if(QDELETED(current_beam)) + break //We shouldn't be processing anymore. + if(QDELETED(B)) + continue + if(!B.owner) + stack_trace("beam without an owner! [B]") + continue + if(B.owner.origin != current_beam.origin) + explosion(B.loc, heavy_impact_range = 3, light_impact_range = 5, flash_range = 8, explosion_cause = src) qdel(dummy) return FALSE - for(var/atom/movable/movable as anything in next_step) - if(!movable.CanPass(dummy, get_dir(next_step, previous_step))) - qdel(dummy) - return FALSE - for(var/obj/effect/ebeam/medical/B in next_step)// Don't cross the str-beams! - if(QDELETED(current_beam)) - break //We shouldn't be processing anymore. - if(QDELETED(B)) - continue - if(!B.owner) - stack_trace("beam without an owner! [B]") - continue - if(B.owner.origin != current_beam.origin) - explosion(B.loc, heavy_impact_range = 3, light_impact_range = 5, flash_range = 8, explosion_cause = src) - qdel(dummy) - return FALSE - previous_step = next_step - qdel(dummy) return TRUE /obj/item/gun/medbeam/proc/on_beam_hit(mob/living/target) diff --git a/code/modules/projectiles/projectile.dm b/code/modules/projectiles/projectile.dm index 0b03f41293142..3d2834edc62db 100644 --- a/code/modules/projectiles/projectile.dm +++ b/code/modules/projectiles/projectile.dm @@ -448,11 +448,11 @@ target = select_target(target_turf, target) continue - if (SEND_SIGNAL(target, COMSIG_PROJECTILE_PREHIT, args, src) & PROJECTILE_INTERRUPT_HIT) + if (SEND_SIGNAL(target, COMSIG_PROJECTILE_PREHIT, src) & PROJECTILE_INTERRUPT_HIT) qdel(src) return - if (SEND_SIGNAL(src, COMSIG_PROJECTILE_SELF_PREHIT, args) & PROJECTILE_INTERRUPT_HIT) + if (SEND_SIGNAL(src, COMSIG_PROJECTILE_SELF_PREHIT, target) & PROJECTILE_INTERRUPT_HIT) qdel(src) return diff --git a/code/modules/projectiles/projectile/energy/nuclear_particle.dm b/code/modules/projectiles/projectile/energy/nuclear_particle.dm index b82ff478a05b4..6626cb9b5ed75 100644 --- a/code/modules/projectiles/projectile/energy/nuclear_particle.dm +++ b/code/modules/projectiles/projectile/energy/nuclear_particle.dm @@ -29,7 +29,7 @@ if (ishuman(target)) SSradiation.irradiate(target) - ..() + return ..() /atom/proc/fire_nuclear_particle(angle = rand(0,360)) //used by fusion to fire random nuclear particles. Fires one particle in a random direction. var/obj/projectile/energy/nuclear_particle/P = new /obj/projectile/energy/nuclear_particle(src) diff --git a/code/modules/reagents/chemistry/reagents.dm b/code/modules/reagents/chemistry/reagents.dm index 4ed21b0e29871..f65383fbfcc7f 100644 --- a/code/modules/reagents/chemistry/reagents.dm +++ b/code/modules/reagents/chemistry/reagents.dm @@ -82,7 +82,7 @@ var/purge_multiplier = 1 ///The default reagent container for the reagent, used for icon generation - var/obj/item/reagent_containers/default_container = /obj/item/reagent_containers/cup/bottle + var/obj/default_container = /obj/item/reagent_containers/cup/bottle // Used for restaurants. ///The amount a robot will pay for a glass of this (20 units but can be higher if you pour more, be frugal!) 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 b8a2250722534..ebd392f536892 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 @@ -480,6 +480,7 @@ Basically, we fill the time between now and 2s from now with hands based off the overdose_threshold = 20 self_consuming = TRUE //No pesky liver shenanigans chemical_flags = REAGENT_DONOTSPLIT | REAGENT_DEAD_PROCESS + affected_organ_flags = NONE ///If we brought someone back from the dead var/back_from_the_dead = FALSE /// List of trait buffs to give to the affected mob, and remove as needed. diff --git a/code/modules/reagents/reagent_containers/spray.dm b/code/modules/reagents/reagent_containers/spray.dm index 17ce2fea149f4..04ff332a9ea31 100644 --- a/code/modules/reagents/reagent_containers/spray.dm +++ b/code/modules/reagents/reagent_containers/spray.dm @@ -402,6 +402,7 @@ spray_range = 2 spray_sound = 'sound/effects/snap.ogg' possible_transfer_amounts = list(5) + reagent_container_liquid_sound = null /obj/item/reagent_containers/spray/chemsprayer/party/spray(atom/A, mob/user) . = ..() diff --git a/code/modules/religion/rites.dm b/code/modules/religion/rites.dm index cd0fabba84974..67526918167a7 100644 --- a/code/modules/religion/rites.dm +++ b/code/modules/religion/rites.dm @@ -20,9 +20,8 @@ LAZYADD(GLOB.religious_sect.active_rites, src) /datum/religion_rites/Destroy() - if(!GLOB?.religious_sect) - return - LAZYREMOVE(GLOB.religious_sect.active_rites, src) + if(GLOB?.religious_sect) + LAZYREMOVE(GLOB.religious_sect.active_rites, src) return ..() /datum/religion_rites/proc/can_afford(mob/living/user) diff --git a/code/modules/research/designs/mecha_designs.dm b/code/modules/research/designs/mecha_designs.dm index 21deb54280cd3..2f43fe5813323 100644 --- a/code/modules/research/designs/mecha_designs.dm +++ b/code/modules/research/designs/mecha_designs.dm @@ -750,7 +750,7 @@ desc = "Equipment for medical exosuits. A mounted sleeper that stabilizes patients and can inject reagents in the exosuit's reserves." id = "mech_sleeper" build_type = MECHFAB - build_path = /obj/item/mecha_parts/mecha_equipment/medical/sleeper + build_path = /obj/item/mecha_parts/mecha_equipment/sleeper/medical materials = list(/datum/material/iron=SHEET_MATERIAL_AMOUNT * 2.5, /datum/material/glass = SHEET_MATERIAL_AMOUNT*5) construction_time = 10 SECONDS category = list( diff --git a/code/modules/research/designs/misc_designs.dm b/code/modules/research/designs/misc_designs.dm index 90b8acee031a9..3aaa99e5ae04b 100644 --- a/code/modules/research/designs/misc_designs.dm +++ b/code/modules/research/designs/misc_designs.dm @@ -1121,3 +1121,21 @@ RND_CATEGORY_EQUIPMENT + RND_SUBCATEGORY_EQUIPMENT_SCIENCE ) departmental_flags = DEPARTMENT_BITFLAG_SCIENCE + +/datum/design/perceptomatrix + name = "Perceptomatrix Helm" + id = "perceptomatrix" + desc = "This helm harnesses hallucinative energies to shield its owner from perceptual anomalies. It requires a Hallucination Anomaly Core in order to function." + build_type = PROTOLATHE | AWAY_LATHE + build_path = /obj/item/clothing/head/helmet/perceptomatrix + materials = list( + /datum/material/titanium = SHEET_MATERIAL_AMOUNT * 2, + /datum/material/silver = SHEET_MATERIAL_AMOUNT * 1, + /datum/material/gold = SHEET_MATERIAL_AMOUNT * 0.5, + /datum/material/plasma = SHEET_MATERIAL_AMOUNT * 3, + /datum/material/uranium = SHEET_MATERIAL_AMOUNT, + ) + category = list( + RND_CATEGORY_EQUIPMENT + RND_SUBCATEGORY_EQUIPMENT_SCIENCE + ) + departmental_flags = DEPARTMENT_BITFLAG_SCIENCE diff --git a/code/modules/research/techweb/_techweb_node.dm b/code/modules/research/techweb/_techweb_node.dm index b6d3bd74d6979..79b8b27986c9f 100644 --- a/code/modules/research/techweb/_techweb_node.dm +++ b/code/modules/research/techweb/_techweb_node.dm @@ -34,7 +34,7 @@ var/category = "Misc" /// The list of experiments required to research the node var/list/required_experiments = list() - /// If completed, these experiments give a specific point amount discount to the node.area + /// If completed, these experiments give a specific point amount discount to the node. var/list/discount_experiments = list() /// When this node is completed, allows these experiments to be performed. var/list/experiments_to_unlock = list() diff --git a/code/modules/research/techweb/nodes/atmos_nodes.dm b/code/modules/research/techweb/nodes/atmos_nodes.dm index b0e2f1598d1e5..86992d5919611 100644 --- a/code/modules/research/techweb/nodes/atmos_nodes.dm +++ b/code/modules/research/techweb/nodes/atmos_nodes.dm @@ -65,7 +65,7 @@ "plasmacutter", ) research_costs = list(TECHWEB_POINT_TYPE_GENERIC = TECHWEB_TIER_2_POINTS) - required_experiments = list(/datum/experiment/ordnance/gaseous/plasma) + discount_experiments = list(/datum/experiment/ordnance/gaseous/plasma = TECHWEB_TIER_2_POINTS) announce_channels = list(RADIO_CHANNEL_ENGINEERING) /datum/techweb_node/fusion diff --git a/code/modules/research/techweb/nodes/mech_nodes.dm b/code/modules/research/techweb/nodes/mech_nodes.dm index 82d6484bf0225..bf520b2fc3d72 100644 --- a/code/modules/research/techweb/nodes/mech_nodes.dm +++ b/code/modules/research/techweb/nodes/mech_nodes.dm @@ -96,6 +96,7 @@ "clarke_right_arm", "clarke_main", "clarke_peri", + "mecha_kineticgun", ) research_costs = list(TECHWEB_POINT_TYPE_GENERIC = TECHWEB_TIER_2_POINTS) announce_channels = list(RADIO_CHANNEL_SCIENCE, RADIO_CHANNEL_SUPPLY) diff --git a/code/modules/research/techweb/nodes/mining_nodes.dm b/code/modules/research/techweb/nodes/mining_nodes.dm index 1bfa3a9284ad5..9c0ab9d879d1b 100644 --- a/code/modules/research/techweb/nodes/mining_nodes.dm +++ b/code/modules/research/techweb/nodes/mining_nodes.dm @@ -56,7 +56,6 @@ description = "Research of Proto-Kinetic Accelerators (PKAs), pneumatic guns renowned for their exceptional performance in low-pressure environments." prereq_ids = list(TECHWEB_NODE_MINING, TECHWEB_NODE_GAS_COMPRESSION) design_ids = list( - "mecha_kineticgun", "damagemod", "rangemod", "cooldownmod", diff --git a/code/modules/research/techweb/nodes/research_nodes.dm b/code/modules/research/techweb/nodes/research_nodes.dm index f05199ab65e68..3b58551ec9cb3 100644 --- a/code/modules/research/techweb/nodes/research_nodes.dm +++ b/code/modules/research/techweb/nodes/research_nodes.dm @@ -49,7 +49,7 @@ "gigabeacon", ) research_costs = list(TECHWEB_POINT_TYPE_GENERIC = TECHWEB_TIER_2_POINTS) - required_experiments = list(/datum/experiment/scanning/points/bluespace_crystal) + discount_experiments = list(/datum/experiment/scanning/points/bluespace_crystal) announce_channels = list(RADIO_CHANNEL_SCIENCE, RADIO_CHANNEL_MEDICAL, RADIO_CHANNEL_SERVICE, RADIO_CHANNEL_SUPPLY) /datum/techweb_node/bluespace_travel @@ -94,7 +94,8 @@ "cybernetic_heart_anomalock", "wormholeprojector", "gravitygun", - "polymorph_belt" + "polymorph_belt", + "perceptomatrix", ) research_costs = list(TECHWEB_POINT_TYPE_GENERIC = TECHWEB_TIER_5_POINTS) discount_experiments = list(/datum/experiment/scanning/points/anomalies = TECHWEB_TIER_5_POINTS) diff --git a/code/modules/research/xenobiology/crossbreeding/burning.dm b/code/modules/research/xenobiology/crossbreeding/burning.dm index c3eb811fa4270..f114d3ad55da4 100644 --- a/code/modules/research/xenobiology/crossbreeding/burning.dm +++ b/code/modules/research/xenobiology/crossbreeding/burning.dm @@ -211,9 +211,6 @@ Burning extracts: effect_desc = "The user gets a dull arm blade in the hand it is used in." /obj/item/slimecross/burning/green/do_effect(mob/user) - var/which_hand = "l_hand" - if(!(user.active_hand_index % 2)) - which_hand = "r_hand" var/mob/living/L = user if(!istype(user)) return @@ -226,7 +223,7 @@ Burning extracts: else user.visible_message(span_danger("[src] sublimates the flesh around [user]'s arm, transforming the bone into a gruesome blade!")) user.emote("scream") - L.apply_damage(30,BURN,which_hand) + L.apply_damage(30, BURN, L.get_active_hand()) ..() /obj/item/slimecross/burning/pink diff --git a/code/modules/research/xenobiology/crossbreeding/chilling.dm b/code/modules/research/xenobiology/crossbreeding/chilling.dm index 0a22cd0380f5e..c1c599da345c2 100644 --- a/code/modules/research/xenobiology/crossbreeding/chilling.dm +++ b/code/modules/research/xenobiology/crossbreeding/chilling.dm @@ -252,9 +252,6 @@ Chilling extracts: effect_desc = "Creates a bone gun in the hand it is used in, which uses blood as ammo." /obj/item/slimecross/chilling/green/do_effect(mob/user) - var/which_hand = "l_hand" - if(!(user.active_hand_index % 2)) - which_hand = "r_hand" var/mob/living/L = user if(!istype(user)) return @@ -267,7 +264,7 @@ Chilling extracts: else user.visible_message(span_danger("[src] chills and snaps off the front of the bone on [user]'s arm, leaving behind a strange, gun-like structure!")) user.emote("scream") - L.apply_damage(30,BURN,which_hand) + L.apply_damage(30, BURN, L.get_active_hand()) ..() /obj/item/slimecross/chilling/pink diff --git a/code/modules/shuttle/supply.dm b/code/modules/shuttle/supply.dm index 4eed7f3e9a7e1..b5b7cc6f6ef85 100644 --- a/code/modules/shuttle/supply.dm +++ b/code/modules/shuttle/supply.dm @@ -151,7 +151,7 @@ GLOBAL_LIST_INIT(blacklisted_cargo_types, typecacheof(list( investigate_log("Chef's [SSshuttle.chef_groceries.len] sized produce order arrived. Cost was deducted from orderer, not cargo.", INVESTIGATE_CARGO) for(var/datum/orderable_item/item as anything in SSshuttle.chef_groceries)//every order for(var/amt in 1 to SSshuttle.chef_groceries[item])//every order amount - new item.item_path(grocery_crate) + new item.purchase_path(grocery_crate) SSshuttle.chef_groceries.Cut() //This lets the console know it can order another round. if(!SSshuttle.shopping_list.len) diff --git a/code/modules/spells/spell_types/jaunt/bloodcrawl.dm b/code/modules/spells/spell_types/jaunt/bloodcrawl.dm index 2795efc2b201b..aa6a58b1341be 100644 --- a/code/modules/spells/spell_types/jaunt/bloodcrawl.dm +++ b/code/modules/spells/spell_types/jaunt/bloodcrawl.dm @@ -5,7 +5,7 @@ */ /datum/action/cooldown/spell/jaunt/bloodcrawl name = "Blood Crawl" - desc = "Allows you to phase in and out of existance via pools of blood." + desc = "Allows you to phase in and out of existence via pools of blood." background_icon_state = "bg_demon" overlay_icon_state = "bg_demon_border" @@ -158,7 +158,7 @@ */ /datum/action/cooldown/spell/jaunt/bloodcrawl/slaughter_demon name = "Voracious Blood Crawl" - desc = "Allows you to phase in and out of existance via pools of blood. If you are dragging someone in critical or dead, \ + desc = "Allows you to phase in and out of existence via pools of blood. If you are dragging someone in critical or dead, \ they will be consumed by you, fully healing you." /// The sound played when someone's consumed. var/consume_sound = 'sound/effects/magic/demon_consume.ogg' @@ -285,7 +285,7 @@ */ /datum/action/cooldown/spell/jaunt/bloodcrawl/slaughter_demon/funny name = "Friendly Blood Crawl" - desc = "Allows you to phase in and out of existance via pools of blood. If you are dragging someone in critical or dead - I mean, \ + desc = "Allows you to phase in and out of existence via pools of blood. If you are dragging someone in critical or dead - I mean, \ sleeping, when entering a blood pool, they will be invited to a party and fully heal you!" consume_sound = 'sound/misc/scary_horn.ogg' @@ -332,7 +332,7 @@ // Heals them back to state one if(!friend.revive(ADMIN_HEAL_ALL, force_grab_ghost = TRUE)) continue - playsound(release_turf, consumed_mobs, 50, TRUE, -1) + friend.playsound_local(release_turf, 'sound/effects/magic/exit_blood.ogg', 50, TRUE, -1) to_chat(friend, span_clown("You leave [source]'s warm embrace, and feel ready to take on the world.")) diff --git a/code/modules/spells/spell_types/pointed/_pointed.dm b/code/modules/spells/spell_types/pointed/_pointed.dm index 9189106d87424..a96e2fe9fd291 100644 --- a/code/modules/spells/spell_types/pointed/_pointed.dm +++ b/code/modules/spells/spell_types/pointed/_pointed.dm @@ -101,7 +101,7 @@ */ /datum/action/cooldown/spell/pointed/projectile /// What projectile we create when we shoot our spell. - var/obj/projectile/magic/projectile_type = /obj/projectile/magic/teleport + var/obj/projectile/projectile_type = /obj/projectile/magic/teleport /// How many projectiles we can fire per cast. Not all at once, per click, kinda like charges var/projectile_amount = 1 /// How many projectiles we have yet to fire, based on projectile_amount diff --git a/code/modules/spells/spell_types/self/splattercasting_spell.dm b/code/modules/spells/spell_types/self/splattercasting_spell.dm index 184a2afab7ca2..e76f8e3c1b9bf 100644 --- a/code/modules/spells/spell_types/self/splattercasting_spell.dm +++ b/code/modules/spells/spell_types/self/splattercasting_spell.dm @@ -28,7 +28,7 @@ brings unimaginable momentary torment as your heart stops, and your skin grows cold. You are now \ merely a vessel for the arcane flow. Soon, all that is left is not pain, but hunger.")) - cast_on.set_species(/datum/species/vampire) + cast_on.set_species(/datum/species/human/vampire) cast_on.blood_volume = BLOOD_VOLUME_NORMAL ///for predictable blood total amounts when the spell is first cast. cast_on.AddComponent(/datum/component/splattercasting) diff --git a/code/modules/spells/spell_types/shapeshift/_shape_status.dm b/code/modules/spells/spell_types/shapeshift/_shape_status.dm index f8f44817a5932..9e1284d27f60c 100644 --- a/code/modules/spells/spell_types/shapeshift/_shape_status.dm +++ b/code/modules/spells/spell_types/shapeshift/_shape_status.dm @@ -243,6 +243,7 @@ desc = "Your form is not your own... you're shapeshifted into another creature! \ A wizard could turn you back - or maybe you're stuck like this for good?" icon_state = "shapeshifted" + clickable_glow = TRUE /atom/movable/screen/alert/status_effect/shapeshifted/Click(location, control, params) . = ..() diff --git a/code/modules/station_goals/bsa.dm b/code/modules/station_goals/bsa.dm index 683afe605c983..7467f85d79e93 100644 --- a/code/modules/station_goals/bsa.dm +++ b/code/modules/station_goals/bsa.dm @@ -212,7 +212,7 @@ GLOBAL_VAR_INIT(bsa_unlock, FALSE) var/turf/point = get_front_turf() var/turf/target = get_target_turf() - var/atom/movable/blocker + var/atom/blocker for(var/T in get_line(get_step(point, dir), target)) var/turf/tile = T if(SEND_SIGNAL(tile, COMSIG_ATOM_BSA_BEAM) & COMSIG_ATOM_BLOCKS_BSA_BEAM) diff --git a/code/modules/surgery/bodyparts/helpers.dm b/code/modules/surgery/bodyparts/helpers.dm index dec8efb154eae..2f9a42e0d1f9c 100644 --- a/code/modules/surgery/bodyparts/helpers.dm +++ b/code/modules/surgery/bodyparts/helpers.dm @@ -40,11 +40,12 @@ ///Get the bodypart for whatever hand we have active, Only relevant for carbons /mob/proc/get_active_hand() + RETURN_TYPE(/obj/item/bodypart) return FALSE /mob/living/carbon/get_active_hand() var/which_hand = BODY_ZONE_PRECISE_L_HAND - if(!(active_hand_index % RIGHT_HANDS)) + if(IS_RIGHT_INDEX(active_hand_index)) which_hand = BODY_ZONE_PRECISE_R_HAND return get_bodypart(check_zone(which_hand)) @@ -54,7 +55,7 @@ /mob/living/carbon/get_inactive_hand() var/which_hand = BODY_ZONE_PRECISE_R_HAND - if(!(active_hand_index % RIGHT_HANDS)) + if(IS_RIGHT_INDEX(active_hand_index)) which_hand = BODY_ZONE_PRECISE_L_HAND return get_bodypart(check_zone(which_hand)) @@ -64,7 +65,7 @@ /mob/living/carbon/has_left_hand(check_disabled = TRUE) for(var/obj/item/bodypart/hand_instance in hand_bodyparts) - if(!(hand_instance.held_index % RIGHT_HANDS) || (check_disabled && hand_instance.bodypart_disabled)) + if(IS_RIGHT_INDEX(hand_instance.held_index) || (check_disabled && hand_instance.bodypart_disabled)) continue return TRUE return FALSE @@ -80,7 +81,7 @@ /mob/living/carbon/has_right_hand(check_disabled = TRUE) for(var/obj/item/bodypart/hand_instance in hand_bodyparts) - if(hand_instance.held_index % RIGHT_HANDS || (check_disabled && hand_instance.bodypart_disabled)) + if(IS_LEFT_INDEX(hand_instance.held_index) || (check_disabled && hand_instance.bodypart_disabled)) continue return TRUE return FALSE diff --git a/code/modules/surgery/bodyparts/parts.dm b/code/modules/surgery/bodyparts/parts.dm index 25f66f40af9a8..c7e1f7f7846da 100644 --- a/code/modules/surgery/bodyparts/parts.dm +++ b/code/modules/surgery/bodyparts/parts.dm @@ -106,7 +106,7 @@ bodypart_flags = BODYPART_UNREMOVABLE max_damage = LIMB_MAX_HP_ALIEN_CORE acceptable_bodyshape = BODYSHAPE_HUMANOID - wing_types = NONE + wing_types = null /obj/item/bodypart/chest/larva icon = 'icons/mob/human/species/alien/bodyparts.dmi' @@ -119,7 +119,7 @@ max_damage = LIMB_MAX_HP_ALIEN_LARVA bodytype = BODYTYPE_LARVA_PLACEHOLDER | BODYTYPE_ORGANIC acceptable_bodytype = BODYTYPE_LARVA_PLACEHOLDER - wing_types = NONE + wing_types = null /// Parent Type for arms, should not appear in game. /obj/item/bodypart/arm diff --git a/code/modules/surgery/bodyparts/species_parts/ethereal_bodyparts.dm b/code/modules/surgery/bodyparts/species_parts/ethereal_bodyparts.dm index 016a80682cf53..33e07b09fcdf7 100644 --- a/code/modules/surgery/bodyparts/species_parts/ethereal_bodyparts.dm +++ b/code/modules/surgery/bodyparts/species_parts/ethereal_bodyparts.dm @@ -22,7 +22,7 @@ is_dimorphic = FALSE dmg_overlay_type = null brute_modifier = 1.25 //ethereal are weak to brute damages - wing_types = NONE + wing_types = null //bodypart_traits = list(TRAIT_NO_UNDERWEAR) //DOPPLER EDIT REMOVAL /obj/item/bodypart/chest/ethereal/update_limb(dropping_limb, is_creating) diff --git a/code/modules/surgery/bodyparts/species_parts/misc_bodyparts.dm b/code/modules/surgery/bodyparts/species_parts/misc_bodyparts.dm index d5d44b1f1f1b8..5bd2ac2e3c943 100644 --- a/code/modules/surgery/bodyparts/species_parts/misc_bodyparts.dm +++ b/code/modules/surgery/bodyparts/species_parts/misc_bodyparts.dm @@ -12,7 +12,7 @@ is_dimorphic = FALSE burn_modifier = 2 biological_state = (BIO_FLESH|BIO_BLOODED) - wing_types = NONE + wing_types = null /obj/item/bodypart/arm/left/snail limb_id = SPECIES_SNAIL @@ -58,7 +58,7 @@ limb_id = SPECIES_ABDUCTOR is_dimorphic = FALSE should_draw_greyscale = FALSE - wing_types = NONE + wing_types = null /obj/item/bodypart/chest/abductor/get_butt_sprite() return icon('icons/mob/butts.dmi', BUTT_SPRITE_GREY) @@ -177,7 +177,7 @@ limb_id = SPECIES_ZOMBIE is_dimorphic = FALSE should_draw_greyscale = FALSE - wing_types = NONE + wing_types = null /obj/item/bodypart/arm/left/zombie limb_id = SPECIES_ZOMBIE @@ -216,7 +216,7 @@ limb_id = SPECIES_PODPERSON is_dimorphic = TRUE burn_modifier = 1.25 - wing_types = NONE + wing_types = null /obj/item/bodypart/chest/pod/get_butt_sprite() return icon('icons/mob/butts.dmi', BUTT_SPRITE_FLOWERPOT) @@ -292,7 +292,7 @@ is_dimorphic = FALSE should_draw_greyscale = FALSE burn_modifier = 1.5 - wing_types = NONE + wing_types = null /obj/item/bodypart/arm/left/shadow limb_id = SPECIES_SHADOW @@ -380,7 +380,7 @@ is_dimorphic = TRUE bodypart_traits = list(TRAIT_NO_JUMPSUIT) burn_modifier = 1.25 - wing_types = NONE + wing_types = null /obj/item/bodypart/arm/left/mushroom limb_id = SPECIES_MUSHROOM @@ -483,7 +483,7 @@ should_draw_greyscale = FALSE dmg_overlay_type = null bodypart_traits = list(TRAIT_NO_JUMPSUIT) - wing_types = NONE + wing_types = null /obj/item/bodypart/chest/golem/Initialize(mapload) worn_belt_offset = new( diff --git a/code/modules/surgery/bodyparts/species_parts/plasmaman_bodyparts.dm b/code/modules/surgery/bodyparts/species_parts/plasmaman_bodyparts.dm index 0125601bda5a7..b668008e44c05 100644 --- a/code/modules/surgery/bodyparts/species_parts/plasmaman_bodyparts.dm +++ b/code/modules/surgery/bodyparts/species_parts/plasmaman_bodyparts.dm @@ -28,7 +28,7 @@ brute_modifier = 1.5 //Plasmemes are weak burn_modifier = 1.5 //Plasmemes are weak bodypart_flags = BODYPART_UNHUSKABLE - wing_types = NONE + wing_types = null /obj/item/bodypart/chest/plasmaman/get_butt_sprite() return icon('icons/mob/butts.dmi', BUTT_SPRITE_PLASMA) diff --git a/code/modules/surgery/organs/internal/cyberimp/augments_arms.dm b/code/modules/surgery/organs/internal/cyberimp/augments_arms.dm index a07b8caed6c9f..7d0b249bdbcbc 100644 --- a/code/modules/surgery/organs/internal/cyberimp/augments_arms.dm +++ b/code/modules/surgery/organs/internal/cyberimp/augments_arms.dm @@ -278,6 +278,35 @@ /obj/item/organ/cyberimp/arm/toolset/l zone = BODY_ZONE_L_ARM +//The order of the item list for this implant is not alphabetized due to it actually affecting how it shows up playerside when opening the implant +/obj/item/organ/cyberimp/arm/paperwork + name = "integrated paperwork implant" + desc = "A highly sought out implant among heads of personnel, and other high up command staff in Nanotrasen. This implant allows the user to always have the tools necesarry for paperwork handy" + icon_state = "toolkit_engineering" + actions_types = list(/datum/action/item_action/organ_action/toggle/toolkit) + items_to_create = list( + /obj/item/pen/fountain, + /obj/item/clipboard, + /obj/item/taperecorder, + /obj/item/lighter, + /obj/item/laser_pointer, + /obj/item/stamp, + /obj/item/stamp/denied, + ) + +/obj/item/organ/cyberimp/arm/paperwork/l + zone = BODY_ZONE_L_ARM + +/obj/item/organ/cyberimp/arm/paperwork/emag_act(mob/user, obj/item/card/emag/emag_card) + for(var/datum/weakref/created_item in items_list) + var/obj/potential_tool = created_item.resolve() + if(istype(/obj/item/stamp/chameleon, potential_tool)) + return FALSE + + balloon_alert(user, "experimental stamp unlocked") + items_list += WEAKREF(new /obj/item/stamp/chameleon(src)) + return TRUE + /obj/item/organ/cyberimp/arm/toolset/emag_act(mob/user, obj/item/card/emag/emag_card) for(var/datum/weakref/created_item in items_list) var/obj/potential_knife = created_item.resolve() diff --git a/code/modules/transport/tram/tram_controller.dm b/code/modules/transport/tram/tram_controller.dm index 5ac6d5bc748bc..37220034b664b 100644 --- a/code/modules/transport/tram/tram_controller.dm +++ b/code/modules/transport/tram/tram_controller.dm @@ -144,7 +144,7 @@ tram_registration.active = FALSE SSblackbox.record_feedback("amount", "tram_destroyed", 1) SSpersistence.save_tram_history(specific_transport_id) - ..() + return ..() /** * Register transport modules to the controller diff --git a/code/modules/tutorials/tutorials/switch_hands.dm b/code/modules/tutorials/tutorials/switch_hands.dm index f1bcbbb3b7117..1d8fbd72f3c90 100644 --- a/code/modules/tutorials/tutorials/switch_hands.dm +++ b/code/modules/tutorials/tutorials/switch_hands.dm @@ -38,7 +38,7 @@ /datum/tutorial/switch_hands/proc/create_hand_preview(initial_screen_loc) hand_preview = animate_ui_element( - "hand_[hand_to_watch % 2 == 0 ? "r" : "l"]", + "hand_[user.held_index_to_dir(hand_to_watch)]", initial_screen_loc, ui_hand_position(hand_to_watch), TIME_TO_START_MOVING_HAND_ICON, @@ -50,7 +50,7 @@ switch (stage) if (STAGE_SHOULD_SWAP_HAND) - var/hand_name = hand_to_watch % 2 == 0 ? "right" : "left" + var/hand_name = IS_RIGHT_INDEX(hand_to_watch) ? "right" : "left" show_instruction(keybinding_message( /datum/keybinding/mob/swap_hands, "Press '%KEY%' to use your [hand_name] hand", diff --git a/code/modules/unit_tests/orderable_items.dm b/code/modules/unit_tests/orderable_items.dm index 8d3db8c3c751f..e94b2985a5475 100644 --- a/code/modules/unit_tests/orderable_items.dm +++ b/code/modules/unit_tests/orderable_items.dm @@ -6,19 +6,19 @@ /datum/unit_test/orderable_items/Run() var/list/all_paths = list() for (var/datum/orderable_item/orderable_item as anything in subtypesof(/datum/orderable_item)) - if(isnull(initial(orderable_item.item_path))) // don't check if they're not actual orderable items + if(isnull(initial(orderable_item.purchase_path))) // don't check if they're not actual orderable items continue if (!isnull(initial(orderable_item.desc))) //don't check if they have a custom description continue - var/item_path = initial(orderable_item.item_path) + var/purchase_path = initial(orderable_item.purchase_path) - var/obj/item/item_instance = allocate(item_path) + var/obj/item/item_instance = allocate(purchase_path) var/initial_desc = initial(item_instance.desc) - if(item_path in all_paths) + if(purchase_path in all_paths) TEST_FAIL("[orderable_item] is purchasable under two different orderable_item types,") - all_paths += item_path + all_paths += purchase_path if (item_instance.desc != initial_desc) - TEST_FAIL("[orderable_item] has an item ([item_path]) that has a dynamic description. [item_instance.desc] (dynamic description) != [initial_desc] (initial description)") + TEST_FAIL("[orderable_item] has a product ([purchase_path]) that has a dynamic description. [item_instance.desc] (dynamic description) != [initial_desc] (initial description)") diff --git a/code/modules/unit_tests/screenshots/screenshot_humanoids__datum_species_vampire.png b/code/modules/unit_tests/screenshots/screenshot_humanoids__datum_species_human_vampire.png similarity index 100% rename from code/modules/unit_tests/screenshots/screenshot_humanoids__datum_species_vampire.png rename to code/modules/unit_tests/screenshots/screenshot_humanoids__datum_species_human_vampire.png diff --git a/code/modules/unit_tests/simple_animal_freeze.dm b/code/modules/unit_tests/simple_animal_freeze.dm index 2f4f7a4b70ae7..55161807eb46e 100644 --- a/code/modules/unit_tests/simple_animal_freeze.dm +++ b/code/modules/unit_tests/simple_animal_freeze.dm @@ -6,7 +6,6 @@ // If you are refactoring a simple_animal, REMOVE it from this list var/list/allowed_types = list( /mob/living/simple_animal/bot, - /mob/living/simple_animal/bot/floorbot, /mob/living/simple_animal/bot/mulebot, /mob/living/simple_animal/bot/mulebot/paranormal, /mob/living/simple_animal/bot/secbot, diff --git a/code/modules/uplink/uplink_items.dm b/code/modules/uplink/uplink_items.dm index 0d347709536ee..77eaeba11140f 100644 --- a/code/modules/uplink/uplink_items.dm +++ b/code/modules/uplink/uplink_items.dm @@ -200,6 +200,14 @@ /datum/uplink_item/proc/can_be_bought(datum/uplink_handler/source) return TRUE +///Real cost if this item, accounting for progression_points if uplink_handler has_progression is TRUE +/datum/uplink_item/proc/real_cost(datum/uplink_handler/source) + if (progression_minimum <= 0 || !source?.has_progression) + return cost + var percentage = CLAMP01(source.progression_points / progression_minimum) + var mult = (1 - percentage) * 3 + percentage * 1 + return ceil(cost * mult) + /datum/uplink_category/discounts name = "Discounted Gear" weight = -1 @@ -217,9 +225,13 @@ category = /datum/uplink_category/discounts purchasable_from = parent_type::purchasable_from & ~UPLINK_SPY // Probably not necessary but just in case +/datum/uplink_category/objective_special + name = "Objective-Specific Equipment" + weight = -3 + // Special equipment (Dynamically fills in uplink component) /datum/uplink_item/special_equipment - category = "Objective-Specific Equipment" + category = /datum/uplink_category/objective_special name = "Objective-Specific Equipment" desc = "Equipment necessary for accomplishing specific objectives. If you are seeing this, something has gone wrong." limited_stock = 1 diff --git a/code/modules/uplink/uplink_items/bundle.dm b/code/modules/uplink/uplink_items/bundle.dm index b6cdc2fd3d657..eac30c41a16c2 100644 --- a/code/modules/uplink/uplink_items/bundle.dm +++ b/code/modules/uplink/uplink_items/bundle.dm @@ -89,28 +89,26 @@ continue if(!uplink_item.surplus) continue - if(handler.not_enough_reputation(uplink_item)) - continue possible_items += uplink_item return possible_items /// picks items from the list given to proc and generates a valid uplink item that is less or equal to the amount of TC it can spend -/datum/uplink_item/bundles_tc/surplus/proc/pick_possible_item(list/possible_items, tc_budget) +/datum/uplink_item/bundles_tc/surplus/proc/pick_possible_item(list/possible_items, tc_budget, datum/uplink_handler/handler) var/datum/uplink_item/uplink_item = pick(possible_items) if(prob(100 - uplink_item.surplus)) return null - if(tc_budget < uplink_item.cost) + if(tc_budget < uplink_item.real_cost(handler)) return null return uplink_item /// fills the crate that will be given to the traitor, edit this to change the crate and how the item is filled -/datum/uplink_item/bundles_tc/surplus/proc/fill_crate(obj/structure/closet/crate/surplus_crate, list/possible_items) +/datum/uplink_item/bundles_tc/surplus/proc/fill_crate(obj/structure/closet/crate/surplus_crate, list/possible_items, datum/uplink_handler/handler) var/tc_budget = crate_tc_value while(tc_budget) - var/datum/uplink_item/uplink_item = pick_possible_item(possible_items, tc_budget) + var/datum/uplink_item/uplink_item = pick_possible_item(possible_items, tc_budget, handler) if(!uplink_item) continue - tc_budget -= uplink_item.cost + tc_budget -= uplink_item.real_cost(handler) new uplink_item.item(surplus_crate) /// overwrites item spawning proc for surplus items to spawn an appropriate crate via a podspawn @@ -142,7 +140,7 @@ crate_type = /obj/structure/closet/crate/secure/syndicrate /// edited version of fill crate for super surplus to ensure it can only be unlocked with the syndicrate key -/datum/uplink_item/bundles_tc/surplus/united/fill_crate(obj/structure/closet/crate/secure/syndicrate/surplus_crate, list/possible_items) +/datum/uplink_item/bundles_tc/surplus/united/fill_crate(obj/structure/closet/crate/secure/syndicrate/surplus_crate, list/possible_items, datum/uplink_handler/handler) if(!istype(surplus_crate)) return var/tc_budget = crate_tc_value @@ -150,7 +148,7 @@ var/datum/uplink_item/uplink_item = pick_possible_item(possible_items, tc_budget) if(!uplink_item) continue - tc_budget -= uplink_item.cost + tc_budget -= uplink_item.real_cost(handler) surplus_crate.unlock_contents += uplink_item.item /datum/uplink_item/bundles_tc/surplus_key diff --git a/code/modules/uplink/uplink_items/device_tools.dm b/code/modules/uplink/uplink_items/device_tools.dm index 714c3133482c4..ef2ab6fd1fddc 100644 --- a/code/modules/uplink/uplink_items/device_tools.dm +++ b/code/modules/uplink/uplink_items/device_tools.dm @@ -242,9 +242,9 @@ active gravitational singularities or tesla balls towards it. This will not work when the engine is still \ in containment. Because of its size, it cannot be carried. Ordering this \ sends you a small beacon that will teleport the larger beacon to your location upon activation." - progression_minimum = 30 MINUTES + progression_minimum = 20 MINUTES item = /obj/item/sbeacondrop - cost = 10 + cost = 4 surplus = 0 // not while there isnt one on any station purchasable_from = ~UPLINK_ALL_SYNDIE_OPS diff --git a/code/modules/vehicles/mecha/combat/durand.dm b/code/modules/vehicles/mecha/combat/durand.dm index 0e1ab1302db91..da1f7122dd14a 100644 --- a/code/modules/vehicles/mecha/combat/durand.dm +++ b/code/modules/vehicles/mecha/combat/durand.dm @@ -35,8 +35,6 @@ . = ..() shield = new /obj/durand_shield(loc, src, plane, layer, dir) RegisterSignal(src, COMSIG_MECHA_ACTION_TRIGGER, PROC_REF(relay)) - RegisterSignal(src, COMSIG_PROJECTILE_PREHIT, PROC_REF(prehit)) - /obj/vehicle/sealed/mecha/durand/Destroy() if(shield) @@ -84,10 +82,12 @@ shield.setDir(dir) //Redirects projectiles to the shield if defense_check decides they should be blocked and returns true. -/obj/vehicle/sealed/mecha/durand/proc/prehit(obj/projectile/source, list/signal_args) - SIGNAL_HANDLER +/obj/vehicle/sealed/mecha/durand/bullet_act(obj/projectile/source, def_zone, mode) if(defense_check(source.loc) && shield) - signal_args[2] = shield + return shield.bullet_act(source, def_zone, mode) + return ..() + + /**Checks if defense mode is enabled, and if the attacker is standing in an area covered by the shield. Expects a turf. Returns true if the attack should be blocked, false if not.*/ diff --git a/code/modules/vehicles/mecha/equipment/tools/medical_tools.dm b/code/modules/vehicles/mecha/equipment/tools/medical_tools.dm index e1c37a3d13a7f..329ade4f377c6 100644 --- a/code/modules/vehicles/mecha/equipment/tools/medical_tools.dm +++ b/code/modules/vehicles/mecha/equipment/tools/medical_tools.dm @@ -15,82 +15,33 @@ if(!chassis) return PROCESS_KILL -/obj/item/mecha_parts/mecha_equipment/medical/sleeper +/obj/item/mecha_parts/mecha_equipment/proc/get_reagent_data(list/datum/reagent/reagent_list) + var/list/contained_reagents = list() + if(length(reagent_list)) + for(var/datum/reagent/reagent as anything in reagent_list) + contained_reagents += list(list("name" = reagent.name, "volume" = round(reagent.volume, 0.01))) // list in a list because Byond merges the first list... + return contained_reagents + +//---- Mecha sleeper, medical subtype has the chemical functionality +/obj/item/mecha_parts/mecha_equipment/sleeper name = "mounted sleeper" - desc = "Equipment for medical exosuits. A mounted sleeper that stabilizes patients and can inject reagents from a equipped exosuit syringe gun." - icon_state = "mecha_sleeper" + desc = "A mounted sleeper that stabilizes patients." + icon_state = "mecha_sleeper_miner" energy_drain = 20 range = MECHA_MELEE equip_cooldown = 20 /// ref to the patient loaded in the sleeper var/mob/living/carbon/patient - /// amount of chems to inject into patient from other hands syringe gun - var/inject_amount = 10 -/obj/item/mecha_parts/mecha_equipment/medical/sleeper/Destroy() +/obj/item/mecha_parts/mecha_equipment/sleeper/Destroy() for(var/atom/movable/content as anything in src) content.forceMove(get_turf(src)) return ..() -/obj/item/mecha_parts/mecha_equipment/medical/proc/get_reagent_data(list/datum/reagent/reagent_list) - var/list/contained_reagents = list() - if(length(reagent_list)) - for(var/datum/reagent/reagent as anything in reagent_list) - contained_reagents += list(list("name" = reagent.name, "volume" = round(reagent.volume, 0.01))) // list in a list because Byond merges the first list... - return contained_reagents - -/obj/item/mecha_parts/mecha_equipment/medical/sleeper/get_snowflake_data() - var/list/data = list("snowflake_id" = MECHA_SNOWFLAKE_ID_SLEEPER) - if(isnull(patient)) - return data - var/patient_state - switch(patient.stat) - if(0) - patient_state = "Conscious" - if(1) - patient_state = "Unconscious" - if(2) - patient_state = "*dead*" - else - patient_state = "Unknown" - var/core_temp = "" - if(ishuman(patient)) - var/mob/living/carbon/human/humi = patient - core_temp = humi.bodytemperature-T0C - data["patient"] = list( - "patient_name" = patient.name, - "patient_health" = patient.health/patient.maxHealth, - "patient_state" = patient_state, - "core_temp" = core_temp, - "brute_loss" = patient.getBruteLoss(), - "burn_loss" = patient.getFireLoss(), - "toxin_loss" = patient.getToxLoss(), - "oxygen_loss" = patient.getOxyLoss(), - ) - data["has_brain_damage"] = patient.get_organ_loss(ORGAN_SLOT_BRAIN) != 0 - data["has_traumas"] = length(patient.get_traumas()) != 0 - data["contained_reagents"] = get_reagent_data(patient.reagents.reagent_list) - - var/obj/item/mecha_parts/mecha_equipment/medical/syringe_gun/shooter = locate(/obj/item/mecha_parts/mecha_equipment/medical/syringe_gun) in chassis - if(shooter) - data["injectible_reagents"] = get_reagent_data(shooter.reagents.reagent_list) - return data - -/obj/item/mecha_parts/mecha_equipment/medical/sleeper/handle_ui_act(action, list/params) - switch(action) - if("eject") - go_out() - return TRUE - var/obj/item/mecha_parts/mecha_equipment/medical/syringe_gun/shooter = locate() in chassis - if(shooter) - for(var/datum/reagent/medication in shooter.reagents.reagent_list) - if(action == ("inject_reagent_" + medication.name)) - inject_reagent(medication, shooter) - break // or maybe return TRUE? i'm not certain - - return FALSE +/obj/item/mecha_parts/mecha_equipment/sleeper/container_resist_act(mob/living/user) + go_out() -/obj/item/mecha_parts/mecha_equipment/medical/sleeper/action(mob/source, atom/atomtarget, list/modifiers) +/obj/item/mecha_parts/mecha_equipment/sleeper/action(mob/source, atom/atomtarget, list/modifiers) if(!action_checks(atomtarget)) return if(!iscarbon(atomtarget)) @@ -112,7 +63,7 @@ log_message("[target] loaded. Life support functions engaged.", LOG_MECHA) return ..() -/obj/item/mecha_parts/mecha_equipment/medical/sleeper/proc/patient_insertion_check(mob/living/carbon/target, mob/user) +/obj/item/mecha_parts/mecha_equipment/sleeper/proc/patient_insertion_check(mob/living/carbon/target, mob/user) if(!isnull(target.buckled)) to_chat(user, "[icon2html(src, user)][span_warning("[target] will not fit into the sleeper because [target.p_theyre()] buckled to [target.buckled]!")]") return FALSE @@ -124,7 +75,7 @@ return FALSE return TRUE -/obj/item/mecha_parts/mecha_equipment/medical/sleeper/proc/go_out() +/obj/item/mecha_parts/mecha_equipment/sleeper/proc/go_out() if(!patient) return patient.forceMove(get_turf(src)) @@ -133,31 +84,56 @@ STOP_PROCESSING(SSobj, src) patient = null -/obj/item/mecha_parts/mecha_equipment/medical/sleeper/detach() +/obj/item/mecha_parts/mecha_equipment/sleeper/detach() if(patient) to_chat(chassis.occupants, "[icon2html(src, chassis.occupants)][span_warning("Unable to detach [src] - equipment occupied!")]") return STOP_PROCESSING(SSobj, src) return ..() -/obj/item/mecha_parts/mecha_equipment/medical/sleeper/proc/inject_reagent(datum/reagent/R, obj/item/mecha_parts/mecha_equipment/medical/syringe_gun/SG) - if(!R || !patient || !SG || !(SG in chassis.flat_equipment)) - return - var/to_inject = min(R.volume, inject_amount) - if(to_inject && patient.reagents.get_reagent_amount(R.type) + to_inject <= inject_amount*2) - to_chat(chassis.occupants, "[icon2html(src, chassis.occupants)][span_notice("Injecting [patient] with [to_inject] units of [R.name].")]") - log_message("Injecting [patient] with [to_inject] units of [R.name].", LOG_MECHA) - for(var/driver in chassis.return_drivers()) - log_combat(driver, patient, "injected", "[name] ([R] - [to_inject] units)") - SG.reagents.trans_to(patient, to_inject, target_id = R.type) +/obj/item/mecha_parts/mecha_equipment/sleeper/get_snowflake_data() + var/list/data = list("snowflake_id" = MECHA_SNOWFLAKE_ID_SLEEPER) + if(isnull(patient)) + return data + var/patient_state + switch(patient.stat) + if(CONSCIOUS) + patient_state = "Conscious" + if(UNCONSCIOUS) + patient_state = "Unconscious" + if(DEAD) + patient_state = "*Dead*" + if(SOFT_CRIT, HARD_CRIT) + patient_state = "Critical" + else + patient_state = "Unknown" + var/core_temp = "" + if(ishuman(patient)) + var/mob/living/carbon/human/humi = patient + core_temp = humi.bodytemperature-T0C + data["patient"] = list( + "patient_name" = patient.name, + "patient_health" = patient.health/patient.maxHealth, + "patient_state" = patient_state, + "core_temp" = core_temp, + "brute_loss" = patient.getBruteLoss(), + "burn_loss" = patient.getFireLoss(), + "toxin_loss" = patient.getToxLoss(), + "oxygen_loss" = patient.getOxyLoss(), + ) + data["contained_reagents"] = get_reagent_data(patient.reagents.reagent_list) + data["has_brain_damage"] = patient.get_organ_loss(ORGAN_SLOT_BRAIN) != 0 + data["has_traumas"] = length(patient.get_traumas()) != 0 -/obj/item/mecha_parts/mecha_equipment/medical/sleeper/container_resist_act(mob/living/user) - go_out() + return data -/obj/item/mecha_parts/mecha_equipment/medical/sleeper/process(seconds_per_tick) - . = ..() - if(.) - return +/obj/item/mecha_parts/mecha_equipment/sleeper/handle_ui_act(action, list/params) + if(action == "eject") + go_out() + return TRUE + return FALSE + +/obj/item/mecha_parts/mecha_equipment/sleeper/process(seconds_per_tick) if(!chassis.has_charge(energy_drain)) log_message("Deactivated.", LOG_MECHA) to_chat(chassis.occupants, "[icon2html(src, chassis.occupants)][span_warning("[src] deactivated - no power.")]") @@ -171,17 +147,59 @@ log_message("[patient] no longer detected - Life support functions disabled.", LOG_MECHA) STOP_PROCESSING(SSobj, src) patient = null - if(ex_patient.health > 0) - ex_patient.adjustOxyLoss(-0.5 * seconds_per_tick) + ex_patient.adjustOxyLoss(-2 * seconds_per_tick) ex_patient.AdjustStun(-40 * seconds_per_tick) ex_patient.AdjustKnockdown(-40 * seconds_per_tick) ex_patient.AdjustParalyzed(-40 * seconds_per_tick) ex_patient.AdjustImmobilized(-40 * seconds_per_tick) ex_patient.AdjustUnconscious(-40 * seconds_per_tick) - if(ex_patient.reagents.get_reagent_amount(/datum/reagent/medicine/epinephrine) < 5) + if(ex_patient.reagents.get_reagent_amount(/datum/reagent/medicine/epinephrine) < 5 \ + && ex_patient.reagents.get_reagent_amount(/datum/reagent/medicine/c2/penthrite) <= 0 \ + && ex_patient.stat >= SOFT_CRIT) ex_patient.reagents.add_reagent(/datum/reagent/medicine/epinephrine, 5) + if(ex_patient.reagents.get_reagent_amount(/datum/reagent/toxin/formaldehyde) <= 0 && ex_patient.stat == DEAD) + ex_patient.reagents.add_reagent(/datum/reagent/toxin/formaldehyde, 3) chassis.use_energy(energy_drain) +//Medical subtype with the chems +/obj/item/mecha_parts/mecha_equipment/sleeper/medical + name = "mounted sleeper" + desc = "Equipment for medical exosuits. A mounted sleeper that stabilizes patients and can inject reagents from a equipped exosuit syringe gun." + icon_state = "mecha_sleeper" + mech_flags = EXOSUIT_MODULE_MEDICAL + /// amount of chems to inject into patient from other hands syringe gun + var/inject_amount = 10 + +/obj/item/mecha_parts/mecha_equipment/sleeper/medical/get_snowflake_data() + var/list/data = ..() + if(isnull(patient)) + return data + var/obj/item/mecha_parts/mecha_equipment/medical/syringe_gun/shooter = locate(/obj/item/mecha_parts/mecha_equipment/medical/syringe_gun) in chassis + if(shooter) + data["injectible_reagents"] = get_reagent_data(shooter.reagents.reagent_list) + return data + +/obj/item/mecha_parts/mecha_equipment/sleeper/medical/handle_ui_act(action, list/params) + . = ..() + if(.) + return TRUE + var/obj/item/mecha_parts/mecha_equipment/medical/syringe_gun/shooter = locate() in chassis + if(shooter) + for(var/datum/reagent/medication as anything in shooter.reagents.reagent_list) + if(action == ("inject_reagent_" + medication.name)) + inject_reagent(medication, shooter) + break // or maybe return TRUE? i'm not certain + +/obj/item/mecha_parts/mecha_equipment/sleeper/medical/proc/inject_reagent(datum/reagent/reagent_to_inject, obj/item/mecha_parts/mecha_equipment/medical/syringe_gun/SG) + if(!reagent_to_inject || !patient || !SG || !(SG in chassis.flat_equipment)) + return + var/to_inject = min(reagent_to_inject.volume, inject_amount) + if(to_inject && patient.reagents.get_reagent_amount(reagent_to_inject.type) + to_inject <= inject_amount*2) + to_chat(chassis.occupants, "[icon2html(src, chassis.occupants)][span_notice("Injecting [patient] with [to_inject] units of [reagent_to_inject.name].")]") + log_message("Injecting [patient] with [to_inject] units of [reagent_to_inject.name].", LOG_MECHA) + for(var/driver in chassis.return_drivers()) + log_combat(driver, patient, "injected", "[name] ([reagent_to_inject] - [to_inject] units)") + SG.reagents.trans_to(patient, to_inject, target_id = reagent_to_inject.type) ///////////////////////////////// Syringe Gun /////////////////////////////////////////////////////////////// diff --git a/code/modules/vehicles/mecha/equipment/tools/mining_tools.dm b/code/modules/vehicles/mecha/equipment/tools/mining_tools.dm index e08020a545f62..cdbf45362e41b 100644 --- a/code/modules/vehicles/mecha/equipment/tools/mining_tools.dm +++ b/code/modules/vehicles/mecha/equipment/tools/mining_tools.dm @@ -9,6 +9,9 @@ name = "exosuit drill" desc = "Equipment for engineering and combat exosuits. This is the drill that'll pierce the heavens!" icon_state = "mecha_drill" + equipment_slot = MECHA_UTILITY + can_be_toggled = TRUE + active = FALSE equip_cooldown = 15 energy_drain = 0.01 * STANDARD_CELL_CHARGE force = 15 @@ -32,6 +35,17 @@ ADD_TRAIT(src, TRAIT_INSTANTLY_PROCESSES_BOULDERS, INNATE_TRAIT) ADD_TRAIT(src, TRAIT_BOULDER_BREAKER, INNATE_TRAIT) +/obj/item/mecha_parts/mecha_equipment/drill/handle_ui_act(action, list/params) + if(action != "toggle") + return + if(active) + RegisterSignal(chassis, COMSIG_MECHA_MELEE_CLICK, PROC_REF(on_mech_click)) + log_message("Activated.", LOG_MECHA) + else + UnregisterSignal(chassis, COMSIG_MECHA_MELEE_CLICK) + log_message("Deactivated.", LOG_MECHA) + return TRUE + /obj/item/mecha_parts/mecha_equipment/drill/attach(obj/vehicle/sealed/mecha/new_mecha, attach_right) . = ..() RegisterSignal(chassis, COMSIG_MOVABLE_BUMP, PROC_REF(bump_mine)) @@ -64,6 +78,14 @@ return FALSE return ..() +///Redirects clicks to use the drill if possible when enabled +/obj/item/mecha_parts/mecha_equipment/drill/proc/on_mech_click(atom/mech, mob/source, atom/target, on_cooldown, adjacent) + SIGNAL_HANDLER + if(on_cooldown || !adjacent) + return + INVOKE_ASYNC(src, PROC_REF(action), source, target, null, FALSE) + return COMPONENT_CANCEL_MELEE_CLICK + /obj/item/mecha_parts/mecha_equipment/drill/action(mob/source, atom/target, list/modifiers, bumped) //If bumped, only bother drilling mineral turfs if(bumped) diff --git a/code/modules/vehicles/mecha/mech_fabricator.dm b/code/modules/vehicles/mecha/mech_fabricator.dm index 54f8cee9ed4c5..ad28886d99f22 100644 --- a/code/modules/vehicles/mecha/mech_fabricator.dm +++ b/code/modules/vehicles/mecha/mech_fabricator.dm @@ -10,6 +10,7 @@ subsystem_type = /datum/controller/subsystem/processing/fastprocess + interaction_flags_atom = parent_type::interaction_flags_atom | INTERACT_ATOM_MOUSEDROP_IGNORE_CHECKS /// Current items in the build queue. var/list/datum/design/queue = list() @@ -49,12 +50,15 @@ /// All designs in the techweb that can be fabricated by this machine, since the last update. var/list/datum/design/cached_designs - //looping sound for printing items + /// Looping sound for printing items var/datum/looping_sound/lathe_print/print_sound /// Local designs that only this mechfab have(using when mechfab emaged so it's illegal designs). var/list/datum/design/illegal_local_designs + /// Direction the produced items will drop (0 means on top of us) + var/drop_direction = SOUTH + /obj/machinery/mecha_part_fabricator/Initialize(mapload) print_sound = new(src, FALSE) rmat = AddComponent(/datum/component/remote_materials, mapload && link_on_init) @@ -136,15 +140,19 @@ . = ..() if(in_range(user, src) || isobserver(user)) . += span_notice("The status display reads: Storing up to [rmat.local_size] material units.
Material consumption at [component_coeff*100]%.
Build time reduced by [100-time_coeff*100]%.") - if(panel_open) - . += span_notice("Alt-click to rotate the output direction.") + . += span_notice("Currently configured to drop printed objects [dir2text(drop_direction)].") -/obj/machinery/mecha_part_fabricator/click_alt(mob/user) - if(!panel_open) - return CLICK_ACTION_BLOCKING - dir = turn(dir, -90) - balloon_alert(user, "rotated to [dir2text(dir)].") - return CLICK_ACTION_SUCCESS +/obj/machinery/mecha_part_fabricator/mouse_drop_dragged(atom/over, mob/user, src_location, over_location, params) + if(!can_interact(user) || (!HAS_SILICON_ACCESS(user) && !isAdminGhostAI(user)) && !Adjacent(user)) + return + if(being_built) + balloon_alert(user, "printing started!") + return + var/direction = get_dir(src, over_location) + if(!direction) + return + drop_direction = direction + balloon_alert(user, "dropping [dir2text(drop_direction)]") /obj/machinery/mecha_part_fabricator/emag_act(mob/user, obj/item/card/emag/emag_card) if(obj_flags & EMAGGED) @@ -267,7 +275,7 @@ /obj/machinery/mecha_part_fabricator/process() // If there's a stored part to dispense due to an obstruction, try to dispense it. if(stored_part) - var/turf/exit = get_step(src,(dir)) + var/turf/exit = get_step(src, drop_direction) if(exit.density) return TRUE @@ -305,7 +313,7 @@ being_built = null - var/turf/exit = get_step(src,(dir)) + var/turf/exit = get_step(src, drop_direction) if(exit.density) say("Error! The part outlet is obstructed.") desc = "It's trying to dispense the fabricated [dispensed_design.name], but the part outlet is obstructed." diff --git a/code/modules/vehicles/mecha/mecha_construction_paths.dm b/code/modules/vehicles/mecha/mecha_construction_paths.dm index 0a305a5db66ae..a8a7c224491a2 100644 --- a/code/modules/vehicles/mecha/mecha_construction_paths.dm +++ b/code/modules/vehicles/mecha/mecha_construction_paths.dm @@ -416,10 +416,10 @@ circuit_control = /obj/item/circuitboard/mecha/clarke/main circuit_periph = /obj/item/circuitboard/mecha/clarke/peripherals - inner_plating = /obj/item/stack/sheet/plasteel + inner_plating = /obj/item/stack/sheet/iron inner_plating_amount = 5 - outer_plating = /obj/item/stack/sheet/mineral/gold + outer_plating = /obj/item/stack/sheet/plasteel outer_plating_amount = 5 /datum/component/construction/mecha/clarke/get_frame_steps() diff --git a/code/modules/vehicles/mecha/mecha_movement.dm b/code/modules/vehicles/mecha/mecha_movement.dm index a4b21190a1ec3..130e0e807b438 100644 --- a/code/modules/vehicles/mecha/mecha_movement.dm +++ b/code/modules/vehicles/mecha/mecha_movement.dm @@ -139,6 +139,8 @@ // if we're not strafing or if we are forced to rotate or if we are holding down the key if(dir != direction && (!strafe || forcerotate || keyheld)) setDir(direction) + if(!(mecha_flags & QUIET_TURNS)) + playsound(src, turnsound, 40, TRUE) if(keyheld || !pivot_step) //If we pivot step, we don't return here so we don't just come to a stop return TRUE @@ -146,10 +148,6 @@ //Otherwise just walk normally . = try_step_multiz(direction) - //dir and olddir are the current direction of the sprite and the old direction of the sprite respectively - if (dir != olddir && !(mecha_flags & QUIET_TURNS)) - playsound(src, turnsound, 40, TRUE) - if(phasing) use_energy(phasing_energy_drain) if(strafe) diff --git a/code/modules/vehicles/mecha/working/clarke.dm b/code/modules/vehicles/mecha/working/clarke.dm index 8ccee945ed26e..1ecf4a9a831bc 100644 --- a/code/modules/vehicles/mecha/working/clarke.dm +++ b/code/modules/vehicles/mecha/working/clarke.dm @@ -1,11 +1,11 @@ -///Lavaproof, fireproof, fast mech with low armor and higher energy consumption, cannot strafe and has an internal ore box. +///Lavaproof, fireproof, fast mech with low armor and higher energy consumption and has an internal ore box. /obj/vehicle/sealed/mecha/clarke - desc = "Combining man and machine for a better, stronger engineer. Can even resist lava!" + desc = "Combining man and machine for a better, stronger miner, Cannot strafe Can even resist lava!" name = "\improper Clarke" icon_state = "clarke" base_icon_state = "clarke" max_temperature = 65000 - max_integrity = 200 + max_integrity = 250 movedelay = 1.25 overclock_coeff = 1.25 resistance_flags = LAVA_PROOF | FIRE_PROOF | ACID_PROOF @@ -15,14 +15,14 @@ equip_by_category = list( MECHA_L_ARM = null, MECHA_R_ARM = null, - MECHA_UTILITY = list(/obj/item/mecha_parts/mecha_equipment/orebox_manager), + MECHA_UTILITY = list(/obj/item/mecha_parts/mecha_equipment/orebox_manager, /obj/item/mecha_parts/mecha_equipment/sleeper/clarke), MECHA_POWER = list(), MECHA_ARMOR = list(), ) max_equip_by_category = list( MECHA_L_ARM = 1, MECHA_R_ARM = 1, - MECHA_UTILITY = 5, + MECHA_UTILITY = 6, MECHA_POWER = 1, MECHA_ARMOR = 1, ) @@ -35,7 +35,7 @@ pivot_step = TRUE /datum/armor/mecha_clarke - melee = 20 + melee = 40 bullet = 10 laser = 20 energy = 10 @@ -55,13 +55,14 @@ /obj/vehicle/sealed/mecha/clarke/generate_actions() . = ..() initialize_passenger_action_type(/datum/action/vehicle/sealed/mecha/mech_search_ruins) + initialize_passenger_action_type(/datum/action/vehicle/sealed/mecha/clarke_scoop_body) //Ore Box Controls ///Special equipment for the Clarke mech, handles moving ore without giving the mech a hydraulic clamp and cargo compartment. /obj/item/mecha_parts/mecha_equipment/orebox_manager name = "ore storage module" - desc = "An automated ore box management device." + desc = "An automated ore box management device, complete with a built-in boulder processor." icon_state = "mecha_bin" equipment_slot = MECHA_UTILITY detachable = FALSE @@ -109,6 +110,26 @@ log_message("Dumped [cached_ore_box].", LOG_MECHA) return TRUE +/obj/item/mecha_parts/mecha_equipment/sleeper/clarke //The Clarke subtype of the sleeper is a built-in utility module + equipment_slot = MECHA_UTILITY + detachable = FALSE + +/datum/action/vehicle/sealed/mecha/clarke_scoop_body + name = "Pick up body" + desc = "Activate to pick up a nearby body" + button_icon = 'icons/obj/devices/mecha_equipment.dmi' + button_icon_state = "mecha_sleeper_miner" + +/datum/action/vehicle/sealed/mecha/clarke_scoop_body/Trigger(trigger_flags) + var/obj/item/mecha_parts/mecha_equipment/sleeper/clarke/sleeper = locate() in chassis + var/mob/living/carbon/human/human_target + for(var/mob/living/carbon/human/body in range(1, chassis)) + if(chassis.is_driver(body) || !ishuman(body) || !chassis.Adjacent(body)) + continue + human_target = body //Non-driver, human, and adjacent + break + sleeper.action(pick(chassis.return_drivers()), human_target) //This will probably break if anyone allows multiple drivers of the Clarke mech + #define SEARCH_COOLDOWN (1 MINUTES) /datum/action/vehicle/sealed/mecha/mech_search_ruins diff --git a/code/modules/vehicles/secway.dm b/code/modules/vehicles/secway.dm index 6726fb02ef150..ab366da4b283e 100644 --- a/code/modules/vehicles/secway.dm +++ b/code/modules/vehicles/secway.dm @@ -101,5 +101,5 @@ if(!buckled_mobs || prob(40)) return ..() for(var/mob/rider as anything in buckled_mobs) - rider.bullet_act(P) - return TRUE + return rider.bullet_act(P) + return ..() diff --git a/code/modules/vending/wardrobes.dm b/code/modules/vending/wardrobes.dm index 8be4c15851b40..cbc2fa73185cf 100644 --- a/code/modules/vending/wardrobes.dm +++ b/code/modules/vending/wardrobes.dm @@ -479,12 +479,6 @@ GLOBAL_VAR_INIT(roaches_deployed, FALSE) /obj/item/plunger = 2, /obj/item/wirebrush = 2, /obj/item/radio/headset/headset_srv = 2, - /obj/item/clothing/head/hats/janitor_doppler = 3, - /obj/item/clothing/shoes/galoshes/doppler = 2, - /obj/item/clothing/gloves/botanic_leather/janitor = 3, - /obj/item/clothing/suit/apron/janitor_cloak = 3, - /obj/item/clothing/under/rank/civilian/janitor/doppler = 3, - /obj/item/clothing/under/rank/civilian/janitor/doppler_ct = 3, ) refill_canister = /obj/item/vending_refill/wardrobe/jani_wardrobe default_price = PAYCHECK_CREW diff --git a/code/modules/wiremod/components/action/laserpointer.dm b/code/modules/wiremod/components/action/laserpointer.dm index 0eb7f822db1ea..8693a5c1ab18b 100644 --- a/code/modules/wiremod/components/action/laserpointer.dm +++ b/code/modules/wiremod/components/action/laserpointer.dm @@ -11,8 +11,8 @@ /// The input port var/datum/port/input/target_input - var/datum/port/input/image_pixel_x = 0 - var/datum/port/input/image_pixel_y = 0 + var/datum/port/input/image_pixel_x + var/datum/port/input/image_pixel_y var/max_range = 7 diff --git a/code/modules/wiremod/components/admin/getvar.dm b/code/modules/wiremod/components/admin/getvar.dm index 2fe8f18b09e3d..e467963fe345b 100644 --- a/code/modules/wiremod/components/admin/getvar.dm +++ b/code/modules/wiremod/components/admin/getvar.dm @@ -45,7 +45,7 @@ output_value.set_datatype(expected_output_type.value) /obj/item/circuit_component/get_variable/input_received(datum/port/input/port) - var/atom/object = entity?.value + var/datum/object = entity?.value if(getvar_options.value == "Global") object = GLOB diff --git a/config/config.txt b/config/config.txt index 96a8c869f4c7c..510988803c616 100644 --- a/config/config.txt +++ b/config/config.txt @@ -9,6 +9,7 @@ $include resources.txt $include interviews.txt $include lua.txt $include auxtools.txt +$include map_vote.txt # You can use the @ character at the beginning of a config option to lock it from being edited in-game # Example usage: @@ -609,3 +610,9 @@ UPLOAD_LIMIT 524288 ## Restricts admin client uploads to the server, defined in bytes, default is 5MB UPLOAD_LIMIT_ADMIN 5242880 + +## Uncomment to allow admins with +DEBUG to start the byond-tracy profiler during the round. +#ALLOW_TRACY_START + +## Uncomment to allow admins with +DEBUG to queue the next round to run the byond-tracy profiler. +#ALLOW_TRACY_QUEUE diff --git a/config/game_options.txt b/config/game_options.txt index 239ec8d43e1b9..952a02651395a 100644 --- a/config/game_options.txt +++ b/config/game_options.txt @@ -514,6 +514,9 @@ MAXFINE 2000 ## How many played hours of DRONE_REQUIRED_ROLE required to be a Maintenance Done #DRONE_ROLE_PLAYTIME 14 +## Will drones be restricted from interacting with the supermatter and atmopherics area? +#DRONE_AREA_INTERACTION_RESTRICT 1 + ## Whether native FoV is enabled for all people. #NATIVE_FOV diff --git a/html/changelogs/AutoChangeLog-pr-87773.yml b/html/changelogs/AutoChangeLog-pr-87773.yml deleted file mode 100644 index beb2605ec2748..0000000000000 --- a/html/changelogs/AutoChangeLog-pr-87773.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "Holoo-1" -delete-after: True -changes: - - bugfix: "fixed roundstart borgs not being synced to ai" \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-87818.yml b/html/changelogs/AutoChangeLog-pr-87818.yml deleted file mode 100644 index 84037f8dcd987..0000000000000 --- a/html/changelogs/AutoChangeLog-pr-87818.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "Ghommie" -delete-after: True -changes: - - bugfix: "Fixed special DNA infusions from squids and pufferfish." \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-87819.yml b/html/changelogs/AutoChangeLog-pr-87819.yml deleted file mode 100644 index 5e7cfe01c003d..0000000000000 --- a/html/changelogs/AutoChangeLog-pr-87819.yml +++ /dev/null @@ -1,5 +0,0 @@ -author: "Ghommie" -delete-after: True -changes: - - bugfix: "Fixed bombing non-turfs fishing spots not spawning loot correctly." - - balance: "Explosive bombing no longer spawns bottled messages/photos." \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-87825.yml b/html/changelogs/AutoChangeLog-pr-87825.yml deleted file mode 100644 index 15258c679ad04..0000000000000 --- a/html/changelogs/AutoChangeLog-pr-87825.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "Ghommie" -delete-after: True -changes: - - bugfix: "Fixed fish not being able to reproduce with other fish of the same type without the crossbreeding trait." \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-87827.yml b/html/changelogs/AutoChangeLog-pr-87827.yml deleted file mode 100644 index 153c3581b473c..0000000000000 --- a/html/changelogs/AutoChangeLog-pr-87827.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "Ghommie" -delete-after: True -changes: - - bugfix: "Fixed fish still being hungry when fed if in aquarium with the 'growth and reproduction' option disabled." \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-87832.yml b/html/changelogs/AutoChangeLog-pr-87832.yml deleted file mode 100644 index 4ebb0e20d35a8..0000000000000 --- a/html/changelogs/AutoChangeLog-pr-87832.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "SmArtKar" -delete-after: True -changes: - - bugfix: "Xenobio console puts sucked up slimes into stasis so they no longer split up inside" \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-87834.yml b/html/changelogs/AutoChangeLog-pr-87834.yml deleted file mode 100644 index 8a0ada8f2cd2d..0000000000000 --- a/html/changelogs/AutoChangeLog-pr-87834.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "harryob" -delete-after: True -changes: - - bugfix: "certain tgui inputs no longer require 2 clicks to open" \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-87835.yml b/html/changelogs/AutoChangeLog-pr-87835.yml deleted file mode 100644 index ab2ded648b722..0000000000000 --- a/html/changelogs/AutoChangeLog-pr-87835.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "sqnztb" -delete-after: True -changes: - - map: "tramstation tool storage trash no longer routes to the barber shop" \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-87836.yml b/html/changelogs/AutoChangeLog-pr-87836.yml deleted file mode 100644 index dcac7fdd74dd8..0000000000000 --- a/html/changelogs/AutoChangeLog-pr-87836.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "Goat" -delete-after: True -changes: - - qol: "You can now examine labelers to tell how many more labels it has." \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-87837.yml b/html/changelogs/AutoChangeLog-pr-87837.yml deleted file mode 100644 index 96a44be2edb83..0000000000000 --- a/html/changelogs/AutoChangeLog-pr-87837.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "tmyqlfpir" -delete-after: True -changes: - - bugfix: "Airlock shells are properly assigned circuit cameras modules" \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-87838.yml b/html/changelogs/AutoChangeLog-pr-87838.yml deleted file mode 100644 index 6e8027cf19a73..0000000000000 --- a/html/changelogs/AutoChangeLog-pr-87838.yml +++ /dev/null @@ -1,5 +0,0 @@ -author: "Neocloudy" -delete-after: True -changes: - - bugfix: "examine tags now use regex for checking if a tag has \"and\" in it" - - spellcheck: "the tooltip for the morbid examine tag doesn't try to use html anymore" \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-87839.yml b/html/changelogs/AutoChangeLog-pr-87839.yml deleted file mode 100644 index 43aafa3b23640..0000000000000 --- a/html/changelogs/AutoChangeLog-pr-87839.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "Rhials" -delete-after: True -changes: - - qol: "Makes some minor updates to Runtimestation, including event spawn points and a cargo bounty pad." \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-87840.yml b/html/changelogs/AutoChangeLog-pr-87840.yml deleted file mode 100644 index 2ce6d8d10d9c9..0000000000000 --- a/html/changelogs/AutoChangeLog-pr-87840.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "EmptyLullaby" -delete-after: True -changes: - - bugfix: "Goliath cloaks are no longer so hard on the calves that they force digitigrade legs to disable." \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-87841.yml b/html/changelogs/AutoChangeLog-pr-87841.yml deleted file mode 100644 index 83704f38ee57b..0000000000000 --- a/html/changelogs/AutoChangeLog-pr-87841.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "Goat" -delete-after: True -changes: - - qol: "Curator console's inventory screen will now update when you change pages or remove items." \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-87843.yml b/html/changelogs/AutoChangeLog-pr-87843.yml deleted file mode 100644 index 168494cd29b45..0000000000000 --- a/html/changelogs/AutoChangeLog-pr-87843.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "Goat" -delete-after: True -changes: - - map: "The library's scanner on Birdshot is now close enough to connect to the computer and was also given a book binder." \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-87845.yml b/html/changelogs/AutoChangeLog-pr-87845.yml deleted file mode 100644 index 9a9672e710500..0000000000000 --- a/html/changelogs/AutoChangeLog-pr-87845.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "timothymtorres" -delete-after: True -changes: - - bugfix: "Fix missing screentips plasmaman helmets and MOD suit hat stabilizer helmets." \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-87846.yml b/html/changelogs/AutoChangeLog-pr-87846.yml deleted file mode 100644 index 3423cb647db77..0000000000000 --- a/html/changelogs/AutoChangeLog-pr-87846.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "timothymtorres" -delete-after: True -changes: - - bugfix: "Fix broken link to issue manager guide in Github contributor guide" \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-87847.yml b/html/changelogs/AutoChangeLog-pr-87847.yml deleted file mode 100644 index b1290b19944e4..0000000000000 --- a/html/changelogs/AutoChangeLog-pr-87847.yml +++ /dev/null @@ -1,5 +0,0 @@ -author: "Absolucy" -delete-after: True -changes: - - bugfix: "You can no longer crush random unsuspecting people with vendors by ventcrawling while cursed." - - qol: "AFK players don't count as \"watchers\" for cursed stuff." \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-87849.yml b/html/changelogs/AutoChangeLog-pr-87849.yml deleted file mode 100644 index 394c7b39a0d9d..0000000000000 --- a/html/changelogs/AutoChangeLog-pr-87849.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "timothymtorres" -delete-after: True -changes: - - bugfix: "Fix holymelon armor not inheriting magic resistance" \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-87850.yml b/html/changelogs/AutoChangeLog-pr-87850.yml deleted file mode 100644 index b84618840865c..0000000000000 --- a/html/changelogs/AutoChangeLog-pr-87850.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "OrionTheFox" -delete-after: True -changes: - - bugfix: "(DeltaStation) Fixed unwired APCs in the Electronic Marketing Den, Abandoned Garden, Security Maintenance, and Private Investigator's Office" \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-87851.yml b/html/changelogs/AutoChangeLog-pr-87851.yml deleted file mode 100644 index e2c0c757c4ee3..0000000000000 --- a/html/changelogs/AutoChangeLog-pr-87851.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "SmArtKar" -delete-after: True -changes: - - bugfix: "Fixed hat stabilizer ignoring clothing worn_y_offset" \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-87852.yml b/html/changelogs/AutoChangeLog-pr-87852.yml deleted file mode 100644 index 50ad199495d90..0000000000000 --- a/html/changelogs/AutoChangeLog-pr-87852.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "SmArtKar" -delete-after: True -changes: - - bugfix: "Fixed basic mob performance impact created by the factorio PR" \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-87855.yml b/html/changelogs/AutoChangeLog-pr-87855.yml deleted file mode 100644 index e31cdb3c8d3a2..0000000000000 --- a/html/changelogs/AutoChangeLog-pr-87855.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "00-Steven" -delete-after: True -changes: - - bugfix: "Fixed auto-reel fishing line item catching logic." \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-87856.yml b/html/changelogs/AutoChangeLog-pr-87856.yml deleted file mode 100644 index df597780aa209..0000000000000 --- a/html/changelogs/AutoChangeLog-pr-87856.yml +++ /dev/null @@ -1,7 +0,0 @@ -author: "SyncIt21" -delete-after: True -changes: - - bugfix: "flatpacker accepts circuitboards with left click" - - bugfix: "rcd can deconstruct tables" - - bugfix: "you can open panels of destructive analyzers with screwdriver right click. Use right click or combat mode with items for default interactions" - - bugfix: "flatpacker & machines with local storage can be RPED'd again" \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-87902.yml b/html/changelogs/AutoChangeLog-pr-87902.yml new file mode 100644 index 0000000000000..fd16ccdeafb71 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-87902.yml @@ -0,0 +1,4 @@ +author: "mc-oofert" +delete-after: True +changes: + - qol: "alerts that do stuff when clicked glow gold" \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-88007.yml b/html/changelogs/AutoChangeLog-pr-88007.yml new file mode 100644 index 0000000000000..e0edf1ba61878 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-88007.yml @@ -0,0 +1,4 @@ +author: "SmArtKar" +delete-after: True +changes: + - bugfix: "Berets no longer make you go bald above your earline." \ No newline at end of file diff --git a/html/changelogs/archive/2024-11.yml b/html/changelogs/archive/2024-11.yml index dc1ca68e5f858..61fd21d9b4c51 100644 --- a/html/changelogs/archive/2024-11.yml +++ b/html/changelogs/archive/2024-11.yml @@ -401,3 +401,316 @@ grungussuss: - qol: you can now mitigate motion sickness from screen shake by enabling "darken screen shake" in preferences +2024-11-13: + 00-Steven: + - bugfix: Fixed auto-reel fishing line item catching logic. + Absolucy: + - bugfix: You can no longer crush random unsuspecting people with vendors by ventcrawling + while cursed. + - qol: AFK players don't count as "watchers" for cursed stuff. + EmptyLullaby: + - bugfix: Goliath cloaks are no longer so hard on the calves that they force digitigrade + legs to disable. + Ghommie: + - bugfix: Fixed special DNA infusions from squids and pufferfish. + - bugfix: Fixed fish still being hungry when fed if in aquarium with the 'growth + and reproduction' option disabled. + - bugfix: Fixed bombing non-turfs fishing spots not spawning loot correctly. + - balance: Explosive bombing no longer spawns bottled messages/photos. + - bugfix: Fixed fish not being able to reproduce with other fish of the same type + without the crossbreeding trait. + Goat: + - map: The library's scanner on Birdshot is now close enough to connect to the computer + and was also given a book binder. + - qol: Curator console's inventory screen will now update when you change pages + or remove items. + - qol: You can now examine labelers to tell how many more labels it has. + Holoo-1: + - bugfix: fixed roundstart borgs not being synced to ai + Neocloudy: + - bugfix: examine tags now use regex for checking if a tag has "and" in it + - spellcheck: the tooltip for the morbid examine tag doesn't try to use html anymore + OrionTheFox: + - bugfix: (DeltaStation) Fixed unwired APCs in the Electronic Marketing Den, Abandoned + Garden, Security Maintenance, and Private Investigator's Office + Rhials: + - qol: Makes some minor updates to Runtimestation, including event spawn points + and a cargo bounty pad. + SmArtKar: + - bugfix: Xenobio console puts sucked up slimes into stasis so they no longer split + up inside + - bugfix: Fixed basic mob performance impact created by the factorio PR + - bugfix: Fixed hat stabilizer ignoring clothing worn_y_offset + SyncIt21: + - bugfix: flatpacker accepts circuitboards with left click + - bugfix: rcd can deconstruct tables + - bugfix: you can open panels of destructive analyzers with screwdriver right click. + Use right click or combat mode with items for default interactions + - bugfix: flatpacker & machines with local storage can be RPED'd again + harryob: + - bugfix: ghosts observing ghosts can no longer click on their screen alerts + - bugfix: certain tgui inputs no longer require 2 clicks to open + sqnztb: + - map: tramstation tool storage trash no longer routes to the barber shop + timothymtorres: + - bugfix: Fix holymelon armor not inheriting magic resistance + - bugfix: Fix broken link to issue manager guide in Github contributor guide + - bugfix: Fix missing screentips plasmaman helmets and MOD suit hat stabilizer helmets. + tmyqlfpir: + - bugfix: Airlock shells are properly assigned circuit cameras modules +2024-11-14: + 00-Steven: + - bugfix: A bitrunner avatar spawning with the exact same name as a name currently + on the records no longer updates that record to match when the hacker alias + gets applied. + - qol: Net avatar ID cards use the net avatar's name instead of being generic. + Fikou: + - bugfix: a modsuit being deleted will delete its parts correctly + - bugfix: a modsuit needs its boots out to be moved by an AI + - qol: you can extend or retract a modsuits parts from the ui panel + - qol: modsuit cores have colorcoded charge bars in the ui panel + - qol: weapon recall module makes you pick up the weapon if its on your tile + - code_imp: tether module has its own button for cutting tethers instead of stealing + it from pins + - bugfix: armor booster doesnt protect from head injury without the helmet on + LT3: + - bugfix: Server config will now read the map vote configuration file + MTandi: + - qol: Chem dispenser UI droplets now have a shadow to not blend with the background + Majkl-J: + - qol: mech fabricator output direction can now be changed with a drag pull + Rhials: + - qol: Crayon bounties are less demanding, and require less crayons for payout. + SmArtKar: + - bugfix: Fixed ayylmao's brain examine lines + - bugfix: Fixed stingbangs using wrong sprites + - bugfix: Fixed detective action palette being invisible + SyncIt21: + - bugfix: holosign creators interact with storage items correctly + grungussuss: + - sound: party popper no longer makes reagent sloshing sounds + - sound: shoes pickup volume is louder now + mc-oofert: + - bugfix: meatlovers flatbread no longer tastes raw + timothymtorres: + - bugfix: Fix using chairs in holodeck to create infinite metal + xPokee, waterpig: + - code_imp: cleaned up beserk.dm +2024-11-15: + Absolucy: + - refactor: The ORM, "ore container", and order console UIs (produce, mining, bitrunner + vendors) now load icons in a more efficient manner. + - bugfix: Admin-deleting a mob now ghostizes it beforehand, preventing a runtime + error. + Ben10Omintrix: + - bugfix: fixes seedling ai getting stuck when trying to refill water from emptied + water tanks + Dawnseer: + - bugfix: removes the gas mask check for if the gas mask mouth is covered. Now it + only checks for filters and other cigs + GremlinSeeker: + - bugfix: Syndicate Biodome fixes + Majkl-J: + - bugfix: Fixes SSWardrobe stealing a camera from the camera app when on a dummy, + causing a harddel + Melbert: + - image: Speeds up some frames of the dust animation slightly + - image: Dust/remains spawned after being dusted are now aligned towards the bottom + of the tile + - image: Bigger mobs now produce bigger piles of ash + - image: Plasmamen now dust into plasma bones + SmArtKar: + - bugfix: Many years later, projectiles finally can pass through portals - this + time without crashing the server. + - bugfix: Fixed tenacity effect printing its messages when it shouldn't be, and + not removing its' effects when it should've. + - bugfix: Fixed scanner gates saying both bypass and detection lines when malfunctioning + SyncIt21: + - bugfix: Fixed visual glitches when inserting items from an slot other than the + hands into evidence bags & other storages that have quick gather mode enabled + - bugfix: silo connection on some machines won't time out when changing FPS settings + - code_imp: improved attack chain code for silo connection + Time-Green: + - bugfix: Nooartrium heart damage can no longer be bypassed with non-organic hearts + carlarctg: + - bugfix: you now snip cuffs with right click to prevent accidental cuts + - spellcheck: 'spellecheck: existence not existance' + - balance: Significantly buffed the anomalock modules. + - balance: Anomalock modules can be used with eachother. + - balance: Antigravity module costs 2 complexity. + - balance: Teleporter module is thrice as fast at teleporting with a slightly reduced + cooldown, but has a much larger power cost. + - code_imp: Changed how teleporter tracks maximum range to be less painful to the + end user. + - refactor: Refactored LoS checks to be a proc on atom, los_check + - balance: Kinesis module's default range has been extended to 8. + - balance: Kinesis module can drag around people in critical condition or worse. + - bugfix: vampires are a human subtype & have stomachs/lungs + grungussuss: + - sound: sandstone blocks have the correct sound now + - qol: added feedback for cutting mulebot wires + larentoun: + - bugfix: Fixes a runtime when wingless creature flaps their wings + mc-oofert: + - bugfix: Added dehydrator to birdshot kitchen. Surgery theatre now has a surgery + tray and surplus prosthetics. An unwired hallway APC is now wired. 1st SM filter + is now set to Nitrogen. Chemistry closet in pharmacy now contains extra chemicals + to compensate for not having a chemical storage. Atmos air for distro mixer + now mixes correctly + timothymtorres: + - balance: Lower the telecrystal price of the singularity beacon from 10 to 4 and + reduce the timer to 20 minutes before it can be purchased. + xPokee: + - bugfix: fixed brains turning invisible after being washed +2024-11-16: + Hardly: + - bugfix: Fixes watchers not attacking their targets in melee range + TheRealSpriteMan1337: + - spellcheck: Fixed some of the typos in computers' build & repair tips, adjusted + wording + Xander3359: + - bugfix: fix furious steel and blade ascension being jank + carlarctg: + - rscadd: Adds the Perceptomatrix Helm, a hallucination anomaly core item + zxaber: + - bugfix: Firelocks opened by a mech will correctly close when the mech moves out + of range. +2024-11-17: + Fikou: + - bugfix: xeno princesses no longer lose their unique identifier + JagOfTroy: + - bugfix: 'Fixed Automatic Announcement System bug with the Research Node Announcement + message not updating properly. It will now properly save and announce whatever + input the user desires! + + :cl:' + SmArtKar: + - rscdel: Removed N-Spect scanner's and scanner gate's ability to scan people for + contraband. + - bugfix: Fixed cats not begging people for food + - bugfix: Fixed a mixup in ripley plate sprites + - bugfix: Fixed tethers being able to move immovable objects (and delete gravgens) + - bugfix: Fixed a missing arg in fish release code causing runtimes + carlarctg: + - bugfix: '[no gbp] renmoves bartender skillchip from chipped quirk' + timothymtorres: + - bugfix: Fix radio jammer screentips +2024-11-18: + BurgerBB: + - qol: Reworks the Druggy visual effect to cause less eye strain. + EOBGames: + - rscadd: DONK CO. HAS UNVEILED A NEW RANGE OF READY-DONK PRODUCTS! GET THEM AT + CARGO TODAY! + - image: 'READY-DONK: NEW LOOK, SAME GREAT TASTE' + EnterTheJake: + - rscadd: New internal sleeper module for the Clarke. + - balance: Clarke Integrity has been bumped from 200 to 250 HP, melee armor bumped + from 20 to 40. + - balance: Exo mining module can now be used to scan vents and begin the wave defense + event. + - balance: The Clarke Ore Storage Module can now collect boulders and internally + smelt them. + - balance: Mech Pka is now bundled within the Clarke tech node, it now does more + damage and comes with the AOE upgrade preinstalled. + - balance: Exo mining drills are now a utility module rather than a weapon. + - balance: Applied Bluespace Research and Controlled Plasma tech nodes are no longer + hardlocked behind surveys, they instead favor from a discount if they are completed. + - bugfix: Fixes Exo Mech modules not granting life support to housed patients. + Ghommie: + - bugfix: You can no longer deploy survival/fishing capsules by the holodeck and + permanently brick it. + - balance: Tendril chests and mystery boxes can now be fished multiple times with + a 30 minutes cooldown. + - balance: other previously fishing loot available in limited amount, such as adamantine + and runite from plasma rivers, regenerate over time. + - rscadd: Using the gibber on people with fish tails now yield some fish tail fillets. + OrionTheFox: + - code_imp: The Greytide event will now play bolt audio and update the icon when + toggling door bolts. + Sothanforax: + - sound: Added sounds for the escape menu opening/closing/being open + TheBoondock: + - sound: added ignition and roaring fire sound to plasma/tritium fire + Vekter: + - map: Removes extra privacy shutters in the HoS' office on NebulaStation + Xackii: + - qol: heretic living heart now points to the target with an arrow. + - bugfix: pinpointer no longer breaks if scanned target disappears from our reality. + aaaa1023: + - bugfix: Birdshot Atmospherics now has an Air alarm + - bugfix: Birdshot Atmospherics pumping room APC is now connected to the main grid + - bugfix: Birdshot Port Primary Hallway APC is now connected to the main grid + carlarctg: + - bugfix: actually adds the perceptomatrix to the techweb + - bugfix: Reverts change that altered pyrokinesis recipe to require firebreath instead + of fiery sweat + grungussuss: + - sound: changed the welding hat toggle sfx + - qol: some hats now "compress" your hair to fit it the headwear better + - bugfix: xenos take more damage to husk + mc-oofert: + - bugfix: You may no longer use a climbing hook to phase through catwalks and such. + On the other hand, improved climbing hook aim and you may climb onto lattices + or catwalks + - balance: makes reputation locked gear instead be very very expensive and get cheaper + as you get to that rep + - bugfix: manufacturing sort-routers can no longer crawl + sqnztb: + - map: metastation's security mail chute no longer has an extra erroneous pipe. + thegrb93: + - bugfix: Fix broken cyborg inducer + timothymtorres: + - map: Fix missing CE Office Shutter Buttons on Icebox. Also removes a duplicate + keycard auth device. +2024-11-19: + Fikou: + - bugfix: Fixed chaplain divine archer outfit rolled down sprite + Jackal-boop: + - balance: syndicate GMO researchers have increased the effectiveness of their 'hot + potato' + carlarctg: + - qol: Improved fish lure descriptions to be easier to grok + fevryk: + - rscadd: Added new weapon carpenter hammer to black market uplink + - rscadd: Added killsound feature + tontyGH: + - bugfix: Haunted 8-balls are now usable again (FINALLY) + - bugfix: Haunted 8-ball UI now correctly displays your selected answer + - qol: Made the haunted 8-ball UI look a pinch better. Just a smidge. + - code_imp: Haunted 8-balls no longer use a duplicate answer list +2024-11-20: + Ben10Omintrix: + - refactor: floorbots have been refactored, please report any bugs + - rscadd: adds repairbots to the game! + Dawnseer: + - rscadd: Unleashed a great evil upon hoplines, in the form of a paperwork implant. + Dmeto: + - map: 'removes a unused disposal pipe from Cargo, fixes mining dock intercom. + + map:adds access helper to disposals south airlock.' + EnterTheJake: + - bugfix: FIxes insulated modsuits not granting full insulation. + Gaxeer: + - bugfix: AI controlled monkeys can again activate items in active hand + Hatterhat: + - bugfix: Crate Chaos's encrypted cache is now randomly placed again. + Jewelry-x: + - bugfix: changeling memories of victims no longer include `` and `
` + Melbert: + - balance: Having a broken arm affects your accuracy with ranged weapons fired with + that arm. Utilizing a painkiller will nullify this effect, however. + - balance: Painkillers will prevent your punches from being cancelled due to having + a broken arm. You'll still take damage, though. + - balance: Being drunk now affects your accuracy with ranged weapon. The bartender + is immune to this effect via their skillchip. + - code_imp: A lot of code involving left and right hand handling has been cleaned + up, easier to read. Report any oddities, like left and rights being flipped + grungussuss: + - bugfix: mobs can no longer hear their own breathing while deaf + - bugfix: a bug regarding orderable items has been fixed + - server: drone area restrictions are now config + - balance: drones now take less time to become "un-shy" of something after it's + been touched. + larentoun: + - bugfix: 'Mafia: Psych''s reveal ability now correctly has a single use' + - bugfix: 'Mafia: Fugitive''s vest ability now correctly should have two uses' diff --git a/icons/effects/96x96.dmi b/icons/effects/96x96.dmi index 38921a6e48402..83d7c14d0cc1b 100644 Binary files a/icons/effects/96x96.dmi and b/icons/effects/96x96.dmi differ diff --git a/icons/effects/beam.dmi b/icons/effects/beam.dmi index 85d450e03bdd6..41bdf992bbf41 100644 Binary files a/icons/effects/beam.dmi and b/icons/effects/beam.dmi differ diff --git a/icons/hud/64x16_actions.dmi b/icons/hud/64x16_actions.dmi index 812d888846ebd..23865a80f0354 100644 Binary files a/icons/hud/64x16_actions.dmi and b/icons/hud/64x16_actions.dmi differ diff --git a/icons/hud/screen_full.dmi b/icons/hud/screen_full.dmi index dfe3bd12091d9..be4571638b10f 100644 Binary files a/icons/hud/screen_full.dmi and b/icons/hud/screen_full.dmi differ diff --git a/icons/hud/screen_gen.dmi b/icons/hud/screen_gen.dmi index 5b1c24d7789cc..c38725e43e433 100644 Binary files a/icons/hud/screen_gen.dmi and b/icons/hud/screen_gen.dmi differ diff --git a/icons/mob/clothing/feet.dmi b/icons/mob/clothing/feet.dmi index 8a8c893577882..5ff2a5b792070 100644 Binary files a/icons/mob/clothing/feet.dmi and b/icons/mob/clothing/feet.dmi differ diff --git a/icons/mob/clothing/hands.dmi b/icons/mob/clothing/hands.dmi index 2f3161b0331a1..3eee250ca66d5 100644 Binary files a/icons/mob/clothing/hands.dmi and b/icons/mob/clothing/hands.dmi differ diff --git a/icons/mob/clothing/head/hats.dmi b/icons/mob/clothing/head/hats.dmi index 01ed2679f23b3..7f59060129712 100644 Binary files a/icons/mob/clothing/head/hats.dmi and b/icons/mob/clothing/head/hats.dmi differ diff --git a/icons/mob/clothing/head/helmet.dmi b/icons/mob/clothing/head/helmet.dmi index db48dda1fd61c..05fe660a33a29 100644 Binary files a/icons/mob/clothing/head/helmet.dmi and b/icons/mob/clothing/head/helmet.dmi differ diff --git a/icons/mob/clothing/suits/utility.dmi b/icons/mob/clothing/suits/utility.dmi index 4b6235d740ad3..f05fcf6514efd 100644 Binary files a/icons/mob/clothing/suits/utility.dmi and b/icons/mob/clothing/suits/utility.dmi differ diff --git a/icons/mob/clothing/under/civilian.dmi b/icons/mob/clothing/under/civilian.dmi index 3511731eac3ca..63788c8d1ed13 100644 Binary files a/icons/mob/clothing/under/civilian.dmi and b/icons/mob/clothing/under/civilian.dmi differ diff --git a/icons/mob/dust_animation.dmi b/icons/mob/dust_animation.dmi index 459fc2aa3c4b3..10d8418a14453 100644 Binary files a/icons/mob/dust_animation.dmi and b/icons/mob/dust_animation.dmi differ diff --git a/icons/mob/inhands/weapons/hammers_lefthand.dmi b/icons/mob/inhands/weapons/hammers_lefthand.dmi index d065edd86e75a..aaae035e056f1 100644 Binary files a/icons/mob/inhands/weapons/hammers_lefthand.dmi and b/icons/mob/inhands/weapons/hammers_lefthand.dmi differ diff --git a/icons/mob/inhands/weapons/hammers_righthand.dmi b/icons/mob/inhands/weapons/hammers_righthand.dmi index 022b281e4626a..6ff58389894e8 100644 Binary files a/icons/mob/inhands/weapons/hammers_righthand.dmi and b/icons/mob/inhands/weapons/hammers_righthand.dmi differ diff --git a/icons/mob/rideables/mecha.dmi b/icons/mob/rideables/mecha.dmi index 5960d05413781..a52a3ff5d4be5 100644 Binary files a/icons/mob/rideables/mecha.dmi and b/icons/mob/rideables/mecha.dmi differ diff --git a/icons/mob/silicon/aibots.dmi b/icons/mob/silicon/aibots.dmi index 86c450ef1ceae..819eecea0b739 100644 Binary files a/icons/mob/silicon/aibots.dmi and b/icons/mob/silicon/aibots.dmi differ diff --git a/icons/obj/clothing/gloves.dmi b/icons/obj/clothing/gloves.dmi index 454f2195e837d..3928c2246f1ed 100644 Binary files a/icons/obj/clothing/gloves.dmi and b/icons/obj/clothing/gloves.dmi differ diff --git a/icons/obj/clothing/head/helmet.dmi b/icons/obj/clothing/head/helmet.dmi index 621afe57ddce4..e213773717591 100644 Binary files a/icons/obj/clothing/head/helmet.dmi and b/icons/obj/clothing/head/helmet.dmi differ diff --git a/icons/obj/clothing/shoes.dmi b/icons/obj/clothing/shoes.dmi index 58d4791adc882..ea87b1dc293bb 100644 Binary files a/icons/obj/clothing/shoes.dmi and b/icons/obj/clothing/shoes.dmi differ diff --git a/icons/obj/clothing/suits/utility.dmi b/icons/obj/clothing/suits/utility.dmi index 8c12f056e21fe..31de04d33a731 100644 Binary files a/icons/obj/clothing/suits/utility.dmi and b/icons/obj/clothing/suits/utility.dmi differ diff --git a/icons/obj/clothing/under/civilian.dmi b/icons/obj/clothing/under/civilian.dmi index 6707876c244b7..a81e3681deb20 100644 Binary files a/icons/obj/clothing/under/civilian.dmi and b/icons/obj/clothing/under/civilian.dmi differ diff --git a/icons/obj/devices/mecha_equipment.dmi b/icons/obj/devices/mecha_equipment.dmi index ebfa5438ae911..e22b021ae236b 100644 Binary files a/icons/obj/devices/mecha_equipment.dmi and b/icons/obj/devices/mecha_equipment.dmi differ diff --git a/icons/obj/devices/new_assemblies.dmi b/icons/obj/devices/new_assemblies.dmi index 7bf96e5ba92e3..f80f89ce20a09 100644 Binary files a/icons/obj/devices/new_assemblies.dmi and b/icons/obj/devices/new_assemblies.dmi differ diff --git a/icons/obj/food/food.dmi b/icons/obj/food/food.dmi index 7b6afcc37ffbe..acc932a40049d 100644 Binary files a/icons/obj/food/food.dmi and b/icons/obj/food/food.dmi differ diff --git a/icons/obj/machines/manufactorio.dmi b/icons/obj/machines/manufactorio.dmi index 31abf6f6a20ee..58b08e4ab440b 100644 Binary files a/icons/obj/machines/manufactorio.dmi and b/icons/obj/machines/manufactorio.dmi differ diff --git a/icons/obj/service/janitor.dmi b/icons/obj/service/janitor.dmi index 9f28c6bbe046e..1ec087a7667f6 100644 Binary files a/icons/obj/service/janitor.dmi and b/icons/obj/service/janitor.dmi differ diff --git a/icons/obj/weapons/hammer.dmi b/icons/obj/weapons/hammer.dmi index 751e626779890..2b4e0cc820488 100644 Binary files a/icons/obj/weapons/hammer.dmi and b/icons/obj/weapons/hammer.dmi differ diff --git a/modular_doppler/modular_cosmetics/code/hands/special.dm b/modular_doppler/modular_cosmetics/code/hands/special.dm new file mode 100644 index 0000000000000..c75f88042e20b --- /dev/null +++ b/modular_doppler/modular_cosmetics/code/hands/special.dm @@ -0,0 +1,7 @@ +/obj/item/clothing/gloves/botanic_leather/janitor + name = "janitor gloves" + desc = "These rubber gloves protect against thorns, barbs, prickles, glass shards and any other threats that might be found in the station's trash. They're also quite warm." + icon = 'modular_doppler/modular_cosmetics/icons/obj/hands/gloves.dmi' + icon_state = "janitor_doppler" + worn_icon = 'modular_doppler/modular_cosmetics/icons/mob/hands/gloves.dmi' + inhand_icon_state = null diff --git a/modular_doppler/modular_cosmetics/code/hats/civilian.dm b/modular_doppler/modular_cosmetics/code/hats/civilian.dm new file mode 100644 index 0000000000000..093a761d6cccc --- /dev/null +++ b/modular_doppler/modular_cosmetics/code/hats/civilian.dm @@ -0,0 +1,7 @@ +/obj/item/clothing/head/hats/janitor_doppler + name = "janitor cap" + desc = "A regal purple cap to keep your head clean as you clean the filthy." + icon = 'modular_doppler/modular_cosmetics/icons/obj/head/hats.dmi' + icon_state = "janitor_doppler" + worn_icon = 'modular_doppler/modular_cosmetics/icons/mob/head/hats.dmi' + inhand_icon_state = "greyscale_softcap" diff --git a/modular_doppler/modular_cosmetics/code/shoes/galoshes.dm b/modular_doppler/modular_cosmetics/code/shoes/galoshes.dm new file mode 100644 index 0000000000000..a4174b2162829 --- /dev/null +++ b/modular_doppler/modular_cosmetics/code/shoes/galoshes.dm @@ -0,0 +1,6 @@ +/obj/item/clothing/shoes/galoshes/doppler + name = "purple galoshes" + desc = "A pair of purple rubber boots, designed to prevent slipping on wet surfaces." + icon = 'modular_doppler/modular_cosmetics/icons/obj/shoes/working.dmi' + icon_state = "galoshes_doppler" + worn_icon = 'modular_doppler/modular_cosmetics/icons/mob/shoes/working.dmi' diff --git a/modular_doppler/modular_cosmetics/code/suits/misc.dm b/modular_doppler/modular_cosmetics/code/suits/misc.dm index ecfb8d0af9df5..c020752e97c27 100644 --- a/modular_doppler/modular_cosmetics/code/suits/misc.dm +++ b/modular_doppler/modular_cosmetics/code/suits/misc.dm @@ -10,3 +10,13 @@ greyscale_config = /datum/greyscale_config/apron greyscale_config_worn = /datum/greyscale_config/apron/worn flags_1 = IS_PLAYER_COLORABLE_1 + +// Janitor +/obj/item/clothing/suit/apron/janitor_cloak + name = "waterproof poncho" + desc = "A transparent, waterproof cloak for your cleaning needs." + icon = 'modular_doppler/modular_cosmetics/icons/obj/suit/working.dmi' + icon_state = "janicloak" + worn_icon = 'modular_doppler/modular_cosmetics/icons/mob/suit/working.dmi' + inhand_icon_state = null + body_parts_covered = CHEST|GROIN|ARMS diff --git a/modular_doppler/modular_cosmetics/code/under/doppler_uniforms.dm b/modular_doppler/modular_cosmetics/code/under/doppler_uniforms.dm index 59148de8721bc..531d0917f8c29 100644 --- a/modular_doppler/modular_cosmetics/code/under/doppler_uniforms.dm +++ b/modular_doppler/modular_cosmetics/code/under/doppler_uniforms.dm @@ -201,3 +201,27 @@ else new /obj/item/clothing/under/misc/doppler_uniform/standard/suit/overalls/colored(loc) return INITIALIZE_HINT_QDEL + +// Doppla janitor uniforms + +/obj/item/clothing/under/rank/civilian/janitor/doppler + name = "janitor uniform" + desc = "It's the official uniform of the station's janitor. It has minor protection from biohazards." + icon = 'modular_doppler/modular_cosmetics/icons/mob/under/janitor_my_beloved.dmi' + icon_state = "janitor_doppler" + worn_icon = 'modular_doppler/modular_cosmetics/icons/obj/under/janitor_my_beloved.dmi' + inhand_icon_state = "janitor" + body_parts_covered = CHEST|GROIN + can_adjust = TRUE + alt_covers_chest = TRUE + +/obj/item/clothing/under/rank/civilian/janitor/doppler_ct + name = "janitor crop top" + desc = "It's the unofficial uniform of the station's janitor. It has minor protection from biohazards." + icon = 'modular_doppler/modular_cosmetics/icons/mob/under/janitor_my_beloved.dmi' + icon_state = "janitor_doppler_ct" + worn_icon = 'modular_doppler/modular_cosmetics/icons/obj/under/janitor_my_beloved.dmi' + inhand_icon_state = "janitor" + body_parts_covered = CHEST|GROIN + can_adjust = TRUE + alt_covers_chest = TRUE diff --git a/modular_doppler/modular_cosmetics/code/uniform_overrides.dm b/modular_doppler/modular_cosmetics/code/uniform_overrides.dm index 9275f59afdf51..85a7587216eef 100644 --- a/modular_doppler/modular_cosmetics/code/uniform_overrides.dm +++ b/modular_doppler/modular_cosmetics/code/uniform_overrides.dm @@ -5,3 +5,8 @@ /datum/colored_assistant/random jumpsuits = list(/obj/item/clothing/under/misc/doppler_uniform/standard/suit/overalls/random) jumpskirts = list(/obj/item/clothing/under/misc/doppler_uniform/standard/suit/overalls/random) // DITTO: see above + +/datum/outfit/job/janitor + uniform = /obj/item/clothing/under/rank/civilian/janitor/doppler + suit = /obj/item/clothing/suit/apron/janitor_cloak + gloves = /obj/item/clothing/gloves/botanic_leather/janitor diff --git a/modular_doppler/modular_cosmetics/icons/mob/hands/gloves.dmi b/modular_doppler/modular_cosmetics/icons/mob/hands/gloves.dmi index dd650ffcf8209..4fe32e363c2fd 100644 Binary files a/modular_doppler/modular_cosmetics/icons/mob/hands/gloves.dmi and b/modular_doppler/modular_cosmetics/icons/mob/hands/gloves.dmi differ diff --git a/modular_doppler/modular_cosmetics/icons/mob/head/hats.dmi b/modular_doppler/modular_cosmetics/icons/mob/head/hats.dmi new file mode 100644 index 0000000000000..9cbfd2fb08db3 Binary files /dev/null and b/modular_doppler/modular_cosmetics/icons/mob/head/hats.dmi differ diff --git a/modular_doppler/modular_cosmetics/icons/mob/shoes/working.dmi b/modular_doppler/modular_cosmetics/icons/mob/shoes/working.dmi new file mode 100644 index 0000000000000..1eb4e350043ad Binary files /dev/null and b/modular_doppler/modular_cosmetics/icons/mob/shoes/working.dmi differ diff --git a/modular_doppler/modular_cosmetics/icons/mob/suit/working.dmi b/modular_doppler/modular_cosmetics/icons/mob/suit/working.dmi new file mode 100644 index 0000000000000..06771ea720981 Binary files /dev/null and b/modular_doppler/modular_cosmetics/icons/mob/suit/working.dmi differ diff --git a/modular_doppler/modular_cosmetics/icons/mob/under/janitor_my_beloved.dmi b/modular_doppler/modular_cosmetics/icons/mob/under/janitor_my_beloved.dmi new file mode 100644 index 0000000000000..4e48b7abb1f80 Binary files /dev/null and b/modular_doppler/modular_cosmetics/icons/mob/under/janitor_my_beloved.dmi differ diff --git a/modular_doppler/modular_cosmetics/icons/obj/hands/gloves.dmi b/modular_doppler/modular_cosmetics/icons/obj/hands/gloves.dmi index 867d49a9d11b6..0f164baaba1ac 100644 Binary files a/modular_doppler/modular_cosmetics/icons/obj/hands/gloves.dmi and b/modular_doppler/modular_cosmetics/icons/obj/hands/gloves.dmi differ diff --git a/modular_doppler/modular_cosmetics/icons/obj/head/hats.dmi b/modular_doppler/modular_cosmetics/icons/obj/head/hats.dmi new file mode 100644 index 0000000000000..c0c8a681834e7 Binary files /dev/null and b/modular_doppler/modular_cosmetics/icons/obj/head/hats.dmi differ diff --git a/modular_doppler/modular_cosmetics/icons/obj/shoes/working.dmi b/modular_doppler/modular_cosmetics/icons/obj/shoes/working.dmi new file mode 100644 index 0000000000000..4d28d21c73ead Binary files /dev/null and b/modular_doppler/modular_cosmetics/icons/obj/shoes/working.dmi differ diff --git a/modular_doppler/modular_cosmetics/icons/obj/suit/working.dmi b/modular_doppler/modular_cosmetics/icons/obj/suit/working.dmi new file mode 100644 index 0000000000000..f4dc8f3af10a1 Binary files /dev/null and b/modular_doppler/modular_cosmetics/icons/obj/suit/working.dmi differ diff --git a/modular_doppler/modular_cosmetics/icons/obj/under/janitor_my_beloved.dmi b/modular_doppler/modular_cosmetics/icons/obj/under/janitor_my_beloved.dmi new file mode 100644 index 0000000000000..8d18986beff15 Binary files /dev/null and b/modular_doppler/modular_cosmetics/icons/obj/under/janitor_my_beloved.dmi differ diff --git a/modular_doppler/modular_quirks/entombed/code/entombed_mod.dm b/modular_doppler/modular_quirks/entombed/code/entombed_mod.dm index 34142ba6bdcc7..b1f77adeffbcf 100644 --- a/modular_doppler/modular_quirks/entombed/code/entombed_mod.dm +++ b/modular_doppler/modular_quirks/entombed/code/entombed_mod.dm @@ -110,7 +110,7 @@ who.balloon_alert(who, "can't strip a fused MODsuit!") return ..() -/obj/item/mod/control/pre_equipped/entombed/retract(mob/user, obj/item/part) +/obj/item/mod/control/pre_equipped/entombed/retract(mob/user, obj/item/part, instant = FALSE) if (ishuman(user)) var/mob/living/carbon/human/human_user = user var/datum/quirk/equipping/entombed/tomb_quirk = human_user.get_quirk(/datum/quirk/equipping/entombed) diff --git a/modular_doppler/modular_vending/code/tg_vendors/wardrobes.dm b/modular_doppler/modular_vending/code/tg_vendors/wardrobes.dm index 0f74e833e49ea..5403d6211f1aa 100644 --- a/modular_doppler/modular_vending/code/tg_vendors/wardrobes.dm +++ b/modular_doppler/modular_vending/code/tg_vendors/wardrobes.dm @@ -8,6 +8,16 @@ /obj/item/clothing/suit/jacket/doppler/departmental_jacket/med = 2, ) +/obj/machinery/vending/wardrobe/jani_wardrobe + products_doppler = list( + /obj/item/clothing/head/hats/janitor_doppler = 3, + /obj/item/clothing/shoes/galoshes/doppler = 2, + /obj/item/clothing/gloves/botanic_leather/janitor = 3, + /obj/item/clothing/suit/apron/janitor_cloak = 3, + /obj/item/clothing/under/rank/civilian/janitor/doppler = 3, + /obj/item/clothing/under/rank/civilian/janitor/doppler_ct = 3, + ) + /obj/machinery/vending/wardrobe/engi_wardrobe products_doppler = list( /obj/item/clothing/under/misc/doppler_uniform/engineering = 5, diff --git a/sound/attributions.txt b/sound/attributions.txt index dab6cedf7eb62..a6cbf21f8369b 100644 --- a/sound/attributions.txt +++ b/sound/attributions.txt @@ -50,7 +50,7 @@ https://freesound.org/s/431740/ (CC 0) chainsaw_stop.ogg is adapted from kyles "chainsaw sawing short cuts +stop.flac" (CC 0) https://freesound.org/people/kyles/sounds/453256/ -clock.mp3 is adapted from Tetrisrocker's "Clock", which uses CC Attributions 0 +clock.ogg is adapted from Tetrisrocker's "Clock", which uses CC Attributions 0 https://freesound.org/people/Tetrisrocker/sounds/458627/ ark_activation.ogg is taken from ScottFerguson1's "Cucko Clock edited version", which is licensed under CC Attribution 3.0 @@ -191,6 +191,10 @@ liquid_pour2.ogg and liquid_pour3.ogg were cut from https://freesound.org/people/MattRuthSound/sounds/561896/ https://freesound.org/people/MattRuthSound/sounds/561895/ + +roaring_fire.ogg made from: 10835 big fire loop.wav by Robinhood76 -- https://freesound.org/s/612277/ -- License: Attribution NonCommercial 4.0 +fire_puff made from: Bonfire Being Lit by samararaine -- https://freesound.org/s/186374/ -- License: Creative Commons 0 + ayylien.ogg was made by remixing: SCIRetro_Energy Swells Synth_Funky Audio_Sonics Spices by Funky_Audio under CC0 -- https://freesound.org/people/realtheremin/sounds/119011/ scifi_scare_a.aiff by realtheremin under CC0 -- https://freesound.org/people/Funky_Audio/sounds/729392/ @@ -204,8 +208,12 @@ Bottle Tap.wav by alex_alexalex -- https://freesound.org/s/395492/ -- License: A beaker_place.ogg was made by cutting and lowering pitch: place glass object.wav by milpower -- https://freesound.org/s/353105/ -- License: Creative Commons 0 + + glass_reverse.ogg is adapted from a combination of: https://freesound.org/people/C_Rogers/sounds/203368/ -- glass-shattering-hit_01.ogg by C_Rogers on freesound.org (CC0) https://freesound.org/people/Czarcazas/sounds/330800/ -- Audio reversal/fading of Shattering Glass (Small) by Czarcazas -- https://freesound.org/s/330800/ -- License: Attribution 3.0 sound/effects/bonk.ogg - recorded by oranges on a coke zero bottle, edited by ninjanomnom, released to public domain + +sound\items\weapons\hammer_death_scream.ogg - Undefeatablesos' scream recorded by Niron3206, edited by Niron3206, License: Creative Commons 0 diff --git a/sound/effects/fire_puff.ogg b/sound/effects/fire_puff.ogg new file mode 100644 index 0000000000000..c238584f55a65 Binary files /dev/null and b/sound/effects/fire_puff.ogg differ diff --git a/sound/effects/fireclip1.ogg b/sound/effects/fireclip1.ogg new file mode 100644 index 0000000000000..89ba2395a4d92 Binary files /dev/null and b/sound/effects/fireclip1.ogg differ diff --git a/sound/effects/fireclip2.ogg b/sound/effects/fireclip2.ogg new file mode 100644 index 0000000000000..c60990cd5bd7e Binary files /dev/null and b/sound/effects/fireclip2.ogg differ diff --git a/sound/effects/fireclip3.ogg b/sound/effects/fireclip3.ogg new file mode 100644 index 0000000000000..cd68608959879 Binary files /dev/null and b/sound/effects/fireclip3.ogg differ diff --git a/sound/effects/fireclip4.ogg b/sound/effects/fireclip4.ogg new file mode 100644 index 0000000000000..9ae01a8d3ade7 Binary files /dev/null and b/sound/effects/fireclip4.ogg differ diff --git a/sound/effects/fireclip5.ogg b/sound/effects/fireclip5.ogg new file mode 100644 index 0000000000000..855cc4b820d5a Binary files /dev/null and b/sound/effects/fireclip5.ogg differ diff --git a/sound/effects/fireclip6.ogg b/sound/effects/fireclip6.ogg new file mode 100644 index 0000000000000..061cc42993d8c Binary files /dev/null and b/sound/effects/fireclip6.ogg differ diff --git a/sound/effects/fireclip7.ogg b/sound/effects/fireclip7.ogg new file mode 100644 index 0000000000000..3a0f9840f3c5e Binary files /dev/null and b/sound/effects/fireclip7.ogg differ diff --git a/sound/effects/roaring_fire.ogg b/sound/effects/roaring_fire.ogg new file mode 100644 index 0000000000000..b3927b69feb87 Binary files /dev/null and b/sound/effects/roaring_fire.ogg differ diff --git a/sound/items/duct_tape/duct_tape_rip.ogg b/sound/items/duct_tape/duct_tape_rip.ogg index bf1746ef7c940..8a5df8ffdd872 100644 Binary files a/sound/items/duct_tape/duct_tape_rip.ogg and b/sound/items/duct_tape/duct_tape_rip.ogg differ diff --git a/sound/items/duct_tape/duct_tape_snap.ogg b/sound/items/duct_tape/duct_tape_snap.ogg index 354061af12152..af253fc7ef24b 100644 Binary files a/sound/items/duct_tape/duct_tape_snap.ogg and b/sound/items/duct_tape/duct_tape_snap.ogg differ diff --git a/sound/items/handling/shoes/sneakers_pickup1.ogg b/sound/items/handling/shoes/sneakers_pickup1.ogg index 9670ec324e372..7d86eaa562f13 100644 Binary files a/sound/items/handling/shoes/sneakers_pickup1.ogg and b/sound/items/handling/shoes/sneakers_pickup1.ogg differ diff --git a/sound/items/weapons/hammer_death_scream.ogg b/sound/items/weapons/hammer_death_scream.ogg new file mode 100644 index 0000000000000..cff35f2328116 Binary files /dev/null and b/sound/items/weapons/hammer_death_scream.ogg differ diff --git a/sound/misc/escape_menu/attribution.txt b/sound/misc/escape_menu/attribution.txt new file mode 100644 index 0000000000000..c4f5fc0206b0f --- /dev/null +++ b/sound/misc/escape_menu/attribution.txt @@ -0,0 +1,3 @@ +esc_middle, esc_open and esc_close are all modified from the following respectively: +Tape Recorder.wav by Pogotron -- https://freesound.org/s/61075/ -- License: Sampling+ +cassette tape deck slot open close hard nice spring various and spinout end.flac by kyles -- https://freesound.org/s/635487/ -- License: Creative Commons 0 diff --git a/sound/misc/escape_menu/esc_close.ogg b/sound/misc/escape_menu/esc_close.ogg new file mode 100644 index 0000000000000..30946e77edd80 Binary files /dev/null and b/sound/misc/escape_menu/esc_close.ogg differ diff --git a/sound/misc/escape_menu/esc_middle.ogg b/sound/misc/escape_menu/esc_middle.ogg new file mode 100644 index 0000000000000..4a8b3134926df Binary files /dev/null and b/sound/misc/escape_menu/esc_middle.ogg differ diff --git a/sound/misc/escape_menu/esc_open.ogg b/sound/misc/escape_menu/esc_open.ogg new file mode 100644 index 0000000000000..4ad958d0bcb2f Binary files /dev/null and b/sound/misc/escape_menu/esc_open.ogg differ diff --git a/sound/voice/repairbot/brick.ogg b/sound/voice/repairbot/brick.ogg new file mode 100644 index 0000000000000..78dae8633a3a6 Binary files /dev/null and b/sound/voice/repairbot/brick.ogg differ diff --git a/sound/voice/repairbot/cantanymore.ogg b/sound/voice/repairbot/cantanymore.ogg new file mode 100644 index 0000000000000..4fc4fb216f72f Binary files /dev/null and b/sound/voice/repairbot/cantanymore.ogg differ diff --git a/sound/voice/repairbot/entropy.ogg b/sound/voice/repairbot/entropy.ogg new file mode 100644 index 0000000000000..ab6a4f6a06732 Binary files /dev/null and b/sound/voice/repairbot/entropy.ogg differ diff --git a/sound/voice/repairbot/fixit.ogg b/sound/voice/repairbot/fixit.ogg new file mode 100644 index 0000000000000..20e095589cbb1 Binary files /dev/null and b/sound/voice/repairbot/fixit.ogg differ diff --git a/sound/voice/repairbot/fixtouch.ogg b/sound/voice/repairbot/fixtouch.ogg new file mode 100644 index 0000000000000..86ca24ffe3f95 Binary files /dev/null and b/sound/voice/repairbot/fixtouch.ogg differ diff --git a/sound/voice/repairbot/passionproject.ogg b/sound/voice/repairbot/passionproject.ogg new file mode 100644 index 0000000000000..6f1fba1d45251 Binary files /dev/null and b/sound/voice/repairbot/passionproject.ogg differ diff --git a/sound/voice/repairbot/patchingholes.ogg b/sound/voice/repairbot/patchingholes.ogg new file mode 100644 index 0000000000000..6c65fc22b9627 Binary files /dev/null and b/sound/voice/repairbot/patchingholes.ogg differ diff --git a/sound/voice/repairbot/pay.ogg b/sound/voice/repairbot/pay.ogg new file mode 100644 index 0000000000000..0aa2b68868c96 Binary files /dev/null and b/sound/voice/repairbot/pay.ogg differ diff --git a/sound/voice/repairbot/strings.ogg b/sound/voice/repairbot/strings.ogg new file mode 100644 index 0000000000000..bc897eacccd14 Binary files /dev/null and b/sound/voice/repairbot/strings.ogg differ diff --git a/strings/tips.txt b/strings/tips.txt index 7d5f9f82ccc2e..2e80296af2258 100644 --- a/strings/tips.txt +++ b/strings/tips.txt @@ -55,6 +55,7 @@ As a Heretic, the Path of Cosmos allows you to take rightful ownership of the ve As a Janitor Cyborg, you are the bane of all slaughter demons and even Bubblegum himself. Cleaning up blood stains will severely gimp them. As a Janitor, if someone steals your janicart, you can instead use your space cleaner spray, grenades, water sprayer, exact bloody revenge or order another from Cargo. As a Janitor, mousetraps can be used to create bombs or booby-trap containers. +As a Janitor, you can command cleanbots by pointing at a tile and saying mop/clean. As a Medical Cyborg, you can fully perform surgery and even augment people. As a Medical Doctor, almost every type of wound can be treated at least temporarily with gauze. When in doubt, wrap it up! As a Medical Doctor, corpses placed inside a freezer or morgue tray will have their organs frozen preventing decay. If you don't have time to revive multiple dead bodies, transfer them to the morgue temporarily! diff --git a/tgstation.dme b/tgstation.dme index 612a69cde7374..593af4983890d 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -245,6 +245,7 @@ #include "code\__DEFINES\time.dm" #include "code\__DEFINES\tools.dm" #include "code\__DEFINES\toys.dm" +#include "code\__DEFINES\tracy.dm" #include "code\__DEFINES\trader.dm" #include "code\__DEFINES\transport.dm" #include "code\__DEFINES\tts.dm" @@ -480,6 +481,7 @@ #include "code\__HELPERS\heap.dm" #include "code\__HELPERS\hearted.dm" #include "code\__HELPERS\honkerblast.dm" +#include "code\__HELPERS\hud.dm" #include "code\__HELPERS\icon_smoothing.dm" #include "code\__HELPERS\icons.dm" #include "code\__HELPERS\jatum.dm" @@ -1208,6 +1210,7 @@ #include "code\datums\components\interaction_booby_trap.dm" #include "code\datums\components\irradiated.dm" #include "code\datums\components\item_equipped_movement_rustle.dm" +#include "code\datums\components\item_killsound.dm" #include "code\datums\components\itembound.dm" #include "code\datums\components\itempicky.dm" #include "code\datums\components\jetpack.dm" @@ -1931,6 +1934,7 @@ #include "code\datums\status_effects\_status_effect_helpers.dm" #include "code\datums\status_effects\agent_pinpointer.dm" #include "code\datums\status_effects\buffs.dm" +#include "code\datums\status_effects\death_sound.dm" #include "code\datums\status_effects\drug_effects.dm" #include "code\datums\status_effects\gas.dm" #include "code\datums\status_effects\grouped_effect.dm" @@ -3979,6 +3983,7 @@ #include "code\modules\clothing\head\mind_monkey_helmet.dm" #include "code\modules\clothing\head\moth.dm" #include "code\modules\clothing\head\papersack.dm" +#include "code\modules\clothing\head\perceptomatrix.dm" #include "code\modules\clothing\head\pirate.dm" #include "code\modules\clothing\head\religious.dm" #include "code\modules\clothing\head\soft_caps.dm" @@ -4903,6 +4908,9 @@ #include "code\modules\mob\living\basic\bots\hygienebot\hygienebot_ai.dm" #include "code\modules\mob\living\basic\bots\medbot\medbot.dm" #include "code\modules\mob\living\basic\bots\medbot\medbot_ai.dm" +#include "code\modules\mob\living\basic\bots\repairbot\repairbot.dm" +#include "code\modules\mob\living\basic\bots\repairbot\repairbot_abilities.dm" +#include "code\modules\mob\living\basic\bots\repairbot\repairbot_ai.dm" #include "code\modules\mob\living\basic\bots\vibebot\vibebot.dm" #include "code\modules\mob\living\basic\bots\vibebot\vibebot_abilities.dm" #include "code\modules\mob\living\basic\bots\vibebot\vibebot_ai.dm" @@ -5357,7 +5365,6 @@ #include "code\modules\mob\living\simple_animal\bot\bot_announcement.dm" #include "code\modules\mob\living\simple_animal\bot\construction.dm" #include "code\modules\mob\living\simple_animal\bot\ed209bot.dm" -#include "code\modules\mob\living\simple_animal\bot\floorbot.dm" #include "code\modules\mob\living\simple_animal\bot\mulebot.dm" #include "code\modules\mob\living\simple_animal\bot\secbot.dm" #include "code\modules\mob\living\simple_animal\bot\SuperBeepsky.dm" @@ -6806,6 +6813,8 @@ #include "modular_doppler\modular_cosmetics\code\face\masks.dm" #include "modular_doppler\modular_cosmetics\code\hands\gloves.dm" #include "modular_doppler\modular_cosmetics\code\hands\rings.dm" +#include "modular_doppler\modular_cosmetics\code\hands\special.dm" +#include "modular_doppler\modular_cosmetics\code\hats\civilian.dm" #include "modular_doppler\modular_cosmetics\code\hats\doppler_command_hats.dm" #include "modular_doppler\modular_cosmetics\code\head\bows.dm" #include "modular_doppler\modular_cosmetics\code\head\hair_tie.dm" @@ -6817,6 +6826,7 @@ #include "modular_doppler\modular_cosmetics\code\plushies\plushes.dm" #include "modular_doppler\modular_cosmetics\code\shoes\baseshoes.dm" #include "modular_doppler\modular_cosmetics\code\shoes\gags_shoes.dm" +#include "modular_doppler\modular_cosmetics\code\shoes\galoshes.dm" #include "modular_doppler\modular_cosmetics\code\storage\backpacks.dm" #include "modular_doppler\modular_cosmetics\code\storage\belts.dm" #include "modular_doppler\modular_cosmetics\code\storage\rings.dm" diff --git a/tgui/package.json b/tgui/package.json index 57d02a389d267..f89241c5a3f2e 100644 --- a/tgui/package.json +++ b/tgui/package.json @@ -45,7 +45,7 @@ "mini-css-extract-plugin": "^2.9.2", "prettier": "^3.2.5", "sass": "^1.80.6", - "sass-loader": "^14.2.1", + "sass-loader": "^16.0.3", "style-loader": "^4.0.0", "swc-loader": "^0.2.6", "typescript": "^5.6.3", diff --git a/tgui/packages/tgui-panel/package.json b/tgui/packages/tgui-panel/package.json index 325e2fde7ca48..f761ce3c61681 100644 --- a/tgui/packages/tgui-panel/package.json +++ b/tgui/packages/tgui-panel/package.json @@ -11,6 +11,7 @@ "react-dom": "^18.3.1", "tgui": "workspace:*", "tgui-dev-server": "workspace:*", - "tgui-polyfill": "workspace:*" + "tgui-polyfill": "workspace:*", + "tgui-styles": "^0.0.10" } } diff --git a/tgui/packages/tgui-panel/styles/components/Chat.scss b/tgui/packages/tgui-panel/styles/components/Chat.scss index b439ace8c58f1..882f86a7aaacb 100644 --- a/tgui/packages/tgui-panel/styles/components/Chat.scss +++ b/tgui/packages/tgui-panel/styles/components/Chat.scss @@ -8,7 +8,7 @@ @use '~tgui/styles/base.scss'; @use '~tgui/styles/colors.scss'; -$text-color: #abc6ec !default; +$text-color: hsl(210, 50%, 80%) !default; $color-bg-section: base.$color-bg-section !default; .Chat { @@ -21,11 +21,11 @@ $color-bg-section: base.$color-bg-section !default; font-size: 0.7em; padding: 0.2em 0.3em; line-height: 1; - color: white; + color: hsl(0, 0%, 100%); text-align: center; white-space: nowrap; vertical-align: middle; - background-color: crimson; + background-color: hsl(348, 83%, 47%); border-radius: 10px; transition: font-size 200ms ease-out; @@ -68,12 +68,12 @@ $color-bg-section: base.$color-bg-section !default; } .Chat__highlight { - color: #000; + color: hsl(0, 0%, 0%); } .Chat__highlight--restricted { - color: #fff; - background-color: #a00; + color: hsl(0, 0%, 100%); + background-color: hsl(0, 100%, 33.3%); font-weight: bold; } @@ -83,7 +83,7 @@ $color-bg-section: base.$color-bg-section !default; .ChatMessage--highlighted { position: relative; - border-left: math.div(1em, 6) solid rgba(255, 221, 68); + border-left: math.div(1em, 6) solid hsl(50, 100%, 63.5%); padding-left: 0.5em; &:after { @@ -93,7 +93,7 @@ $color-bg-section: base.$color-bg-section !default; bottom: 0; left: 0; right: 0; - background-color: rgba(255, 221, 68, 0.1); + background-color: hsla(50, 100%, 63.5%, 0.1); // Make this click-through since this is an overlay pointer-events: none; } diff --git a/tgui/packages/tgui-panel/styles/components/Notifications.scss b/tgui/packages/tgui-panel/styles/components/Notifications.scss index f3669967fd70c..2e99e59a20aa0 100644 --- a/tgui/packages/tgui-panel/styles/components/Notifications.scss +++ b/tgui/packages/tgui-panel/styles/components/Notifications.scss @@ -11,8 +11,8 @@ } .Notification { - color: #fff; - background-color: crimson; + color: hsl(0, 0%, 100%); + background-color: hsl(348, 83%, 47%); padding: 0.5em; margin: 1em 0; diff --git a/tgui/packages/tgui-panel/styles/components/Ping.scss b/tgui/packages/tgui-panel/styles/components/Ping.scss index 251b0fd953912..292caf11105e0 100644 --- a/tgui/packages/tgui-panel/styles/components/Ping.scss +++ b/tgui/packages/tgui-panel/styles/components/Ping.scss @@ -23,6 +23,6 @@ $border-color: rgba(140, 140, 140, 0.5) !default; left: 0.5em; width: 0.5em; height: 0.5em; - background-color: #888; + background-color: hsl(0, 0%, 53.3%); border-radius: 0.25em; } diff --git a/tgui/packages/tgui-panel/styles/main.scss b/tgui/packages/tgui-panel/styles/main.scss index 08e60d18ee6a3..60198a654b930 100644 --- a/tgui/packages/tgui-panel/styles/main.scss +++ b/tgui/packages/tgui-panel/styles/main.scss @@ -5,11 +5,13 @@ @use 'sass:meta'; @use 'sass:color'; +// Components +@use 'pkg:tgui-styles'; @use '~tgui/styles/colors.scss'; @use '~tgui/styles/base.scss' with ( - $color-bg: #202020, - $color-bg-section: color.adjust(#202020, $lightness: -5%), + $color-bg: hsl(0, 0%, 12.5%), + $color-bg-section: color.adjust(hsl(0, 0%, 12.5%), $lightness: -5%), $color-bg-grad-spread: 0% ); @@ -23,29 +25,6 @@ @include meta.load-css('~tgui/styles/atomic/outline.scss'); @include meta.load-css('~tgui/styles/atomic/text.scss'); -// Components -@include meta.load-css('~tgui/styles/components/BlockQuote.scss'); -@include meta.load-css('~tgui/styles/components/Button.scss'); -@include meta.load-css('~tgui/styles/components/ColorBox.scss'); -@include meta.load-css('~tgui/styles/components/Dimmer.scss'); -@include meta.load-css('~tgui/styles/components/Divider.scss'); -@include meta.load-css('~tgui/styles/components/Dropdown.scss'); -@include meta.load-css('~tgui/styles/components/Flex.scss'); -@include meta.load-css('~tgui/styles/components/Input.scss'); -@include meta.load-css('~tgui/styles/components/Knob.scss'); -@include meta.load-css('~tgui/styles/components/LabeledList.scss'); -@include meta.load-css('~tgui/styles/components/Modal.scss'); -@include meta.load-css('~tgui/styles/components/NoticeBox.scss'); -@include meta.load-css('~tgui/styles/components/NumberInput.scss'); -@include meta.load-css('~tgui/styles/components/ProgressBar.scss'); -@include meta.load-css('~tgui/styles/components/Section.scss'); -@include meta.load-css('~tgui/styles/components/Slider.scss'); -@include meta.load-css('~tgui/styles/components/Stack.scss'); -@include meta.load-css('~tgui/styles/components/Table.scss'); -@include meta.load-css('~tgui/styles/components/Tabs.scss'); -@include meta.load-css('~tgui/styles/components/TextArea.scss'); -@include meta.load-css('~tgui/styles/components/Tooltip.scss'); - // Components specific to tgui-panel @include meta.load-css('./components/Chat.scss'); @include meta.load-css('./components/Ping.scss'); diff --git a/tgui/packages/tgui-panel/styles/tgchat/chat-dark.scss b/tgui/packages/tgui-panel/styles/tgchat/chat-dark.scss index c1cb06cff3ae2..5329e25487006 100644 --- a/tgui/packages/tgui-panel/styles/tgchat/chat-dark.scss +++ b/tgui/packages/tgui-panel/styles/tgchat/chat-dark.scss @@ -27,15 +27,15 @@ img.icon { } a { - color: #397ea5; + color: hsl(201.7, 48.6%, 43.5%); } a.visited { - color: #7c00e6; + color: hsl(272.3, 100%, 45.1%); } a:visited { - color: #7c00e6; + color: hsl(272.3, 100%, 45.1%); } a.popt { @@ -139,7 +139,7 @@ a.popt { } .highlightPopup input.highlightColor { - background-color: #ffff00; + background-color: hsl(60, 100%, 50%); } .highlightPopup input.highlightTermSubmit { @@ -199,7 +199,7 @@ a.popt { /* MOTD */ .motd { - color: #a4bad6; + color: hsl(213.6, 37.9%, 74.1%); font-family: Verdana, sans-serif; white-space: normal; } @@ -210,7 +210,7 @@ a.popt { .motd h4, .motd h5, .motd h6 { - color: #a4bad6; + color: hsl(213.6, 37.9%, 74.1%); text-decoration: underline; } @@ -219,7 +219,7 @@ a.popt { .motd a:visited, .motd a:active, .motd a:hover { - color: #a4bad6; + color: hsl(213.6, 37.9%, 74.1%); } /* ADD HERE FOR BOLD */ @@ -255,13 +255,13 @@ h3, h4, h5, h6 { - color: #a4bad6; + color: hsl(213.6, 37.9%, 74.1%); font-family: Georgia, Verdana, sans-serif; } h1.alert, h2.alert { - color: #a4bad6; + color: hsl(213.6, 37.9%, 74.1%); } em { @@ -270,27 +270,27 @@ em { } .ooc { - color: #cca300; + color: hsl(47.9, 100%, 40%); font-weight: bold; } .adminobserverooc { - color: #0099cc; + color: hsl(195, 100%, 40%); font-weight: bold; } .adminooc { - color: #3d5bc3; + color: hsl(226.6, 52.8%, 50.2%); font-weight: bold; } .adminsay { - color: #ff4500; + color: hsl(16.2, 100%, 50%); font-weight: bold; } .admin { - color: #5975da; + color: hsl(227, 63.5%, 60.2%); font-weight: bold; } @@ -306,91 +306,91 @@ em { } .deadsay { - color: #e2c1ff; + color: hsl(271.9, 100%, 87.8%); } .binarysay { - color: #1e90ff; + color: hsl(209.6, 100%, 55.9%); } .binarysay a { - color: #00ff00; + color: hsl(120, 100%, 50%); } .binarysay a:active, .binarysay a:visited { - color: #88ff88; + color: hsl(120, 100%, 76.7%); } /* RADIO COLORS */ /* IF YOU CHANGE THIS KEEP IT IN SYNC WITH TGUI CONSTANTS */ .radio { - color: #1ecc43; + color: hsl(132.8, 74.4%, 45.9%); } .sciradio { - color: #c68cfa; + color: hsl(271.6, 91.7%, 76.5%); } .comradio { - color: #fcdf03; + color: hsl(53, 97.6%, 50%); } .secradio { - color: #dd3535; + color: hsl(0, 71.2%, 53.7%); } .medradio { - color: #57b8f0; + color: hsl(202, 83.6%, 64.1%); } .engradio { - color: #f37746; + color: hsl(17, 87.8%, 61.4%); } .suppradio { - color: #b88646; + color: hsl(33.7, 44.9%, 49.8%); } .servradio { - color: #6ca729; + color: hsl(88.1, 60.6%, 40.8%); } .syndradio { - color: #8f4a4b; + color: hsl(359.1, 31.8%, 42.5%); } .gangradio { - color: #ac2ea1; + color: hsl(305.2, 57.8%, 42.7%); } .centcomradio { - color: #2681a5; + color: hsl(197, 62.6%, 39.8%); } .aiprivradio { - color: #d65d95; + color: hsl(332.2, 59.6%, 60.2%); } .enteradio { - color: #79c5a8; + color: hsl(157.1, 39.6%, 62.4%); } .redteamradio { - color: #ff4444 !important; + color: hsl(0, 100%, 63.3%) !important; } .blueteamradio { - color: #3434fd !important; + color: hsl(240, 98%, 59.8%) !important; } .greenteamradio { - color: #34fd34 !important; + color: hsl(120, 98%, 59.8%) !important; } .yellowteamradio { - color: #fdfd34 !important; + color: hsl(60, 98%, 59.8%) !important; } .yell { @@ -398,122 +398,122 @@ em { } .alert { - color: #d82020; + color: hsl(0, 74.2%, 48.6%); } .userdanger { - color: #c51e1e; + color: hsl(0, 73.6%, 44.5%); font-weight: bold; font-size: 185%; } .bolddanger { - color: #c51e1e; + color: hsl(0, 73.6%, 44.5%); font-weight: bold; } .danger { - color: #c51e1e; + color: hsl(0, 73.6%, 44.5%); } .tinydanger { - color: #c51e1e; + color: hsl(0, 73.6%, 44.5%); font-size: 85%; } .smalldanger { - color: #c51e1e; + color: hsl(0, 73.6%, 44.5%); font-size: 90%; } .warning { - color: #c51e1e; + color: hsl(0, 73.6%, 44.5%); font-style: italic; } .alertwarning { - color: #ff0000; + color: hsl(0, 100%, 50%); font-weight: bold; } .boldwarning { - color: #c51e1e; + color: hsl(0, 73.6%, 44.5%); font-style: italic; font-weight: bold; } .announce { - color: #c51e1e; + color: hsl(0, 73.6%, 44.5%); font-weight: bold; } .boldannounce { - color: #c51e1e; + color: hsl(0, 73.6%, 44.5%); font-weight: bold; } .minorannounce { - color: #c51e1e; + color: hsl(0, 73.6%, 44.5%); font-weight: bold; font-size: 185%; } .minoralert { - color: #a4bad6; + color: hsl(213.6, 37.9%, 74.1%); font-size: 125%; } .priorityannounce { - color: #a4bad6; + color: hsl(213.6, 37.9%, 74.1%); font-weight: bold; font-size: 225%; } .prioritytitle { - color: #6685f5; + color: hsl(227, 87.7%, 68%); font-weight: bold; font-size: 185%; } .priorityalert { - color: #c51e1e; + color: hsl(0, 73.6%, 44.5%); font-size: 140%; } .greenannounce { - color: #059223; + color: hsl(132.8, 93.4%, 29.6%); font-weight: bold; } .rose { - color: #ff5050; + color: hsl(0, 100%, 65.7%); } .info { - color: #9ab0ff; + color: hsl(226.9, 100%, 80.2%); } .notice { - color: #6685f5; + color: hsl(227, 87.7%, 68%); } .tinynotice { - color: #6685f5; + color: hsl(227, 87.7%, 68%); font-size: 85%; } .tinynoticeital { - color: #6685f5; + color: hsl(227, 87.7%, 68%); font-style: italic; font-size: 85%; } .smallnotice { - color: #6685f5; + color: hsl(227, 87.7%, 68%); font-size: 90%; } .smallnoticeital { - color: #6685f5; + color: hsl(227, 87.7%, 68%); font-style: italic; font-size: 90%; } @@ -524,218 +524,218 @@ em { } .boldnotice { - color: #6685f5; + color: hsl(227, 87.7%, 68%); font-weight: bold; } .hear { - color: #6685f5; + color: hsl(227, 87.7%, 68%); font-style: italic; } .adminnotice { - color: #6685f5; + color: hsl(227, 87.7%, 68%); } .adminhelp { - color: #ff0000; + color: hsl(0, 100%, 50%); font-weight: bold; } .unconscious { - color: #a4bad6; + color: hsl(213.6, 37.9%, 74.1%); font-weight: bold; } .suicide { - color: #ff5050; + color: hsl(0, 100%, 65.7%); font-style: italic; } .green { - color: #059223; + color: hsl(132.8, 93.4%, 29.6%); } .grey { - color: #838383; + color: hsl(0, 0%, 51.4%); } .red { - color: #ff0000; + color: hsl(0, 100%, 50%); } .blue { - color: #215cff; + color: hsl(224.1, 100%, 56.5%); } .nicegreen { - color: #059223; + color: hsl(132.8, 93.4%, 29.6%); } .boldnicegreen { - color: #059223; + color: hsl(132.8, 93.4%, 29.6%); font-weight: bold; } .blob { - color: #ee4000; + color: hsl(16.1, 100%, 46.7%); } .blobannounce { - color: #556b2f; + color: hsl(82, 39%, 30.2%); font-weight: bold; font-size: 185%; } .cult { - color: #973e3b; + color: hsl(2, 43.8%, 41.2%); } .cult_italic { - color: #973e3b; + color: hsl(2, 43.8%, 41.2%); font-style: italic; } .cult_bold { - color: #973e3b; + color: hsl(2, 43.8%, 41.2%); font-style: italic; font-weight: bold; } .cult_bold_italic { - color: #973e3b; + color: hsl(2, 43.8%, 41.2%); font-weight: bold; font-size: 185%; } .cult_large { - color: #973e3b; + color: hsl(2, 43.8%, 41.2%); font-weight: bold; font-size: 185%; } .narsie { - color: #973e3b; + color: hsl(2, 43.8%, 41.2%); font-weight: bold; font-size: 925%; } .narsiesmall { - color: #973e3b; + color: hsl(2, 43.8%, 41.2%); font-weight: bold; font-size: 370%; } .colossus { - color: #7f282a; + color: hsl(358.6, 52.1%, 32.7%); font-size: 310%; } .hierophant { - color: #b441ee; + color: hsl(279.9, 83.6%, 59.4%); font-weight: bold; font-style: italic; } .hierophant_warning { - color: #c56bf1; + color: hsl(280.3, 82.7%, 68.2%); font-style: italic; } .purple { - color: #9956d3; + color: hsl(272.2, 58.7%, 58.2%); } .holoparasite { - color: #88809c; + color: hsl(257.1, 12.4%, 55.7%); } .revennotice { - color: #c099e2; + color: hsl(272.1, 55.7%, 74.3%); } .revenboldnotice { - color: #c099e2; + color: hsl(272.1, 55.7%, 74.3%); font-weight: bold; } .revenbignotice { - color: #c099e2; + color: hsl(272.1, 55.7%, 74.3%); font-weight: bold; font-size: 185%; } .revenminor { - color: #823abb; + color: hsl(273.5, 52.7%, 48%); } .revenwarning { - color: #760fbb; + color: hsl(275.9, 85.1%, 39.6%); font-style: italic; } .revendanger { - color: #760fbb; + color: hsl(275.9, 85.1%, 39.6%); font-weight: bold; font-size: 185%; } .deconversion_message { - color: #a947ff; + color: hsl(272, 100%, 63.9%); font-size: 185%; font-style: italic; } .ghostalert { - color: #6600ff; + color: hsl(264, 100%, 50%); font-style: italic; font-weight: bold; } .alien { - color: #855d85; + color: hsl(300, 17.7%, 44.3%); } .noticealien { - color: #059223; + color: hsl(132.8, 93.4%, 29.6%); } .alertalien { - color: #059223; + color: hsl(132.8, 93.4%, 29.6%); font-weight: bold; } .changeling { - color: #059223; + color: hsl(132.8, 93.4%, 29.6%); font-style: italic; } .alertsyndie { - color: #ff0000; + color: hsl(0, 100%, 50%); font-size: 185%; font-weight: bold; } .spiderbroodmother { - color: #8800ff; + color: hsl(272, 100%, 50%); font-weight: bold; font-size: 185%; } .spiderbreacher { - color: #e8b670; + color: hsl(35, 72.3%, 67.5%); font-weight: bold; font-size: 140%; } .spiderscout { - color: #231d98; + color: hsl(242.9, 68%, 35.5%); font-weight: bold; font-size: 120%; } .interface { - color: #750e75; + color: hsl(300, 78.6%, 25.7%); } .sans { @@ -751,7 +751,7 @@ em { } .tape_recorder { - color: #ff0000; + color: hsl(0, 100%, 50%); font-family: 'Courier New', cursive, sans-serif; } @@ -786,17 +786,17 @@ em { } .greentext { - color: #059223; + color: hsl(132.8, 93.4%, 29.6%); font-size: 185%; } .redtext { - color: #c51e1e; + color: hsl(0, 73.6%, 44.5%); font-size: 185%; } .clown { - color: #ff70c1; + color: hsl(326, 100%, 72%); font-size: 160%; font-family: 'Comic Sans MS', cursive, sans-serif; font-weight: bold; @@ -808,13 +808,13 @@ em { } .his_grace { - color: #15d512; + color: hsl(119.1, 84.4%, 45.3%); font-family: 'Courier New', cursive, sans-serif; font-style: italic; } .hypnophrase { - color: #202020; + color: hsl(0, 0%, 12.5%); font-weight: bold; animation: hypnocolor 1500ms infinite; animation-direction: alternate; @@ -822,43 +822,43 @@ em { @keyframes hypnocolor { 0% { - color: #202020; + color: hsl(0, 0%, 12.5%); } 25% { - color: #4b02ac; + color: hsl(265.8, 97.7%, 34.1%); } 50% { - color: #9f41f1; + color: hsl(272, 86.3%, 60%); } 75% { - color: #541c9c; + color: hsl(266.2, 69.6%, 36.1%); } 100% { - color: #7adbf3; + color: hsl(191.9, 83.4%, 71.6%); } } .phobia { - color: #dd0000; + color: hsl(0, 100%, 43.3%); font-weight: bold; animation: phobia 750ms infinite; } @keyframes phobia { 0% { - color: #f75a5a; + color: hsl(0, 90.8%, 66.1%); } 50% { - color: #dd0000; + color: hsl(0, 100%, 43.3%); } 100% { - color: #f75a5a; + color: hsl(0, 90.8%, 66.1%); } } @@ -876,7 +876,7 @@ em { } .memo { - color: #638500; + color: hsl(75.3, 100%, 26.1%); text-align: center; } @@ -886,35 +886,35 @@ em { } .abductor { - color: #c204c2; + color: hsl(300, 96%, 38.8%); font-style: italic; } .mind_control { - color: #df3da9; + color: hsl(320, 71.7%, 55.7%); font-size: 100%; font-weight: bold; font-style: italic; } .slime { - color: #00ced1; + color: hsl(180.9, 100%, 41%); } .drone { - color: #848482; + color: hsl(60, 0.8%, 51.4%); } .monkey { - color: #975032; + color: hsl(17.8, 50.2%, 39.4%); } .swarmer { - color: #2c75ff; + color: hsl(219.2, 100%, 58.6%); } .resonate { - color: #298f85; + color: hsl(174.1, 55.4%, 36.1%); } .upside_down { @@ -938,7 +938,7 @@ em { } .internal.boldnshit { - color: #3d5bc3; + color: hsl(226.6, 52.8%, 50.2%); font-weight: bold; } @@ -967,8 +967,8 @@ em { } .examine_block { - background: #1b1c1e; - border: 1px solid #a4bad6; + background: hsl(220, 5.3%, 11.2%); + border: 1px solid hsl(213.6, 37.9%, 74.1%); margin: 0.5em; padding: 0.5em 0.75em; } @@ -990,7 +990,7 @@ em { .separator::after { content: ''; flex: 1; - border-bottom: 1px solid #a4bad6; + border-bottom: 1px solid hsl(213.6, 37.9%, 74.1%); } .separator:not(:empty)::before { @@ -1040,51 +1040,51 @@ em { /*DOPPLER ADDITION END*/ $alert-stripe-colors: ( - 'default': #00283a, - 'green': #003d00, - 'blue': #00283a, - 'pink': #30001b, - 'yellow': #574a00, - 'orange': #593400, - 'red': #420000, - 'purple': #2c0030, - 'grey': #252525, + 'default': hsl(198.6, 100%, 11.4%), + 'green': hsl(120, 100%, 12%), + 'blue': hsl(198.6, 100%, 11.4%), + 'pink': hsl(326.2, 100%, 9.4%), + 'yellow': hsl(51, 100%, 17.1%), + 'orange': hsl(35.1, 100%, 17.5%), + 'red': hsl(0, 100%, 12.9%), + 'purple': hsl(295, 100%, 9.4%), + 'grey': hsl(0, 0%, 14.5%), ); $alert-stripe-alternate-colors: ( - 'default': #003045, - 'green': #004700, - 'blue': #003045, - 'pink': #400025, - 'yellow': #4d4100, - 'orange': #6b4200, - 'red': #520000, - 'purple': #38003d, - 'grey': #292929, + 'default': hsl(198.3, 100%, 13.5%), + 'green': hsl(120, 100%, 13.9%), + 'blue': hsl(198.3, 100%, 13.5%), + 'pink': hsl(325.3, 100%, 12.5%), + 'yellow': hsl(50.6, 100%, 15.1%), + 'orange': hsl(37, 100%, 21%), + 'red': hsl(0, 100%, 16.1%), + 'purple': hsl(295.1, 100%, 12%), + 'grey': hsl(0, 0%, 16.1%), ); $alert-major-header-colors: ( - 'default': #33d5ff, - 'green': #00ff80, - 'blue': #33d5ff, - 'pink': #ff5297, - 'yellow': #fff4e0, - 'orange': #feefe7, - 'red': #ff5297, - 'purple': #c7a1f7, - 'grey': #ff5297, + 'default': hsl(192.4, 100%, 60%), + 'green': hsl(150.1, 100%, 50%), + 'blue': hsl(192.4, 100%, 60%), + 'pink': hsl(336.1, 100%, 66.1%), + 'yellow': hsl(38.7, 100%, 93.9%), + 'orange': hsl(20.9, 92%, 95.1%), + 'red': hsl(336.1, 100%, 66.1%), + 'purple': hsl(266.5, 84.3%, 80%), + 'grey': hsl(336.1, 100%, 66.1%), ); $alert-subheader-header-colors: ( - 'default': #ff5297, - 'green': #ff85b5, - 'blue': #ff5297, - 'pink': #33d5ff, - 'yellow': #33d5ff, - 'orange': #33d5ff, - 'red': #33d5ff, - 'purple': #33d5ff, - 'grey': #33d5ff, + 'default': hsl(336.1, 100%, 66.1%), + 'green': hsl(336.4, 100%, 76.1%), + 'blue': hsl(336.1, 100%, 66.1%), + 'pink': hsl(192.4, 100%, 60%), + 'yellow': hsl(192.4, 100%, 60%), + 'orange': hsl(192.4, 100%, 60%), + 'red': hsl(192.4, 100%, 60%), + 'purple': hsl(192.4, 100%, 60%), + 'grey': hsl(192.4, 100%, 60%), ); $border-width: 4; @@ -1111,8 +1111,8 @@ $border-width-px: $border-width * 1px; } .major_announcement_text { - color: #eaeaea; - background-color: #131313; + color: hsl(0, 0%, 91.8%); + background-color: hsl(0, 0%, 7.5%); font-weight: bold; font-size: 100%; text-align: left; @@ -1133,8 +1133,8 @@ $border-width-px: $border-width * 1px; } .minor_announcement_text { - background-color: #202020; - color: #eaeaea; + background-color: hsl(0, 0%, 12.5%); + color: hsl(0, 0%, 91.8%); padding: 0.5rem 0.5rem; text-align: left; font-size: 100%; @@ -1147,18 +1147,18 @@ $border-width-px: $border-width * 1px; } .ooc_alert { - background: #4d4100; - border: 1px solid #cca300; + background: hsl(50.6, 100%, 15.1%); + border: 1px solid hsl(47.9, 100%, 40%); margin: 0.5em; padding: 0.5em 0.5em 0.5em 0.2em; - color: #ffffff; + color: hsl(0, 0%, 100%); font-weight: bold; display: flex; flex-direction: column; } .ooc_announcement_text { - color: #cca300; + color: hsl(47.9, 100%, 40%); padding: 0.5em 0 0 0.35em; display: flex; flex-direction: column; @@ -1166,7 +1166,7 @@ $border-width-px: $border-width * 1px; @each $color-name, $color-value in $alert-stripe-colors { .chat_alert_#{$color-name} { - color: #ffffff; + color: hsl(0, 0%, 100%); padding: 0.5rem 0.5rem; box-shadow: none; font-weight: bold; diff --git a/tgui/packages/tgui-panel/styles/tgchat/chat-light.scss b/tgui/packages/tgui-panel/styles/tgchat/chat-light.scss index 4efa080ced03a..3db23507b56ae 100644 --- a/tgui/packages/tgui-panel/styles/tgchat/chat-light.scss +++ b/tgui/packages/tgui-panel/styles/tgchat/chat-light.scss @@ -11,7 +11,7 @@ body { padding: 0; margin: 0; height: 100%; - color: #000000; + color: hsl(0, 0%, 0%); } body { @@ -45,15 +45,15 @@ img.icon { } a { - color: #0000ff; + color: hsl(240, 100%, 50%); } a.visited { - color: #ff00ff; + color: hsl(300, 100%, 50%); } a:visited { - color: #ff00ff; + color: hsl(300, 100%, 50%); } a.popt { @@ -157,7 +157,7 @@ a.popt { } .highlightPopup input.highlightColor { - background-color: #ffff00; + background-color: hsl(60, 100%, 50%); } .highlightPopup input.highlightTermSubmit { @@ -217,7 +217,7 @@ a.popt { /* MOTD */ .motd { - color: #638500; + color: hsl(75.3, 100%, 26.1%); font-family: Verdana, sans-serif; white-space: normal; } @@ -228,7 +228,7 @@ a.popt { .motd h4, .motd h5, .motd h6 { - color: #638500; + color: hsl(75.3, 100%, 26.1%); text-decoration: underline; } @@ -237,7 +237,7 @@ a.popt { .motd a:visited, .motd a:active, .motd a:hover { - color: #638500; + color: hsl(75.3, 100%, 26.1%); } /* ADD HERE FOR BOLD */ @@ -273,13 +273,13 @@ h3, h4, h5, h6 { - color: #0000ff; + color: hsl(240, 100%, 50%); font-family: Georgia, Verdana, sans-serif; } h1.alert, h2.alert { - color: #000000; + color: hsl(0, 0%, 0%); } em { @@ -288,27 +288,27 @@ em { } .ooc { - color: #002eb8; + color: hsl(225, 100%, 36.1%); font-weight: bold; } .adminobserverooc { - color: #0099cc; + color: hsl(195, 100%, 40%); font-weight: bold; } .adminooc { - color: #700038; + color: hsl(330, 100%, 22%); font-weight: bold; } .adminsay { - color: #ff4500; + color: hsl(16.2, 100%, 50%); font-weight: bold; } .admin { - color: #4473ff; + color: hsl(224.9, 100%, 63.3%); font-weight: bold; } @@ -324,90 +324,90 @@ em { } .deadsay { - color: #5c00e6; + color: hsl(264, 100%, 45.1%); } .binarysay { - color: #20c20e; - background-color: #000000; + color: hsl(114, 86.5%, 40.8%); + background-color: hsl(0, 0%, 0%); display: block; } .binarysay a { - color: #00ff00; + color: hsl(120, 100%, 50%); } .binarysay a:active, .binarysay a:visited { - color: #88ff88; + color: hsl(120, 100%, 76.7%); } .radio { - color: #008000; + color: hsl(120, 100%, 25.1%); } .sciradio { - color: #993399; + color: hsl(300, 50%, 40%); } .comradio { - color: #948f02; + color: hsl(57.9, 97.3%, 29.4%); } .secradio { - color: #a30000; + color: hsl(0, 100%, 32%); } .medradio { - color: #337296; + color: hsl(201.8, 49.3%, 39.4%); } .engradio { - color: #fb5613; + color: hsl(17.3, 96.7%, 52.9%); } .suppradio { - color: #a8732b; + color: hsl(34.6, 59.2%, 41.4%); } .servradio { - color: #6eaa2c; + color: hsl(88.6, 58.9%, 42%); } .syndradio { - color: #6d3f40; + color: hsl(358.7, 26.7%, 33.7%); } .gangradio { - color: #ac2ea1; + color: hsl(305.2, 57.8%, 42.7%); } .centcomradio { - color: #686868; + color: hsl(0, 0%, 40.8%); } .aiprivradio { - color: #ff00ff; + color: hsl(300, 100%, 50%); } .enteradio { - color: #5c8a87; + color: hsl(176.1, 20%, 45.1%); } .redteamradio { - color: #ff0000 !important; + color: hsl(0, 100%, 50%) !important; } .blueteamradio { - color: #0000ff !important; + color: hsl(240, 100%, 50%) !important; } .greenteamradio { - color: #00ff00 !important; + color: hsl(120, 100%, 50%) !important; } .yellowteamradio { - color: #d1ba22 !important; + color: hsl(52.1, 72%, 47.6%) !important; } .yell { @@ -415,345 +415,345 @@ em { } .alert { - color: #ff0000; + color: hsl(0, 100%, 50%); } h1.alert, h2.alert { - color: #000000; + color: hsl(0, 0%, 0%); } .userdanger { - color: #ff0000; + color: hsl(0, 100%, 50%); font-weight: bold; font-size: 185%; } .bolddanger { - color: #ff0000; + color: hsl(0, 100%, 50%); font-weight: bold; } .danger { - color: #ff0000; + color: hsl(0, 100%, 50%); } .tinydanger { - color: #ff0000; + color: hsl(0, 100%, 50%); font-size: 85%; } .smalldanger { - color: #ff0000; + color: hsl(0, 100%, 50%); font-size: 90%; } .warning { - color: #ff0000; + color: hsl(0, 100%, 50%); font-style: italic; } .alertwarning { - color: #ff0000; + color: hsl(0, 100%, 50%); font-weight: bold; } .boldwarning { - color: #ff0000; + color: hsl(0, 100%, 50%); font-style: italic; font-weight: bold; } .announce { - color: #228b22; + color: hsl(120, 60.7%, 33.9%); font-weight: bold; } .boldannounce { - color: #ff0000; + color: hsl(0, 100%, 50%); font-weight: bold; } .minorannounce { - color: #ff0000; + color: hsl(0, 100%, 50%); font-weight: bold; font-size: 185%; } .minoralert { - color: #000000; + color: hsl(0, 0%, 0%); font-size: 125%; } .priorityannounce { - color: #000000; + color: hsl(0, 0%, 0%); font-weight: bold; font-size: 225%; } .prioritytitle { - color: #0000ff; + color: hsl(240, 100%, 50%); font-weight: bold; font-size: 185%; } .priorityalert { - color: #ff0000; + color: hsl(0, 100%, 50%); font-size: 140%; } .greenannounce { - color: #00ff00; + color: hsl(120, 100%, 50%); font-weight: bold; } .rose { - color: #ff5050; + color: hsl(0, 100%, 65.7%); } .info { - color: #0000cc; + color: hsl(240, 100%, 40%); } .notice { - color: #000099; + color: hsl(240, 100%, 30%); } .tinynotice { - color: #000099; + color: hsl(240, 100%, 30%); font-size: 85%; } .tinynoticeital { - color: #000099; + color: hsl(240, 100%, 30%); font-style: italic; font-size: 85%; } .smallnotice { - color: #000099; + color: hsl(240, 100%, 30%); font-size: 90%; } .smallnoticeital { - color: #000099; + color: hsl(240, 100%, 30%); font-style: italic; font-size: 90%; } .boldnotice { - color: #000099; + color: hsl(240, 100%, 30%); font-weight: bold; } .hear { - color: #000099; + color: hsl(240, 100%, 30%); font-style: italic; } .adminnotice { - color: #0000ff; + color: hsl(240, 100%, 50%); } .adminhelp { - color: #ff0000; + color: hsl(0, 100%, 50%); font-weight: bold; } .unconscious { - color: #0000ff; + color: hsl(240, 100%, 50%); font-weight: bold; } .suicide { - color: #ff5050; + color: hsl(0, 100%, 65.7%); font-style: italic; } .green { - color: #03ff39; + color: hsl(132.9, 100%, 50.6%); } .grey { - color: #838383; + color: hsl(0, 0%, 51.4%); } .red { - color: #ff0000; + color: hsl(0, 100%, 50%); } .blue { - color: #0000ff; + color: hsl(240, 100%, 50%); } .nicegreen { - color: #14a833; + color: hsl(132.6, 78.7%, 36.9%); } .boldnicegreen { - color: #14a833; + color: hsl(132.6, 78.7%, 36.9%); font-weight: bold; } .cult { - color: #973e3b; + color: hsl(2, 43.8%, 41.2%); } .cultitalic { - color: #973e3b; + color: hsl(2, 43.8%, 41.2%); font-style: italic; } .cult_bold { - color: #973e3b; + color: hsl(2, 43.8%, 41.2%); font-style: italic; font-weight: bold; } .cult_bold_italic { - color: #973e3b; + color: hsl(2, 43.8%, 41.2%); font-weight: bold; font-size: 185%; } .cult_large { - color: #973e3b; + color: hsl(2, 43.8%, 41.2%); font-weight: bold; font-size: 185%; } .blob { - color: #ee4000; + color: hsl(16.1, 100%, 46.7%); } .blobannounce { - color: #323f1c; + color: hsl(82.3, 38.5%, 17.8%); font-weight: bold; font-size: 185%; } .narsie { - color: #973e3b; + color: hsl(2, 43.8%, 41.2%); font-weight: bold; font-size: 925%; } .narsiesmall { - color: #973e3b; + color: hsl(2, 43.8%, 41.2%); font-weight: bold; font-size: 370%; } .colossus { - color: #7f282a; + color: hsl(358.6, 52.1%, 32.7%); font-size: 310%; } .hierophant { - color: #660099; + color: hsl(280, 100%, 30%); font-weight: bold; font-style: italic; } .hierophant_warning { - color: #660099; + color: hsl(280, 100%, 30%); font-style: italic; } .purple { - color: #5e2d79; + color: hsl(278.7, 45.8%, 32.5%); } .holoparasite { - color: #35333a; + color: hsl(257.1, 6.4%, 21.4%); } .revennotice { - color: #1d2953; + color: hsl(226.7, 48.2%, 22%); } .revenboldnotice { - color: #1d2953; + color: hsl(226.7, 48.2%, 22%); font-weight: bold; } .revenbignotice { - color: #1d2953; + color: hsl(226.7, 48.2%, 22%); font-weight: bold; font-size: 185%; } .revenminor { - color: #823abb; + color: hsl(273.5, 52.7%, 48%); } .revenwarning { - color: #760fbb; + color: hsl(275.9, 85.1%, 39.6%); font-style: italic; } .revendanger { - color: #760fbb; + color: hsl(275.9, 85.1%, 39.6%); font-weight: bold; font-size: 185%; } .deconversion_message { - color: #5000a0; + color: hsl(270, 100%, 31.4%); font-size: 185%; font-style: italic; } .ghostalert { - color: #5c00e6; + color: hsl(264, 100%, 45.1%); font-style: italic; font-weight: bold; } .alien { - color: #543354; + color: hsl(300, 24.4%, 26.5%); } .noticealien { - color: #00c000; + color: hsl(120, 100%, 37.6%); } .alertalien { - color: #00c000; + color: hsl(120, 100%, 37.6%); font-weight: bold; } .changeling { - color: #800080; + color: hsl(300, 100%, 25.1%); font-style: italic; } .alertsyndie { - color: #ff0000; + color: hsl(0, 100%, 50%); font-size: 185%; font-weight: bold; } .spiderbroodmother { - color: #4d004d; + color: hsl(300, 100%, 15.1%); font-weight: bold; font-size: 185%; } .spiderbreacher { - color: #804b02; + color: hsl(34.8, 96.9%, 25.5%); font-weight: bold; font-size: 140%; } .spiderscout { - color: #0c0674; + color: hsl(243.3, 90.2%, 23.9%); font-weight: bold; font-size: 120%; } .interface { - color: #330033; + color: hsl(300, 100%, 10%); } .sans { @@ -769,7 +769,7 @@ h2.alert { } .tape_recorder { - color: #800000; + color: hsl(0, 100%, 25.1%); font-family: 'Courier New', cursive, sans-serif; } @@ -804,17 +804,17 @@ h2.alert { } .greentext { - color: #00ff00; + color: hsl(120, 100%, 50%); font-size: 185%; } .redtext { - color: #ff0000; + color: hsl(0, 100%, 50%); font-size: 185%; } .clown { - color: #ff69bf; + color: hsl(325.6, 100%, 70.6%); font-size: 160%; font-family: 'Comic Sans MS', cursive, sans-serif; font-weight: bold; @@ -826,13 +826,13 @@ h2.alert { } .his_grace { - color: #15d512; + color: hsl(119.1, 84.4%, 45.3%); font-family: 'Courier New', cursive, sans-serif; font-style: italic; } .hypnophrase { - color: #0d0d0d; + color: hsl(0, 0%, 5.1%); font-weight: bold; animation: hypnocolor 1500ms infinite; animation-direction: alternate; @@ -840,43 +840,43 @@ h2.alert { @keyframes hypnocolor { 0% { - color: #0d0d0d; + color: hsl(0, 0%, 5.1%); } 25% { - color: #410194; + color: hsl(266.1, 98.7%, 29.2%); } 50% { - color: #7f17d8; + color: hsl(272.3, 80.8%, 46.9%); } 75% { - color: #410194; + color: hsl(266.1, 98.7%, 29.2%); } 100% { - color: #3bb5d3; + color: hsl(191.8, 63.3%, 52.9%); } } .phobia { - color: #dd0000; + color: hsl(0, 100%, 43.3%); font-weight: bold; animation: phobia 750ms infinite; } @keyframes phobia { 0% { - color: #0d0d0d; + color: hsl(0, 0%, 5.1%); } 50% { - color: #dd0000; + color: hsl(0, 100%, 43.3%); } 100% { - color: #0d0d0d; + color: hsl(0, 0%, 5.1%); } } @@ -894,7 +894,7 @@ h2.alert { } .memo { - color: #638500; + color: hsl(75.3, 100%, 26.1%); text-align: center; } @@ -904,35 +904,35 @@ h2.alert { } .abductor { - color: #800080; + color: hsl(300, 100%, 25.1%); font-style: italic; } .mind_control { - color: #a00d6f; + color: hsl(320, 85%, 33.9%); font-size: 100%; font-weight: bold; font-style: italic; } .slime { - color: #00ced1; + color: hsl(180.9, 100%, 41%); } .drone { - color: #848482; + color: hsl(60, 0.8%, 51.4%); } .monkey { - color: #975032; + color: hsl(17.8, 50.2%, 39.4%); } .swarmer { - color: #2c75ff; + color: hsl(219.2, 100%, 58.6%); } .resonate { - color: #298f85; + color: hsl(174.1, 55.4%, 36.1%); } .upside_down { @@ -985,8 +985,8 @@ h2.alert { } .examine_block { - background: #f2f7fa; - border: 1px solid #111a27; + background: hsl(202.5, 44.4%, 96.5%); + border: 1px solid hsl(215.5, 39.3%, 11%); margin: 0.5em; padding: 0.5em 0.75em; } @@ -1008,7 +1008,7 @@ h2.alert { .separator::after { content: ''; flex: 1; - border-bottom: 1px solid #111a27; + border-bottom: 1px solid hsl(215.5, 39.3%, 11%); } .separator:not(:empty)::before { @@ -1059,51 +1059,51 @@ h2.alert { /*DOPPLER ADDITION END*/ $alert-stripe-colors: ( - 'default': #b3bfff, - 'green': #adffad, - 'blue': #b3bfff, - 'pink': #ffb3df, - 'yellow': #fff3b3, - 'orange': #ffe2b3, - 'red': #ffb3b3, - 'purple': #fac2ff, - 'grey': #e3e3e3, + 'default': hsl(230.5, 100%, 85.1%), + 'green': hsl(120, 100%, 83.9%), + 'blue': hsl(230.5, 100%, 85.1%), + 'pink': hsl(325.3, 100%, 85.1%), + 'yellow': hsl(50.5, 100%, 85.1%), + 'orange': hsl(37.1, 100%, 85.1%), + 'red': hsl(0, 100%, 85.1%), + 'purple': hsl(295.1, 100%, 88%), + 'grey': hsl(0, 0%, 89%), ); $alert-stripe-alternate-colors: ( - 'default': #bdc8ff, - 'green': #bdffbd, - 'blue': #bdc8ff, - 'pink': #ffc2e5, - 'yellow': #fff5c2, - 'orange': #ffe8c2, - 'red': #ffc2c2, - 'purple': #fbd1ff, - 'grey': #ebebeb, + 'default': hsl(230, 100%, 87.1%), + 'green': hsl(120, 100%, 87.1%), + 'blue': hsl(230, 100%, 87.1%), + 'pink': hsl(325.6, 100%, 88%), + 'yellow': hsl(50.2, 100%, 88%), + 'orange': hsl(37.4, 100%, 88%), + 'red': hsl(0, 100%, 88%), + 'purple': hsl(294.8, 100%, 91%), + 'grey': hsl(0, 0%, 92.2%), ); $alert-major-header-colors: ( - 'default': #003061, - 'green': #005229, - 'blue': #003061, - 'pink': #800033, - 'yellow': #754900, - 'orange': #823208, - 'red': #800029, - 'purple': #450d8c, - 'grey': #800033, + 'default': hsl(210.3, 100%, 19%), + 'green': hsl(150, 100%, 16.1%), + 'blue': hsl(210.3, 100%, 19%), + 'pink': hsl(336.1, 100%, 25.1%), + 'yellow': hsl(37.4, 100%, 22.9%), + 'orange': hsl(20.7, 88.4%, 27.1%), + 'red': hsl(340.8, 100%, 25.1%), + 'purple': hsl(266.5, 83%, 30%), + 'grey': hsl(336.1, 100%, 25.1%), ); $alert-subheader-header-colors: ( - 'default': #6b0020, - 'green': #6b0020, - 'blue': #6b0020, - 'pink': #002c85, - 'yellow': #002c85, - 'orange': #002c85, - 'red': #002c85, - 'purple': #002c85, - 'grey': #002c85, + 'default': hsl(342.1, 100%, 21%), + 'green': hsl(342.1, 100%, 21%), + 'blue': hsl(342.1, 100%, 21%), + 'pink': hsl(220.2, 100%, 26.1%), + 'yellow': hsl(220.2, 100%, 26.1%), + 'orange': hsl(220.2, 100%, 26.1%), + 'red': hsl(220.2, 100%, 26.1%), + 'purple': hsl(220.2, 100%, 26.1%), + 'grey': hsl(220.2, 100%, 26.1%), ); $border-width: 4; @@ -1130,8 +1130,8 @@ $border-width-px: $border-width * 1px; } .major_announcement_text { - color: #131313; - background-color: #eaeaea; + color: hsl(0, 0%, 7.5%); + background-color: hsl(0, 0%, 91.8%); font-weight: bold; font-size: 100%; text-align: left; @@ -1152,8 +1152,8 @@ $border-width-px: $border-width * 1px; } .minor_announcement_text { - background-color: #eaeaea; - color: #202020; + background-color: hsl(0, 0%, 91.8%); + color: hsl(0, 0%, 12.5%); padding: 0.5rem 0.5rem; text-align: left; font-size: 100%; @@ -1166,18 +1166,18 @@ $border-width-px: $border-width * 1px; } .ooc_alert { - background: #bdc8ff; - border: 1px solid #002eb8; + background: hsl(230, 100%, 87.1%); + border: 1px solid hsl(225, 100%, 36.1%); margin: 0.5em; padding: 0.5em 0.5em 0.5em 0.2em; - color: #00283a; + color: hsl(198.6, 100%, 11.4%); font-weight: bold; display: flex; flex-direction: column; } .ooc_announcement_text { - color: #002eb8; + color: hsl(225, 100%, 36.1%); padding: 0.5em 0 0 0.35em; display: flex; flex-direction: column; @@ -1185,7 +1185,7 @@ $border-width-px: $border-width * 1px; @each $color-name, $color-value in $alert-stripe-colors { .chat_alert_#{$color-name} { - color: #ffffff; + color: hsl(0, 0%, 100%); padding: 0.5rem 0.5rem; box-shadow: none; font-weight: bold; diff --git a/tgui/packages/tgui-panel/styles/themes/light.scss b/tgui/packages/tgui-panel/styles/themes/light.scss index f8bfd67ee934f..7d769abac10ed 100644 --- a/tgui/packages/tgui-panel/styles/themes/light.scss +++ b/tgui/packages/tgui-panel/styles/themes/light.scss @@ -7,21 +7,21 @@ @use 'sass:meta'; @use '~tgui/styles/colors.scss' with ( - $primary: #ffffff, + $primary: hsl(0, 0%, 100%), $bg-lightness: -25%, $fg-lightness: -10%, - $label: #3b3b3b, + $label: hsl(0, 0%, 23.1%), // Makes button look actually grey due to weird maths. - $grey: #ffffff, + $grey: hsl(0, 0%, 100%), // Commenting out color maps will adjust all colors based on the lightness // settings above, but will add extra 10KB to the theme. // $fg-map-keys: (), // $bg-map-keys: (), ); @use '~tgui/styles/base.scss' with ( - $color-fg: #000000, - $color-bg: #eeeeee, - $color-bg-section: #ffffff, + $color-fg: hsl(0, 0%, 0%), + $color-bg: hsl(0, 0%, 93.3%), + $color-bg-section: hsl(0, 0%, 100%), $color-bg-grad-spread: 0% ); @@ -33,7 +33,7 @@ // Components @include meta.load-css( - '~tgui/styles/components/Tabs.scss', + 'pkg:tgui-styles/components/Tabs', $with: ( 'text-color': rgba(0, 0, 0, 0.5), 'color-default': rgba(0, 0, 0, 1), @@ -41,35 +41,35 @@ 'tab-color-hovered': rgba(0, 0, 0, 0.075) ) ); - @include meta.load-css('~tgui/styles/components/Section.scss'); + @include meta.load-css('pkg:tgui-styles/components/Section'); @include meta.load-css( - '~tgui/styles/components/Button.scss', + 'pkg:tgui-styles/components/Button', $with: ( - 'color-default': #bbbbbb, - 'color-disabled': #363636, - 'color-selected': #0668b8, - 'color-caution': #be6209, - 'color-danger': #9a9d00, + 'color-default': hsl(0, 0%, 73.3%), + 'color-disabled': hsl(0, 0%, 21.2%), + 'color-selected': hsl(204, 94%, 35.3%), + 'color-caution': hsl(28, 91%, 38.2%), + 'color-danger': hsl(62, 100%, 30.2%), 'color-transparent-text': rgba(0, 0, 0, 0.5) ) ); @include meta.load-css( - '~tgui/styles/components/Input.scss', + 'pkg:tgui-styles/components/Input', $with: ( 'border-color': colors.fg(colors.$label), - 'background-color': #e6e6e6 + 'background-color': hsl(0, 0%, 90.2%) ) ); - @include meta.load-css('~tgui/styles/components/NumberInput.scss'); - @include meta.load-css('~tgui/styles/components/TextArea.scss'); - @include meta.load-css('~tgui/styles/components/Knob.scss'); - @include meta.load-css('~tgui/styles/components/Slider.scss'); - @include meta.load-css('~tgui/styles/components/ProgressBar.scss'); + @include meta.load-css('pkg:tgui-styles/components/NumberInput'); + @include meta.load-css('pkg:tgui-styles/components/TextArea'); + @include meta.load-css('pkg:tgui-styles/components/Knob'); + @include meta.load-css('pkg:tgui-styles/components/Slider'); + @include meta.load-css('pkg:tgui-styles/components/ProgressBar'); // Components specific to tgui-panel @include meta.load-css( '../components/Chat.scss', - $with: ('text-color': #000000) + $with: ('text-color': hsl(0, 0%, 0%)) ); // Layouts diff --git a/tgui/packages/tgui-say/package.json b/tgui/packages/tgui-say/package.json index 5c8eaf390a96c..d8c09604c1b26 100644 --- a/tgui/packages/tgui-say/package.json +++ b/tgui/packages/tgui-say/package.json @@ -9,6 +9,7 @@ "react": "^18.3.1", "react-dom": "^18.3.1", "tgui": "workspace:*", - "tgui-polyfill": "workspace:*" + "tgui-polyfill": "workspace:*", + "tgui-styles": "^0.0.10" } } diff --git a/tgui/packages/tgui-say/styles/colors.scss b/tgui/packages/tgui-say/styles/colors.scss index 9a6c1beb265ad..05cef9b550991 100644 --- a/tgui/packages/tgui-say/styles/colors.scss +++ b/tgui/packages/tgui-say/styles/colors.scss @@ -1,31 +1,31 @@ @use 'sass:map'; -$background: #131313; -$button: #1f1f1f; -$lightMode: #ffffff; -$lightBorder: #bbbbbb; -$lightHover: #eaeaea; +$background: hsl(0, 0%, 7.5%); +$button: hsl(0, 0%, 12.2%); +$lightMode: hsl(0, 0%, 100%); +$lightBorder: hsl(0, 0%, 73.3%); +$lightHover: hsl(0, 0%, 91.8%); $_channel_map: ( - 'Admin': #ffbbff, - 'AI': #d65d95, - 'CCom': #2681a5, - 'Cling': #4c701f, - 'Cmd': #fcdf03, - 'Engi': #f37746, - 'Hive': #855d85, - 'io': #1e90ff, - 'Me': #5975da, - 'Med': #57b8f0, - 'OOC': #cca300, - 'Ent': #5c8a87, - 'Radio': #1ecc43, - 'Say': #a4bad6, - 'Sci': #c68cfa, - 'Sec': #dd3535, - 'Supp': #b88646, - 'Svc': #6ca729, - 'Synd': #8f4a4b, + 'Admin': hsl(300, 100%, 86.7%), + 'AI': hsl(332.2, 59.6%, 60.2%), + 'CCom': hsl(197, 62.6%, 39.8%), + 'Cling': hsl(86.7, 56.6%, 28%), + 'Cmd': hsl(53, 97.6%, 50%), + 'Engi': hsl(17, 87.8%, 61.4%), + 'Hive': hsl(300, 17.7%, 44.3%), + 'io': hsl(209.6, 100%, 55.9%), + 'Me': hsl(227, 63.5%, 60.2%), + 'Med': hsl(202, 83.6%, 64.1%), + 'OOC': hsl(47.9, 100%, 40%), + 'Ent': hsl(176.1, 20%, 45.1%), + 'Radio': hsl(132.8, 74.4%, 45.9%), + 'Say': hsl(213.6, 37.9%, 74.1%), + 'Sci': hsl(271.6, 91.7%, 76.5%), + 'Sec': hsl(0, 71.2%, 53.7%), + 'Supp': hsl(33.7, 44.9%, 49.8%), + 'Svc': hsl(88.1, 60.6%, 40.8%), + 'Synd': hsl(359.1, 31.8%, 42.5%), // DOPPLER EDIT ADDITION START 'Whis': #7c7fd9, 'LOOC': #ffceb6, diff --git a/tgui/packages/tgui-say/styles/main.scss b/tgui/packages/tgui-say/styles/main.scss index 8c7ca885c9047..8e164aa21fa7f 100644 --- a/tgui/packages/tgui-say/styles/main.scss +++ b/tgui/packages/tgui-say/styles/main.scss @@ -7,7 +7,7 @@ // Atomic styles @include meta.load-css('~tgui/styles/atomic/text.scss'); // External styles -@include meta.load-css('~tgui/styles/components/TextArea.scss'); +@include meta.load-css('pkg:tgui-styles/components/TextArea'); // Local styles @include meta.load-css('./button.scss'); @include meta.load-css('./content.scss'); diff --git a/tgui/packages/tgui/interfaces/ApcControl.jsx b/tgui/packages/tgui/interfaces/ApcControl.jsx index caeb5ee1bed6e..16c74b8d955c4 100644 --- a/tgui/packages/tgui/interfaces/ApcControl.jsx +++ b/tgui/packages/tgui/interfaces/ApcControl.jsx @@ -1,5 +1,4 @@ import { map, sortBy } from 'common/collections'; -import { flow } from 'common/fp'; import { useState } from 'react'; import { Box, @@ -11,6 +10,7 @@ import { Table, Tabs, } from 'tgui-core/components'; +import { flow } from 'tgui-core/fp'; import { useBackend, useLocalState } from '../backend'; import { Window } from '../layouts'; diff --git a/tgui/packages/tgui/interfaces/Aquarium.tsx b/tgui/packages/tgui/interfaces/Aquarium.tsx index 592a2af2ea839..bbdc753263417 100644 --- a/tgui/packages/tgui/interfaces/Aquarium.tsx +++ b/tgui/packages/tgui/interfaces/Aquarium.tsx @@ -1,4 +1,3 @@ -import { capitalizeFirst } from 'common/string'; import { Box, Button, @@ -12,6 +11,7 @@ import { Stack, } from 'tgui-core/components'; import { BooleanLike } from 'tgui-core/react'; +import { capitalizeFirst } from 'tgui-core/string'; import { useBackend } from '../backend'; import { Window } from '../layouts'; diff --git a/tgui/packages/tgui/interfaces/BigManipulator.tsx b/tgui/packages/tgui/interfaces/BigManipulator.tsx index 9b0f6a3a3f6cc..ffca97b25346b 100644 --- a/tgui/packages/tgui/interfaces/BigManipulator.tsx +++ b/tgui/packages/tgui/interfaces/BigManipulator.tsx @@ -1,4 +1,4 @@ -import { BooleanLike } from 'common/react'; +import { BooleanLike } from 'tgui-core/react'; import { useBackend } from '../backend'; import { Button, Section, Stack, Table } from '../components'; diff --git a/tgui/packages/tgui/interfaces/Biogenerator.tsx b/tgui/packages/tgui/interfaces/Biogenerator.tsx index f87eb73d903f9..a978287c04530 100644 --- a/tgui/packages/tgui/interfaces/Biogenerator.tsx +++ b/tgui/packages/tgui/interfaces/Biogenerator.tsx @@ -12,8 +12,7 @@ import { Table, Tabs, } from 'tgui-core/components'; -import { BooleanLike } from 'tgui-core/react'; -import { classes } from 'tgui-core/react'; +import { BooleanLike, classes } from 'tgui-core/react'; import { useBackend } from '../backend'; import { Window } from '../layouts'; diff --git a/tgui/packages/tgui/interfaces/ChemDispenser.tsx b/tgui/packages/tgui/interfaces/ChemDispenser.tsx index 1f5f8b1b37b73..6beaf45acb022 100644 --- a/tgui/packages/tgui/interfaces/ChemDispenser.tsx +++ b/tgui/packages/tgui/interfaces/ChemDispenser.tsx @@ -191,12 +191,11 @@ export const ChemDispenser = (props) => { width="129.5px" lineHeight={1.75} tooltip={'pH: ' + chemical.pH} + style={{ + textShadow: '1px 1px 0 black', + }} backgroundColor={ - recipeReagents.includes(chemical.id) - ? showPhCol - ? 'black' - : 'green' - : 'default' + recipeReagents.includes(chemical.id) ? 'green' : 'default' } onClick={() => act('dispense', { @@ -204,7 +203,14 @@ export const ChemDispenser = (props) => { }) } > - {chemical.title} + + {chemical.title} + ))} diff --git a/tgui/packages/tgui/interfaces/CrewManifest.jsx b/tgui/packages/tgui/interfaces/CrewManifest.jsx index 6557dda31f4b9..4039eb8fc3a2f 100644 --- a/tgui/packages/tgui/interfaces/CrewManifest.jsx +++ b/tgui/packages/tgui/interfaces/CrewManifest.jsx @@ -1,5 +1,5 @@ import { Icon, Section, Table, Tooltip } from 'tgui-core/components'; -import { classes } from '../../common/react'; +import { classes } from 'tgui-core/react'; import { useBackend } from '../backend'; import { Window } from '../layouts'; diff --git a/tgui/packages/tgui/interfaces/DeathmatchLobby.tsx b/tgui/packages/tgui/interfaces/DeathmatchLobby.tsx index e7b66093d2099..113704af7e64d 100644 --- a/tgui/packages/tgui/interfaces/DeathmatchLobby.tsx +++ b/tgui/packages/tgui/interfaces/DeathmatchLobby.tsx @@ -1,6 +1,3 @@ -import { BooleanLike } from 'common/react'; - -import { useBackend } from '../backend'; import { Box, Button, @@ -14,7 +11,10 @@ import { Stack, Table, Tooltip, -} from '../components'; +} from 'tgui-core/components'; +import { BooleanLike } from 'tgui-core/react'; + +import { useBackend } from '../backend'; import { ButtonCheckbox } from '../components/Button'; import { Window } from '../layouts'; diff --git a/tgui/packages/tgui/interfaces/DeathmatchPanel.tsx b/tgui/packages/tgui/interfaces/DeathmatchPanel.tsx index 252a6e5123113..3731d927c03b3 100644 --- a/tgui/packages/tgui/interfaces/DeathmatchPanel.tsx +++ b/tgui/packages/tgui/interfaces/DeathmatchPanel.tsx @@ -1,6 +1,3 @@ -import { BooleanLike } from 'common/react'; - -import { useBackend } from '../backend'; import { Button, Dropdown, @@ -10,7 +7,10 @@ import { Stack, Table, Tooltip, -} from '../components'; +} from 'tgui-core/components'; +import { BooleanLike } from 'tgui-core/react'; + +import { useBackend } from '../backend'; import { Window } from '../layouts'; type Lobby = { diff --git a/tgui/packages/tgui/interfaces/DecalPainter.tsx b/tgui/packages/tgui/interfaces/DecalPainter.tsx index dd835773960c7..5b45db3a4ddad 100644 --- a/tgui/packages/tgui/interfaces/DecalPainter.tsx +++ b/tgui/packages/tgui/interfaces/DecalPainter.tsx @@ -1,5 +1,6 @@ +import { Button, ColorBox, Flex, Section } from 'tgui-core/components'; + import { useBackend } from '../backend'; -import { Button, ColorBox, Flex, Section } from '../components'; import { Window } from '../layouts'; type DecalInfo = { diff --git a/tgui/packages/tgui/interfaces/DestinationTagger.tsx b/tgui/packages/tgui/interfaces/DestinationTagger.tsx index 5326f93e01bac..37fe5d3c1553f 100644 --- a/tgui/packages/tgui/interfaces/DestinationTagger.tsx +++ b/tgui/packages/tgui/interfaces/DestinationTagger.tsx @@ -1,7 +1,7 @@ import { map, sortBy } from 'common/collections'; +import { Button, Section, Stack } from 'tgui-core/components'; import { useBackend } from '../backend'; -import { Button, Section, Stack } from '../components'; import { Window } from '../layouts'; type DestinationTaggerData = { diff --git a/tgui/packages/tgui/interfaces/DestructiveAnalyzer.tsx b/tgui/packages/tgui/interfaces/DestructiveAnalyzer.tsx index 85a895a03e975..fda2dd32c8896 100644 --- a/tgui/packages/tgui/interfaces/DestructiveAnalyzer.tsx +++ b/tgui/packages/tgui/interfaces/DestructiveAnalyzer.tsx @@ -1,7 +1,7 @@ -import { BooleanLike } from 'common/react'; +import { Box, Button, Image, NoticeBox, Section } from 'tgui-core/components'; +import { BooleanLike } from 'tgui-core/react'; import { useBackend } from '../backend'; -import { Box, Button, Image, NoticeBox, Section } from '../components'; import { Window } from '../layouts'; type Data = { diff --git a/tgui/packages/tgui/interfaces/DisposalUnit.jsx b/tgui/packages/tgui/interfaces/DisposalUnit.jsx index f163c3c1c2c22..08bb0a9ad19ca 100644 --- a/tgui/packages/tgui/interfaces/DisposalUnit.jsx +++ b/tgui/packages/tgui/interfaces/DisposalUnit.jsx @@ -1,5 +1,11 @@ +import { + Button, + LabeledList, + ProgressBar, + Section, +} from 'tgui-core/components'; + import { useBackend } from '../backend'; -import { Button, LabeledList, ProgressBar, Section } from '../components'; import { Window } from '../layouts'; export const DisposalUnit = (props) => { diff --git a/tgui/packages/tgui/interfaces/DnaVault.tsx b/tgui/packages/tgui/interfaces/DnaVault.tsx index 2b6781d6cf747..42220a7076015 100644 --- a/tgui/packages/tgui/interfaces/DnaVault.tsx +++ b/tgui/packages/tgui/interfaces/DnaVault.tsx @@ -1,6 +1,3 @@ -import { BooleanLike } from 'common/react'; - -import { useBackend } from '../backend'; import { Box, Button, @@ -8,7 +5,10 @@ import { ProgressBar, Section, Stack, -} from '../components'; +} from 'tgui-core/components'; +import { BooleanLike } from 'tgui-core/react'; + +import { useBackend } from '../backend'; import { Window } from '../layouts'; type Data = { diff --git a/tgui/packages/tgui/interfaces/DopplerArray.jsx b/tgui/packages/tgui/interfaces/DopplerArray.jsx index f62fa8de56b71..14bd9b160dfe4 100644 --- a/tgui/packages/tgui/interfaces/DopplerArray.jsx +++ b/tgui/packages/tgui/interfaces/DopplerArray.jsx @@ -1,4 +1,3 @@ -import { useBackend, useSharedState } from '../backend'; import { Box, Button, @@ -8,7 +7,9 @@ import { Section, Stack, Tabs, -} from '../components'; +} from 'tgui-core/components'; + +import { useBackend, useSharedState } from '../backend'; import { Window } from '../layouts'; export const DopplerArray = (props) => { diff --git a/tgui/packages/tgui/interfaces/EightBallVote.tsx b/tgui/packages/tgui/interfaces/EightBallVote.tsx index f85b8724ffefb..c129ae0b083a7 100644 --- a/tgui/packages/tgui/interfaces/EightBallVote.tsx +++ b/tgui/packages/tgui/interfaces/EightBallVote.tsx @@ -1,8 +1,16 @@ -import { BooleanLike } from 'common/react'; -import { toTitleCase } from 'common/string'; +import { + Box, + Button, + Divider, + Flex, + NoticeBox, + Section, + Stack, +} from 'tgui-core/components'; +import { BooleanLike } from 'tgui-core/react'; +import { toTitleCase } from 'tgui-core/string'; import { useBackend } from '../backend'; -import { Box, Button, NoticeBox, Section, Stack } from '../components'; import { Window } from '../layouts'; type Data = { @@ -21,12 +29,22 @@ export function EightBallVote(props) { const { data } = useBackend(); const { shaking } = data; + const idealHeight = shaking ? 265 : 70; return ( - - - {(shaking && ( - No question is currently being asked. - )) || } + + + {!shaking ? ( + + No question is currently being asked. + + ) : ( + <> + + A question is currently being asked! + + + + )} ); @@ -34,19 +52,25 @@ export function EightBallVote(props) { function EightBallVoteQuestion(props) { const { act, data } = useBackend(); - const { question, answers = [] } = data; + const { shaking, question, answers = [] } = data; return ( -
- - "{question}" - +
+ + " + {question} + " + + + + {answers.map((answer) => (
diff --git a/tgui/packages/tgui/interfaces/LanguageMenu.jsx b/tgui/packages/tgui/interfaces/LanguageMenu.jsx index fc5a43feb6133..404ac8484ef99 100644 --- a/tgui/packages/tgui/interfaces/LanguageMenu.jsx +++ b/tgui/packages/tgui/interfaces/LanguageMenu.jsx @@ -1,5 +1,6 @@ +import { Button, LabeledList, Section } from 'tgui-core/components'; + import { useBackend } from '../backend'; -import { Button, LabeledList, Section } from '../components'; import { Window } from '../layouts'; export const LanguageMenu = (props) => { diff --git a/tgui/packages/tgui/interfaces/LaunchpadConsole.tsx b/tgui/packages/tgui/interfaces/LaunchpadConsole.tsx index fdad995589449..e584a9deed0ce 100644 --- a/tgui/packages/tgui/interfaces/LaunchpadConsole.tsx +++ b/tgui/packages/tgui/interfaces/LaunchpadConsole.tsx @@ -1,4 +1,3 @@ -import { useBackend } from '../backend'; import { Box, Button, @@ -9,7 +8,9 @@ import { Section, Stack, Tabs, -} from '../components'; +} from 'tgui-core/components'; + +import { useBackend } from '../backend'; import { Window } from '../layouts'; type Data = { diff --git a/tgui/packages/tgui/interfaces/LaunchpadRemote.tsx b/tgui/packages/tgui/interfaces/LaunchpadRemote.tsx index 5e7d1ba8516b4..8dfa89318eda5 100644 --- a/tgui/packages/tgui/interfaces/LaunchpadRemote.tsx +++ b/tgui/packages/tgui/interfaces/LaunchpadRemote.tsx @@ -1,7 +1,7 @@ -import { BooleanLike } from 'common/react'; +import { NoticeBox } from 'tgui-core/components'; +import { BooleanLike } from 'tgui-core/react'; import { useBackend } from '../backend'; -import { NoticeBox } from '../components'; import { Window } from '../layouts'; import { LaunchpadControl } from './LaunchpadConsole'; diff --git a/tgui/packages/tgui/interfaces/Lawpanel.tsx b/tgui/packages/tgui/interfaces/Lawpanel.tsx index 3ce64868ff8aa..7d72c527ab25a 100644 --- a/tgui/packages/tgui/interfaces/Lawpanel.tsx +++ b/tgui/packages/tgui/interfaces/Lawpanel.tsx @@ -1,6 +1,3 @@ -import { BooleanLike } from 'common/react'; - -import { useBackend } from '../backend'; import { Button, Collapsible, @@ -11,7 +8,10 @@ import { NoticeBox, Section, Stack, -} from '../components'; +} from 'tgui-core/components'; +import { BooleanLike } from 'tgui-core/react'; + +import { useBackend } from '../backend'; import { Window } from '../layouts'; const lawtype_to_color = { diff --git a/tgui/packages/tgui/interfaces/LibraryAdmin.tsx b/tgui/packages/tgui/interfaces/LibraryAdmin.tsx index fd88fdc48fb2f..5e9ead80a6054 100644 --- a/tgui/packages/tgui/interfaces/LibraryAdmin.tsx +++ b/tgui/packages/tgui/interfaces/LibraryAdmin.tsx @@ -1,8 +1,5 @@ import { map, sortBy } from 'common/collections'; -import { capitalize } from 'common/string'; import { useState } from 'react'; - -import { useBackend, useLocalState } from '../backend'; import { Box, Button, @@ -13,7 +10,10 @@ import { Stack, Table, TextArea, -} from '../components'; +} from 'tgui-core/components'; +import { capitalize } from 'tgui-core/string'; + +import { useBackend, useLocalState } from '../backend'; import { Window } from '../layouts'; import { PageSelect } from './LibraryConsole'; diff --git a/tgui/packages/tgui/interfaces/LibraryConsole.jsx b/tgui/packages/tgui/interfaces/LibraryConsole.jsx index de10b3a2e86b0..87d87f9bac84f 100644 --- a/tgui/packages/tgui/interfaces/LibraryConsole.jsx +++ b/tgui/packages/tgui/interfaces/LibraryConsole.jsx @@ -1,8 +1,5 @@ import { map, sortBy } from 'common/collections'; -import { classes } from 'common/react'; import { useState } from 'react'; - -import { useBackend, useLocalState } from '../backend'; import { Box, Button, @@ -16,7 +13,10 @@ import { Section, Stack, Table, -} from '../components'; +} from 'tgui-core/components'; +import { classes } from 'tgui-core/react'; + +import { useBackend, useLocalState } from '../backend'; import { Window } from '../layouts'; import { sanitizeText } from '../sanitize'; diff --git a/tgui/packages/tgui/interfaces/LibraryScanner.jsx b/tgui/packages/tgui/interfaces/LibraryScanner.jsx index efa7156abfbee..3f06b7b3ab36f 100644 --- a/tgui/packages/tgui/interfaces/LibraryScanner.jsx +++ b/tgui/packages/tgui/interfaces/LibraryScanner.jsx @@ -1,5 +1,6 @@ +import { Button, NoticeBox, Section, Stack } from 'tgui-core/components'; + import { useBackend } from '../backend'; -import { Button, NoticeBox, Section, Stack } from '../components'; import { Window } from '../layouts'; export const LibraryScanner = (props) => { diff --git a/tgui/packages/tgui/interfaces/LibraryVisitor.jsx b/tgui/packages/tgui/interfaces/LibraryVisitor.jsx index cb27e42704d98..50ea9bad108c0 100644 --- a/tgui/packages/tgui/interfaces/LibraryVisitor.jsx +++ b/tgui/packages/tgui/interfaces/LibraryVisitor.jsx @@ -1,6 +1,4 @@ import { map, sortBy } from 'common/collections'; - -import { useBackend } from '../backend'; import { Box, Button, @@ -10,7 +8,9 @@ import { Section, Stack, Table, -} from '../components'; +} from 'tgui-core/components'; + +import { useBackend } from '../backend'; import { Window } from '../layouts'; import { PageSelect } from './LibraryConsole'; diff --git a/tgui/packages/tgui/interfaces/LightController.tsx b/tgui/packages/tgui/interfaces/LightController.tsx index 810b644f90f6b..e65104fd9c5a1 100644 --- a/tgui/packages/tgui/interfaces/LightController.tsx +++ b/tgui/packages/tgui/interfaces/LightController.tsx @@ -1,9 +1,17 @@ import { useState } from 'react'; +import { + Box, + Button, + Knob, + Section, + Slider, + Stack, + Tabs, +} from 'tgui-core/components'; import { round } from '../../common/math'; import { BooleanLike, classes } from '../../common/react'; import { useBackend } from '../backend'; -import { Box, Button, Knob, Section, Slider, Stack, Tabs } from '../components'; import { Window } from '../layouts'; enum Direction { diff --git a/tgui/packages/tgui/interfaces/LightSpawn.tsx b/tgui/packages/tgui/interfaces/LightSpawn.tsx index 68e3430d8178e..75c1f2cf07d6c 100644 --- a/tgui/packages/tgui/interfaces/LightSpawn.tsx +++ b/tgui/packages/tgui/interfaces/LightSpawn.tsx @@ -1,8 +1,16 @@ import { useState } from 'react'; +import { + Box, + Button, + Knob, + Section, + Slider, + Stack, + Tabs, +} from 'tgui-core/components'; import { classes } from '../../common/react'; import { useBackend, useLocalState } from '../backend'; -import { Box, Button, Knob, Section, Slider, Stack, Tabs } from '../components'; import { Window } from '../layouts'; enum Direction { diff --git a/tgui/packages/tgui/interfaces/Limbgrower.jsx b/tgui/packages/tgui/interfaces/Limbgrower.jsx index 363b416f12fde..8ee02d086b78e 100644 --- a/tgui/packages/tgui/interfaces/Limbgrower.jsx +++ b/tgui/packages/tgui/interfaces/Limbgrower.jsx @@ -1,4 +1,3 @@ -import { useBackend, useSharedState } from '../backend'; import { Box, Button, @@ -7,7 +6,9 @@ import { LabeledList, Section, Tabs, -} from '../components'; +} from 'tgui-core/components'; + +import { useBackend, useSharedState } from '../backend'; import { Window } from '../layouts'; export const Limbgrower = (props) => { diff --git a/tgui/packages/tgui/interfaces/LingMMITalk.tsx b/tgui/packages/tgui/interfaces/LingMMITalk.tsx index 9f4effb2e663a..fc1f0da7c9e80 100644 --- a/tgui/packages/tgui/interfaces/LingMMITalk.tsx +++ b/tgui/packages/tgui/interfaces/LingMMITalk.tsx @@ -1,7 +1,7 @@ import { useState } from 'react'; +import { Button, ByondUi, Stack, TextArea } from 'tgui-core/components'; import { useBackend } from '../backend'; -import { Button, ByondUi, Stack, TextArea } from '../components'; import { Window } from '../layouts'; type Data = { diff --git a/tgui/packages/tgui/interfaces/LockedSafe.tsx b/tgui/packages/tgui/interfaces/LockedSafe.tsx index ba8d6bc966140..77d042912afe1 100644 --- a/tgui/packages/tgui/interfaces/LockedSafe.tsx +++ b/tgui/packages/tgui/interfaces/LockedSafe.tsx @@ -1,7 +1,7 @@ -import { BooleanLike } from 'common/react'; +import { Box, Flex } from 'tgui-core/components'; +import { BooleanLike } from 'tgui-core/react'; import { useBackend } from '../backend'; -import { Box, Flex } from '../components'; import { Window } from '../layouts'; import { NukeKeypad } from './NuclearBomb'; diff --git a/tgui/packages/tgui/interfaces/LogViewer.tsx b/tgui/packages/tgui/interfaces/LogViewer.tsx index ffdd18a730fe1..0fe5daf5ec783 100644 --- a/tgui/packages/tgui/interfaces/LogViewer.tsx +++ b/tgui/packages/tgui/interfaces/LogViewer.tsx @@ -1,6 +1,4 @@ import { useState } from 'react'; - -import { useBackend } from '../backend'; import { Button, Collapsible, @@ -8,7 +6,9 @@ import { NoticeBox, Section, Stack, -} from '../components'; +} from 'tgui-core/components'; + +import { useBackend } from '../backend'; import { Window } from '../layouts'; type LogViewerData = { diff --git a/tgui/packages/tgui/interfaces/MODpaint.jsx b/tgui/packages/tgui/interfaces/MODpaint.jsx index 7a047b384260c..0d9a56e459eb5 100644 --- a/tgui/packages/tgui/interfaces/MODpaint.jsx +++ b/tgui/packages/tgui/interfaces/MODpaint.jsx @@ -1,6 +1,3 @@ -import { capitalize } from 'common/string'; - -import { useBackend } from '../backend'; import { Box, Button, @@ -9,7 +6,10 @@ import { Section, Slider, Stack, -} from '../components'; +} from 'tgui-core/components'; +import { capitalize } from 'tgui-core/string'; + +import { useBackend } from '../backend'; import { Window } from '../layouts'; const colorToMatrix = (param) => { diff --git a/tgui/packages/tgui/interfaces/MODsuit.tsx b/tgui/packages/tgui/interfaces/MODsuit.tsx index 11d1e294824aa..d2b96a7735c0f 100644 --- a/tgui/packages/tgui/interfaces/MODsuit.tsx +++ b/tgui/packages/tgui/interfaces/MODsuit.tsx @@ -1,7 +1,4 @@ -import { BooleanLike } from 'common/react'; import { useState } from 'react'; - -import { useBackend } from '../backend'; import { AnimatedNumber, Box, @@ -18,32 +15,39 @@ import { Section, Stack, Table, -} from '../components'; +} from 'tgui-core/components'; +import { BooleanLike } from 'tgui-core/react'; + +import { useBackend } from '../backend'; import { formatSiUnit } from '../format'; import { Window } from '../layouts'; type MODsuitData = { // Static ui_theme: string; - control: string; complexity_max: number; - parts: PartData[]; // Dynamic suit_status: SuitStatus; user_status: UserStatus; module_custom_status: ModuleCustomStatus; module_info: Module[]; + control: string; + parts: PartData[]; }; type PartData = { slot: string; name: string; + deployed: BooleanLike; + ref: string; }; type SuitStatus = { core_name: string; - cell_charge_current: number; - cell_charge_max: number; + charge_current: number; + charge_max: number; + chargebar_color: string; + chargebar_string: string; active: BooleanLike; open: BooleanLike; seconds_electrified: number; @@ -53,8 +57,8 @@ type SuitStatus = { complexity: number; selected_module: string; ai_name: string; - has_pai: boolean; - is_ai: boolean; + has_pai: BooleanLike; + is_ai: BooleanLike; link_id: string; link_freq: string; link_call: string; @@ -257,6 +261,20 @@ const ConfigurePinEntry = (props) => { ); }; +// fuck u smartkar configs werent meant to be used as actions 🖕🖕🖕 +// and really u couldnt be bothered to make this and instead used +// the pin entry? 🖕🖕🖕🖕🖕🖕🖕🖕🖕🖕🖕🖕🖕🖕🖕🖕🖕🖕🖕🖕 +const ConfigureButtonEntry = (props) => { + const { name, value, module_ref } = props; + const { act } = useBackend(); + return ( + + + ))} + +
+ ); +} diff --git a/tgui/packages/tgui/interfaces/ScannerGate.jsx b/tgui/packages/tgui/interfaces/ScannerGate.jsx index 51e32cbdc6e67..8eb61cea7f270 100644 --- a/tgui/packages/tgui/interfaces/ScannerGate.jsx +++ b/tgui/packages/tgui/interfaces/ScannerGate.jsx @@ -67,10 +67,6 @@ const SCANNER_GATE_ROUTES = { title: 'Scanner Mode: Nutrition', component: () => ScannerGateNutrition, }, - Contraband: { - title: 'Scanner Mode: Contraband', - component: () => ScannerGateContraband, - }, }; const ScannerGateControl = (props) => { @@ -98,7 +94,6 @@ const ScannerGateControl = (props) => { const ScannerGateOff = (props) => { const { act, data } = useBackend(); - const { contraband_enabled } = data; return ( <> Select a scanning mode below. @@ -127,11 +122,6 @@ const ScannerGateOff = (props) => { content="Nutrition" onClick={() => act('set_mode', { new_mode: 'Nutrition' })} /> -