diff --git a/_maps/RandomRuins/AnywhereRuins/golem_ship.dmm b/_maps/RandomRuins/AnywhereRuins/golem_ship.dmm index 5c36e667456..051aaad259a 100644 --- a/_maps/RandomRuins/AnywhereRuins/golem_ship.dmm +++ b/_maps/RandomRuins/AnywhereRuins/golem_ship.dmm @@ -1,628 +1,1177 @@ //MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE -"a" = ( -/turf/template_noop, -/area/template_noop) -"b" = ( -/turf/closed/wall/mineral/titanium/nodiagonal, +"am" = ( +/obj/structure/table, +/obj/item/tape{ + pixel_x = 2; + pixel_y = -1 + }, +/obj/item/pen/blue{ + pixel_x = -5 + }, +/turf/open/floor/mineral/titanium/purple, /area/ruin/powered/golem_ship) -"c" = ( -/obj/structure/closet/crate, -/obj/item/shovel, -/obj/item/shovel, -/obj/item/shovel, -/obj/item/pickaxe, -/obj/item/pickaxe, -/obj/item/pickaxe, -/obj/item/storage/bag/ore, -/obj/item/storage/bag/ore, -/obj/item/mining_scanner, -/obj/item/flashlight/lantern, -/obj/item/card/id/advanced/mining, +"aU" = ( +/obj/structure/chair/office{ + dir = 4 + }, +/turf/open/floor/wood, +/area/ruin/powered/golem_ship) +"bb" = ( +/obj/structure/frame/computer{ + dir = 4 + }, +/turf/open/floor/mineral/titanium/purple, +/area/ruin/powered/golem_ship) +"bu" = ( +/obj/item/stack/ore/titanium{ + pixel_y = 10; + pixel_x = -10 + }, +/obj/item/stack/ore/iron{ + pixel_y = 10; + pixel_x = 10 + }, +/obj/structure/bed, +/turf/open/floor/wood, +/area/ruin/powered/golem_ship) +"bO" = ( +/obj/structure/reagent_dispensers/plumbed, +/turf/open/floor/mineral/titanium/purple, +/area/ruin/powered/golem_ship) +"ch" = ( +/obj/structure/table, +/obj/item/chisel{ + pixel_y = 8; + pixel_x = -7 + }, +/obj/item/assembly/signaler{ + pixel_y = 12; + pixel_x = 7 + }, +/turf/open/floor/mineral/titanium, +/area/ruin/powered/golem_ship) +"cp" = ( +/obj/structure/railing{ + dir = 8 + }, +/obj/structure/filingcabinet/chestdrawer, +/obj/item/aquarium_prop/treasure{ + pixel_y = 10; + pixel_x = 8 + }, +/obj/item/storage/crayons, +/obj/item/pen{ + pixel_y = -2 + }, +/obj/item/toy/cards/deck, +/obj/item/toy/cards/deck/cas/black, +/obj/item/toy/cards/deck/cas, +/obj/item/toy/cards/deck/tarot, +/obj/item/toy/cards/deck/wizoff, +/obj/item/stack/spacecash/c500, +/turf/open/floor/wood, +/area/ruin/powered/golem_ship) +"cy" = ( +/obj/structure/chair/office{ + dir = 4 + }, +/turf/open/floor/mineral/titanium/purple, +/area/ruin/powered/golem_ship) +"cN" = ( +/obj/structure/railing{ + dir = 8 + }, +/turf/open/floor/wood, +/area/ruin/powered/golem_ship) +"cP" = ( +/obj/item/storage/toolbox/mechanical{ + pixel_y = 7; + pixel_x = 3 + }, +/obj/item/storage/toolbox/mechanical{ + pixel_y = 1; + pixel_x = -2 + }, +/obj/structure/table, +/turf/open/floor/mineral/titanium/purple, +/area/ruin/powered/golem_ship) +"dE" = ( +/obj/structure/table, +/obj/item/taperecorder{ + pixel_y = 7; + pixel_x = 5 + }, +/turf/open/floor/mineral/titanium, +/area/ruin/powered/golem_ship) +"dT" = ( +/obj/machinery/griddle, +/turf/open/floor/mineral/titanium/purple, +/area/ruin/powered/golem_ship) +"ed" = ( +/obj/item/toy/crayon/spraycan{ + pixel_x = -11; + pixel_y = 21 + }, +/turf/open/floor/mineral/titanium, +/area/ruin/powered/golem_ship) +"eJ" = ( +/obj/item/stack/sheet/glass{ + pixel_y = 2; + pixel_x = 5 + }, +/obj/item/stack/cable_coil/five{ + pixel_y = 7; + pixel_x = 4 + }, /turf/open/floor/plating, /area/ruin/powered/golem_ship) -"d" = ( -/obj/structure/closet/crate, -/obj/item/shovel, -/obj/item/shovel, -/obj/item/pickaxe, -/obj/item/pickaxe, +"fk" = ( +/turf/open/floor/wood, +/area/ruin/powered/golem_ship) +"fS" = ( +/obj/effect/turf_decal/siding/thinplating_new{ + dir = 4 + }, +/turf/open/floor/mineral/titanium, +/area/ruin/powered/golem_ship) +"fT" = ( +/obj/structure/table/reinforced, +/obj/machinery/reagentgrinder, +/turf/open/floor/mineral/titanium/purple, +/area/ruin/powered/golem_ship) +"gv" = ( +/obj/structure/closet, +/obj/item/storage/bag/ore, +/obj/item/storage/bag/ore, +/obj/item/storage/bag/ore, +/obj/item/storage/bag/ore, +/obj/item/storage/bag/ore, +/obj/item/storage/bag/ore, +/obj/item/storage/bag/ore, /obj/item/storage/bag/ore, /obj/item/storage/bag/ore, -/obj/item/mining_scanner, /obj/item/flashlight/lantern, -/obj/item/card/id/advanced/mining, +/obj/item/flashlight/lantern, +/obj/item/flashlight/lantern, +/obj/item/flashlight/lantern, +/obj/item/flashlight/lantern, +/obj/item/flashlight/lantern, +/obj/item/flashlight/lantern, +/obj/item/flashlight/lantern, +/obj/item/flashlight/lantern, /turf/open/floor/plating, /area/ruin/powered/golem_ship) -"e" = ( -/obj/item/storage/toolbox/mechanical, -/turf/open/floor/plating, +"gz" = ( +/obj/structure/bookcase/random/reference, +/turf/open/floor/wood, /area/ruin/powered/golem_ship) -"f" = ( -/turf/open/floor/plating, +"hy" = ( +/obj/machinery/vending/cigarette, +/turf/open/floor/mineral/titanium/purple, /area/ruin/powered/golem_ship) -"g" = ( -/obj/structure/reagent_dispensers/watertank, -/turf/open/floor/plating, +"ir" = ( +/obj/effect/turf_decal/siding/thinplating_new, +/turf/open/floor/mineral/titanium, /area/ruin/powered/golem_ship) -"h" = ( -/obj/machinery/power/shuttle_engine/heater{ - dir = 4 +"kx" = ( +/obj/structure/chair/office{ + dir = 8 }, -/obj/structure/window/reinforced/spawner/directional/west, +/turf/open/floor/mineral/titanium, +/area/ruin/powered/golem_ship) +"lh" = ( +/obj/machinery/computer/order_console/mining/golem, +/turf/open/floor/mineral/titanium/purple, +/area/ruin/powered/golem_ship) +"lF" = ( +/obj/effect/spawner/structure/window/reinforced/shuttle, /turf/open/floor/plating, /area/ruin/powered/golem_ship) -"i" = ( +"lH" = ( +/obj/structure/railing{ + dir = 8 + }, +/obj/item/chair/wood{ + pixel_x = 4; + pixel_y = -8 + }, +/turf/open/floor/wood, +/area/ruin/powered/golem_ship) +"mE" = ( +/turf/open/water/jungle, +/area/ruin/powered/golem_ship) +"mU" = ( /obj/machinery/power/shuttle_engine/propulsion{ dir = 4 }, /turf/open/floor/plating, /area/ruin/powered/golem_ship) -"j" = ( -/obj/machinery/door/airlock/titanium, +"mX" = ( +/obj/structure/table, /turf/open/floor/mineral/titanium/purple, /area/ruin/powered/golem_ship) -"k" = ( -/obj/machinery/computer/arcade/battle, +"nz" = ( +/obj/structure/ore_box, /turf/open/floor/mineral/titanium/purple, /area/ruin/powered/golem_ship) -"l" = ( +"nP" = ( +/obj/structure/extinguisher_cabinet/directional/south, +/turf/open/floor/mineral/titanium, +/area/ruin/powered/golem_ship) +"ok" = ( +/obj/structure/table, +/obj/item/stack/sticky_tape{ + pixel_y = 12; + pixel_x = 4 + }, +/obj/item/pen{ + pixel_x = -6 + }, +/obj/structure/light_construct/directional/north, /turf/open/floor/mineral/titanium/purple, /area/ruin/powered/golem_ship) -"m" = ( -/obj/effect/mob_spawn/ghost_role/human/golem/adamantine, +"oZ" = ( +/obj/structure/closet/crate, +/obj/item/pickaxe, +/obj/item/pickaxe, +/obj/item/pickaxe, +/obj/item/pickaxe, +/obj/item/shovel, +/obj/item/shovel, +/obj/item/shovel, +/obj/item/shovel, +/obj/item/fishing_rod, +/obj/item/fishing_rod, +/turf/open/floor/plating, +/area/ruin/powered/golem_ship) +"pE" = ( /turf/open/floor/mineral/titanium/purple, /area/ruin/powered/golem_ship) -"n" = ( -/obj/machinery/computer/order_console/mining/golem, +"pK" = ( +/obj/item/storage/medkit/brute{ + pixel_y = 7; + pixel_x = -11 + }, +/obj/item/storage/medkit/brute{ + pixel_y = 14; + pixel_x = -12 + }, +/obj/structure/table, +/obj/item/assembly/timer{ + pixel_y = -1; + pixel_x = 8 + }, +/turf/open/floor/mineral/titanium/purple, +/area/ruin/powered/golem_ship) +"pS" = ( +/obj/effect/turf_decal/tile/dark_red{ + dir = 1 + }, +/obj/effect/turf_decal/tile/dark_red{ + dir = 8 + }, +/obj/effect/turf_decal/tile/yellow{ + dir = 4 + }, +/obj/effect/turf_decal/tile/yellow, +/turf/open/floor/mineral/plastitanium, +/area/ruin/powered/golem_ship) +"qk" = ( +/obj/structure/light_construct/directional/north, +/turf/open/floor/mineral/titanium, +/area/ruin/powered/golem_ship) +"rb" = ( +/obj/structure/frame/machine, +/obj/item/circuitboard/machine/ore_redemption/offstation{ + pixel_y = -13; + pixel_x = 7 + }, +/turf/open/floor/plating, +/area/ruin/powered/golem_ship) +"sa" = ( +/obj/structure/table/reinforced, +/obj/item/disk/design_disk/golem_shell{ + pixel_y = 2; + pixel_x = 6 + }, +/obj/item/assembly/igniter{ + pixel_y = 12; + pixel_x = -3 + }, +/obj/item/stock_parts/micro_laser{ + pixel_x = -2 + }, /turf/open/floor/mineral/titanium/purple, /area/ruin/powered/golem_ship) -"o" = ( -/obj/item/resonator, +"sS" = ( +/turf/open/floor/mineral/titanium, +/area/ruin/powered/golem_ship) +"te" = ( +/obj/structure/light_construct/directional/south, /turf/open/floor/mineral/titanium/purple, /area/ruin/powered/golem_ship) -"q" = ( -/obj/structure/statue/gold/rd, -/obj/structure/window/reinforced/spawner/directional/east{ - name = "shrine of the liberator" +"tA" = ( +/obj/effect/turf_decal/tile/dark_red, +/obj/effect/turf_decal/tile/dark_red{ + dir = 4 + }, +/obj/effect/turf_decal/tile/dark_red{ + dir = 1 + }, +/obj/effect/turf_decal/tile/yellow{ + dir = 8 }, -/obj/machinery/light/directional/west, +/turf/open/floor/mineral/plastitanium, +/area/ruin/powered/golem_ship) +"tY" = ( +/obj/item/stack/ore/plasma{ + pixel_x = -8; + pixel_y = -8 + }, +/obj/item/stack/ore/gold{ + pixel_y = 2; + pixel_x = 6 + }, +/obj/item/stack/ore/iron{ + pixel_y = 5; + pixel_x = -10 + }, +/turf/open/floor/wood, +/area/ruin/powered/golem_ship) +"un" = ( +/obj/structure/table/wood, +/obj/item/areaeditor/blueprints/golem{ + pixel_y = 3; + pixel_x = -2 + }, +/obj/structure/light_construct/small/directional/east, +/turf/open/floor/wood, +/area/ruin/powered/golem_ship) +"uP" = ( +/obj/machinery/computer/arcade/orion_trail, /turf/open/floor/mineral/titanium/purple, /area/ruin/powered/golem_ship) -"r" = ( -/obj/machinery/computer/shuttle, +"uR" = ( +/obj/item/pickaxe, +/obj/effect/mob_spawn/ghost_role/human/golem/adamantine, /turf/open/floor/mineral/titanium/purple, /area/ruin/powered/golem_ship) -"t" = ( -/obj/structure/extinguisher_cabinet/directional/north, +"vr" = ( +/obj/structure/table, +/obj/item/storage/toolbox/fishing{ + pixel_y = 14 + }, +/obj/item/storage/toolbox/fishing{ + pixel_y = 7; + pixel_x = -1 + }, +/obj/item/storage/toolbox/fishing{ + pixel_y = -1; + pixel_x = -1 + }, /turf/open/floor/mineral/titanium/purple, /area/ruin/powered/golem_ship) -"u" = ( +"vZ" = ( +/obj/effect/turf_decal/siding/thinplating_new{ + dir = 1 + }, +/turf/open/floor/mineral/titanium, +/area/ruin/powered/golem_ship) +"wN" = ( +/turf/template_noop, +/area/template_noop) +"wQ" = ( +/obj/structure/table/reinforced, +/obj/item/storage/medkit/fire{ + pixel_y = 8; + pixel_x = 1 + }, +/turf/open/floor/mineral/titanium/purple, +/area/ruin/powered/golem_ship) +"wT" = ( /obj/structure/table/wood, -/obj/item/bedsheet/rd/royal_cape{ - layer = 3; - pixel_x = 5; - pixel_y = 9 +/obj/item/resonator/upgraded{ + name = "Chief Golem's Resonator"; + pixel_y = 6; + pixel_x = -8 }, -/obj/item/book/manual/wiki/research_and_development{ - name = "Sacred Text of the Liberator"; - pixel_x = -4; - pixel_y = 3 +/obj/item/paper_bin{ + pixel_x = 9; + pixel_y = 7 + }, +/obj/item/pen{ + pixel_y = -2 }, -/obj/structure/window/reinforced/spawner/directional/east{ - name = "shrine of the liberator" +/turf/open/floor/wood, +/area/ruin/powered/golem_ship) +"xa" = ( +/obj/structure/closet, +/obj/item/card/id/advanced/mining, +/obj/item/card/id/advanced/mining, +/obj/item/card/id/advanced/mining, +/obj/item/card/id/advanced/mining, +/obj/item/card/id/advanced/mining, +/obj/item/card/id/advanced/mining, +/obj/item/card/id/advanced/mining, +/obj/item/card/id/advanced/mining, +/obj/item/card/id/advanced/mining, +/obj/item/mining_scanner, +/obj/item/mining_scanner, +/obj/item/mining_scanner, +/obj/item/mining_scanner, +/obj/item/mining_scanner, +/obj/item/mining_scanner, +/obj/item/mining_scanner, +/obj/item/mining_scanner, +/obj/item/mining_scanner, +/turf/open/floor/mineral/titanium/purple, +/area/ruin/powered/golem_ship) +"xv" = ( +/obj/structure/table, +/obj/item/instrument/harmonica{ + pixel_y = 5; + pixel_x = -1 }, /turf/open/floor/mineral/titanium/purple, /area/ruin/powered/golem_ship) -"v" = ( -/obj/item/resonator/upgraded, +"xR" = ( +/obj/structure/table, +/obj/item/folder/blue{ + pixel_y = 1; + pixel_x = 4 + }, +/obj/item/paper_bin{ + pixel_x = -6; + pixel_y = 7 + }, +/obj/item/assembly/voice{ + pixel_x = -6; + pixel_y = -4 + }, /turf/open/floor/mineral/titanium/purple, /area/ruin/powered/golem_ship) -"w" = ( -/obj/machinery/autolathe, +"yG" = ( +/obj/effect/turf_decal/tile/dark_red, +/obj/effect/turf_decal/tile/dark_red{ + dir = 4 + }, +/obj/effect/turf_decal/tile/dark_red{ + dir = 8 + }, +/obj/effect/turf_decal/trimline/yellow/arrow_ccw{ + dir = 6 + }, +/obj/effect/turf_decal/trimline/yellow/arrow_ccw{ + dir = 6 + }, +/obj/effect/turf_decal/trimline/yellow/arrow_ccw{ + dir = 6 + }, +/obj/effect/turf_decal/tile/yellow{ + dir = 1 + }, +/turf/open/floor/mineral/plastitanium, +/area/ruin/powered/golem_ship) +"zN" = ( +/obj/machinery/vending/games, /turf/open/floor/mineral/titanium/purple, /area/ruin/powered/golem_ship) -"x" = ( -/obj/structure/table/wood, -/obj/machinery/reagentgrinder, +"At" = ( +/obj/effect/mob_spawn/ghost_role/human/golem/adamantine, /turf/open/floor/mineral/titanium/purple, /area/ruin/powered/golem_ship) -"y" = ( -/obj/machinery/computer/arcade/orion_trail, +"Az" = ( +/obj/structure/reagent_dispensers/fueltank, /turf/open/floor/mineral/titanium/purple, /area/ruin/powered/golem_ship) -"z" = ( -/obj/structure/extinguisher_cabinet/directional/south, +"Bx" = ( +/obj/item/storage/medkit/fire{ + pixel_y = 6; + pixel_x = -1 + }, +/obj/item/storage/medkit/fire{ + pixel_y = 13; + pixel_x = -1 + }, +/obj/structure/table, +/obj/structure/light_construct/directional/south, /turf/open/floor/mineral/titanium/purple, /area/ruin/powered/golem_ship) -"C" = ( -/obj/item/storage/medkit/brute, -/obj/structure/table/wood, -/obj/item/storage/medkit/brute, -/obj/item/areaeditor/blueprints/golem, +"BN" = ( +/obj/effect/turf_decal/siding/thinplating_new{ + dir = 8 + }, +/turf/open/floor/mineral/titanium, +/area/ruin/powered/golem_ship) +"CI" = ( +/obj/effect/mob_spawn/ghost_role/human/golem/adamantine, +/obj/structure/sink/directional/west, +/obj/structure/mirror/directional/east, /turf/open/floor/mineral/titanium/purple, /area/ruin/powered/golem_ship) -"D" = ( -/obj/item/storage/medkit/brute, -/obj/structure/table/wood, -/obj/item/storage/medkit/brute, -/obj/item/disk/design_disk/golem_shell, +"Df" = ( +/turf/closed/wall/mineral/titanium/nodiagonal, +/area/ruin/powered/golem_ship) +"DU" = ( +/obj/structure/light_construct/directional/north, /turf/open/floor/mineral/titanium/purple, /area/ruin/powered/golem_ship) -"E" = ( -/obj/structure/reagent_dispensers/fueltank, +"DW" = ( +/obj/item/storage/bag/ore{ + pixel_x = -5; + pixel_y = -5 + }, /turf/open/floor/plating, /area/ruin/powered/golem_ship) -"F" = ( -/obj/structure/ore_box, +"EF" = ( +/obj/effect/mob_spawn/ghost_role/human/golem/adamantine, +/turf/open/floor/mineral/titanium, +/area/ruin/powered/golem_ship) +"ET" = ( +/obj/item/stack/ore/gold{ + pixel_y = 7; + pixel_x = -11 + }, +/obj/item/stack/ore/iron{ + pixel_y = -17; + pixel_x = 10 + }, +/obj/item/stack/ore/gold{ + pixel_y = -16; + pixel_x = -6 + }, +/obj/item/stack/ore/iron{ + pixel_y = 7; + pixel_x = 12 + }, +/obj/structure/statue/gold/rd{ + name = "Statue of the Liberator"; + desc = "This is a highly valuable statue made from gold. It represents the creator of your species, the Liberator." + }, +/obj/item/stack/ore/gold{ + pixel_y = 18; + pixel_x = -8 + }, +/turf/open/floor/wood, +/area/ruin/powered/golem_ship) +"EY" = ( +/obj/item/stack/sheet/glass{ + pixel_y = 7; + pixel_x = 12 + }, /turf/open/floor/plating, /area/ruin/powered/golem_ship) -"G" = ( -/turf/closed/wall/mineral/titanium, +"FD" = ( +/obj/effect/turf_decal/siding/thinplating_new/corner{ + dir = 8 + }, +/turf/open/floor/mineral/titanium, /area/ruin/powered/golem_ship) -"H" = ( -/obj/machinery/door/airlock/titanium, -/obj/structure/fans/tiny, -/turf/open/floor/mineral/titanium/purple, +"Hp" = ( +/obj/machinery/door/airlock/titanium{ + name = "Liberator's Shrine" + }, +/obj/effect/turf_decal/siding/wood, +/turf/open/floor/wood, /area/ruin/powered/golem_ship) -"I" = ( -/obj/machinery/light/small/directional/south, +"Hu" = ( +/obj/item/stack/sheet/glass{ + pixel_y = -4; + pixel_x = 12 + }, /turf/open/floor/plating, /area/ruin/powered/golem_ship) -"K" = ( -/obj/machinery/door/airlock/titanium, -/obj/structure/fans/tiny, -/obj/effect/mapping_helpers/airlock/cyclelink_helper{ +"Iu" = ( +/obj/effect/turf_decal/tile/dark_red, +/obj/effect/turf_decal/tile/dark_red{ + dir = 1 + }, +/obj/effect/turf_decal/tile/dark_red{ dir = 8 }, +/obj/effect/turf_decal/trimline/purple/arrow_ccw{ + dir = 8 + }, +/obj/effect/turf_decal/trimline/purple/arrow_ccw{ + dir = 8 + }, +/obj/effect/turf_decal/trimline/purple/arrow_ccw{ + dir = 8 + }, +/obj/effect/turf_decal/trimline/purple/arrow_ccw{ + dir = 8 + }, +/obj/effect/turf_decal/tile/yellow{ + dir = 4 + }, +/turf/open/floor/mineral/plastitanium, +/area/ruin/powered/golem_ship) +"ID" = ( +/obj/machinery/door/airlock/titanium, +/turf/open/floor/wood, +/area/ruin/powered/golem_ship) +"IZ" = ( +/obj/structure/chair/office{ + dir = 4 + }, +/turf/open/floor/mineral/titanium, +/area/ruin/powered/golem_ship) +"Je" = ( +/obj/structure/closet/crate, +/obj/item/pickaxe, +/obj/item/pickaxe, +/obj/item/pickaxe, +/obj/item/pickaxe, +/obj/item/shovel, +/obj/item/shovel, +/obj/item/shovel, +/obj/item/shovel, +/obj/item/fishing_rod, +/obj/item/fishing_rod, +/obj/item/fishing_rod, /turf/open/floor/mineral/titanium/purple, /area/ruin/powered/golem_ship) -"L" = ( -/obj/machinery/light/small/directional/north, +"LN" = ( +/obj/machinery/computer/arcade/battle, /turf/open/floor/mineral/titanium/purple, /area/ruin/powered/golem_ship) -"M" = ( -/obj/effect/mob_spawn/ghost_role/human/golem/adamantine, -/obj/machinery/light/small/directional/north, +"MC" = ( +/obj/structure/ore_box, +/turf/open/floor/plating, +/area/ruin/powered/golem_ship) +"Ne" = ( +/obj/machinery/door/airlock/titanium, /turf/open/floor/mineral/titanium/purple, /area/ruin/powered/golem_ship) -"N" = ( -/obj/machinery/light/directional/north, +"Ni" = ( +/obj/machinery/door/airlock/titanium{ + name = "Storage" + }, /turf/open/floor/mineral/titanium/purple, /area/ruin/powered/golem_ship) -"P" = ( -/obj/structure/table/wood, -/obj/item/surgical_drapes{ - pixel_x = 15 +"Pa" = ( +/obj/machinery/bookbinder, +/turf/open/floor/wood, +/area/ruin/powered/golem_ship) +"Pe" = ( +/obj/structure/aquarium, +/turf/open/floor/wood, +/area/ruin/powered/golem_ship) +"Pq" = ( +/obj/item/stack/sheet/glass{ + pixel_y = 7; + pixel_x = 5 + }, +/turf/open/floor/plating, +/area/ruin/powered/golem_ship) +"Qp" = ( +/obj/structure/chair/office{ + dir = 8 }, -/obj/item/storage/medkit/fire, -/obj/item/storage/medkit/fire, -/obj/item/stock_parts/matter_bin, -/obj/item/assembly/igniter, -/obj/item/stock_parts/micro_laser, -/obj/item/stack/sheet/glass, -/obj/item/stack/sheet/glass, -/obj/item/stack/sheet/glass, -/obj/item/stack/sheet/glass, -/obj/item/stack/sheet/glass, -/obj/machinery/light/directional/south, /turf/open/floor/mineral/titanium/purple, /area/ruin/powered/golem_ship) -"Q" = ( -/obj/machinery/light/small/directional/south, +"QX" = ( +/obj/structure/table, +/obj/item/fishing_line/reinforced{ + pixel_y = 11; + pixel_x = -7 + }, +/obj/item/fishing_line/reinforced{ + pixel_y = 4; + pixel_x = 2 + }, /turf/open/floor/mineral/titanium/purple, /area/ruin/powered/golem_ship) -"S" = ( -/obj/item/storage/medkit/fire, +"Ro" = ( /obj/structure/table/wood, -/obj/item/storage/medkit/fire, -/turf/open/floor/mineral/titanium/purple, +/obj/item/bedsheet/rd/royal_cape{ + layer = 3; + pixel_x = 5; + pixel_y = 9 + }, +/turf/open/floor/wood, /area/ruin/powered/golem_ship) -"T" = ( -/obj/structure/fans/tiny, -/obj/machinery/door/airlock/titanium, +"Rt" = ( +/turf/open/floor/plating, +/area/ruin/powered/golem_ship) +"Ta" = ( +/obj/machinery/computer/shuttle{ + dir = 4 + }, /turf/open/floor/mineral/titanium/purple, /area/ruin/powered/golem_ship) -"U" = ( -/obj/effect/mob_spawn/ghost_role/human/golem/adamantine, -/obj/machinery/light/small/directional/south, +"Tn" = ( +/obj/effect/turf_decal/tile/dark_red, +/obj/effect/turf_decal/tile/dark_red{ + dir = 4 + }, +/obj/effect/turf_decal/tile/dark_red{ + dir = 8 + }, +/obj/effect/turf_decal/trimline/yellow/arrow_ccw, +/obj/effect/turf_decal/trimline/yellow/arrow_ccw, +/obj/effect/turf_decal/trimline/yellow/arrow_ccw, +/obj/effect/turf_decal/tile/yellow{ + dir = 1 + }, +/turf/open/floor/mineral/plastitanium, +/area/ruin/powered/golem_ship) +"Ul" = ( +/obj/item/storage/medkit/fire{ + pixel_y = 5; + pixel_x = 7 + }, +/obj/item/surgical_drapes{ + pixel_x = 7; + pixel_y = 10 + }, +/obj/structure/table, /turf/open/floor/mineral/titanium/purple, /area/ruin/powered/golem_ship) -"V" = ( -/obj/machinery/light/small/directional/north, +"Ux" = ( +/obj/machinery/power/shuttle_engine/heater{ + dir = 4 + }, +/obj/structure/window/reinforced/spawner/directional/west, /turf/open/floor/plating, /area/ruin/powered/golem_ship) -"W" = ( -/obj/structure/closet/crate, -/obj/item/shovel, -/obj/item/shovel, -/obj/item/shovel, -/obj/item/pickaxe, -/obj/item/pickaxe, -/obj/item/pickaxe, -/obj/item/storage/bag/ore, -/obj/item/storage/bag/ore, -/obj/item/mining_scanner, -/obj/item/flashlight/lantern, -/obj/item/card/id/advanced/mining, -/obj/machinery/light/small/directional/west, +"UL" = ( +/obj/item/shovel{ + pixel_x = -6; + pixel_y = -8 + }, /turf/open/floor/plating, /area/ruin/powered/golem_ship) -"X" = ( -/obj/structure/frame/machine, -/obj/item/stack/cable_coil/five, -/obj/item/circuitboard/machine/ore_redemption/offstation, +"WL" = ( +/obj/item/stack/ore/gold{ + pixel_y = 13; + pixel_x = -8 + }, +/obj/structure/table/wood, +/obj/item/flashlight/lamp/green{ + pixel_y = 15 + }, +/obj/item/book/manual/wiki/research_and_development{ + name = "Sacred Text of the Liberator"; + pixel_x = -4; + pixel_y = 3 + }, +/turf/open/floor/wood, +/area/ruin/powered/golem_ship) +"WM" = ( +/obj/machinery/autolathe, /turf/open/floor/mineral/titanium/purple, /area/ruin/powered/golem_ship) -"Y" = ( -/obj/machinery/door/airlock/titanium, -/obj/effect/mapping_helpers/airlock/cyclelink_helper{ +"Xy" = ( +/obj/effect/turf_decal/tile/dark_red, +/obj/effect/turf_decal/tile/dark_red{ dir = 4 }, +/obj/effect/turf_decal/tile/dark_red{ + dir = 1 + }, +/obj/effect/turf_decal/tile/dark_red{ + dir = 8 + }, +/obj/effect/turf_decal/trimline/purple/arrow_ccw{ + dir = 8 + }, +/obj/effect/turf_decal/trimline/purple/arrow_ccw{ + dir = 8 + }, +/obj/effect/turf_decal/trimline/purple/arrow_ccw{ + dir = 8 + }, +/obj/effect/turf_decal/trimline/purple/arrow_ccw{ + dir = 8 + }, +/obj/effect/turf_decal/trimline/yellow/arrow_ccw, +/obj/effect/turf_decal/trimline/yellow/arrow_ccw, +/obj/effect/turf_decal/trimline/yellow/arrow_ccw, +/turf/open/floor/mineral/plastitanium, +/area/ruin/powered/golem_ship) +"XK" = ( +/obj/structure/closet/crate/bin, /turf/open/floor/mineral/titanium/purple, /area/ruin/powered/golem_ship) -"Z" = ( -/obj/structure/ore_box, -/obj/machinery/light/small/directional/west, -/turf/open/floor/plating, +"XR" = ( +/obj/item/aquarium_kit{ + pixel_y = 12; + pixel_x = -5 + }, +/obj/effect/turf_decal/siding/thinplating_new/corner, +/turf/open/floor/mineral/titanium, +/area/ruin/powered/golem_ship) +"ZQ" = ( +/obj/effect/turf_decal/siding/thinplating_new/corner{ + dir = 4 + }, +/turf/open/floor/mineral/titanium, +/area/ruin/powered/golem_ship) +"ZS" = ( +/obj/effect/turf_decal/siding/thinplating_new/corner{ + dir = 1 + }, +/turf/open/floor/mineral/titanium, /area/ruin/powered/golem_ship) (1,1,1) = {" -a -a -a -a -a -a -b -b -b -b -a -a -a -a -a -a +wN +Df +lF +lF +Df +wN +wN +wN +lF +lF +lF +lF +lF +lF +wN +wN "} (2,1,1) = {" -a -a -a -a -a -a -b -q -u -G -a -a -a -a -a -a +Df +Df +WL +Ro +lF +wN +wN +lF +lF +Ta +xR +am +bb +lF +lF +wN "} (3,1,1) = {" -a -a -a -b -b -H -b -r -l -G -T -b -b -a -a -a +Df +bu +ET +tY +lF +wN +wN +Df +sa +Qp +kx +kx +Qp +Bx +Df +wN "} (4,1,1) = {" -a -a -a -b -k -l -j -l -l -j -l -y -b -a -a -a +lF +cp +cN +lH +Df +lF +lF +Df +WM +sS +sS +sS +sS +pK +lF +wN "} (5,1,1) = {" -a -a -a -b -l -l -j -l -l -j -l -l -b -a -a -a +lF +Pe +fk +fk +ID +fk +fk +Hp +pE +sS +IZ +IZ +sS +mX +lF +wN "} (6,1,1) = {" -b -b -b -b -L -l -b -l -l -G -l -Q -b -b -b -b +Df +gz +aU +Pa +Df +lF +lF +Df +LN +sS +dE +ch +sS +Ul +lF +wN "} (7,1,1) = {" -b -W -f -j -l -l -b -l -Q -G -l -l -j -f -Z -b +Df +gz +wT +un +Df +wN +wN +Df +uP +sS +kx +kx +sS +cP +Df +wN "} (8,1,1) = {" -b -c -f -j -l -l -b -l -l -G -l -l -j -f -F -b +Df +Df +lF +Df +Df +wN +Df +Df +Df +qk +sS +sS +nP +Df +Df +wN "} (9,1,1) = {" -b -c -f -b -M -o -b -L -l -G -o -U -b -f -F -b +wN +wN +wN +wN +wN +wN +lF +zN +ed +sS +sS +sS +sS +dT +lF +wN "} (10,1,1) = {" -b -c -f -b -m -o -b -l -l -G -o -m -b -f -F -b +wN +wN +mE +mE +Df +Df +Df +hy +sS +sS +sS +XK +fT +wQ +lF +wN "} (11,1,1) = {" -b -c -I -b -b -j -b -j -j -G -j -b -b -V -F -b +wN +mE +mE +Df +Df +vr +QX +sS +sS +sS +At +Df +Df +Df +Df +Df "} (12,1,1) = {" -b -c -f -b -l -l -l -l -l -l -l -z -b -f -F -b +wN +mE +mE +Df +bO +XR +fS +fS +ZQ +sS +xv +Df +Je +MC +nz +Df "} (13,1,1) = {" -b -d -f -j -l -l -l -l -l -l -l -l -j -f -F -b +wN +wN +mE +lF +bO +ir +Tn +tA +vZ +pE +Df +Df +pE +MC +MC +Df "} (14,1,1) = {" -b -d -f -j -l -l -l -l -l -l -l -l -j -f -e -b +wN +wN +wN +lF +cy +ir +Xy +Iu +vZ +te +Df +uR +pE +MC +nz +Df "} (15,1,1) = {" -b -d -f -b -N -l -l -l -l -l -l -P -b -f -f -b +wN +wN +wN +Df +ok +ir +yG +pS +vZ +pE +Ni +pE +pE +DW +MC +Df "} (16,1,1) = {" -T -e -I -b -l -l -l -l -l -v -l -S -b -V -f -T +wN +wN +wN +lF +Qp +FD +BN +BN +ZS +pE +Df +eJ +EY +pE +oZ +Df "} (17,1,1) = {" -T -f -f -b -l -l -X -l -l -w -l -C -b -f -f -T +wN +wN +wN +lF +Az +sS +EF +Df +Ne +Ne +Df +rb +Hu +Rt +gv +Df "} (18,1,1) = {" -b -g -g -b -n -l -b -Y -Y -b -x -D -b -E -E -b +wN +wN +wN +Df +Az +pE +CI +Df +DU +pE +Df +lh +Pq +UL +xa +Df "} (19,1,1) = {" -b -h -h -b -h -h -b -t -Q -b -h -h -b -h -h -b +wN +wN +wN +Df +Ux +Ux +Df +Df +Ne +Ne +Df +Df +Df +Ux +Ux +Df "} (20,1,1) = {" -b -i -i -b -i -i -b -K -K -b -i -i -b -i -i -b +wN +wN +wN +Df +mU +mU +Df +wN +wN +wN +wN +wN +Df +mU +mU +Df "} diff --git a/_maps/RandomRuins/LavaRuins/lavaland_surface_mookvillage.dmm b/_maps/RandomRuins/LavaRuins/lavaland_surface_mookvillage.dmm index 5db8dd37a24..e848889711e 100644 --- a/_maps/RandomRuins/LavaRuins/lavaland_surface_mookvillage.dmm +++ b/_maps/RandomRuins/LavaRuins/lavaland_surface_mookvillage.dmm @@ -161,7 +161,7 @@ "O" = ( /obj/structure/table/wood/shuttle_bar, /obj/item/hatchet/wooden, -/obj/item/storage/belt/champion/wrestling, +/obj/item/storage/belt/champion, /turf/open/floor/holofloor/wood, /area/lavaland/surface/outdoors) "P" = ( diff --git a/_maps/RandomZLevels/TheBeach.dmm b/_maps/RandomZLevels/TheBeach.dmm index 7b36dfb1471..1df876c3430 100644 --- a/_maps/RandomZLevels/TheBeach.dmm +++ b/_maps/RandomZLevels/TheBeach.dmm @@ -303,9 +303,6 @@ name = "Balcony"; id_tag = "beach_room_x" }, -/obj/structure/railing/corner/end{ - dir = 8 - }, /turf/open/floor/wood, /area/awaymission/beach) "dS" = ( @@ -565,7 +562,9 @@ /obj/structure/table/bronze, /obj/structure/sign/poster/random/directional/east, /obj/machinery/button/door/directional/south{ - id = "beach_room_10" + id = "beach_room_10"; + normaldoorcontrol = 1; + specialfunctions = 4 }, /obj/item/table_clock{ pixel_y = 4 @@ -868,7 +867,9 @@ /area/awaymission/beach) "kR" = ( /obj/machinery/button/door/directional/north{ - id = "beach_room_12" + id = "beach_room_12"; + normaldoorcontrol = 1; + specialfunctions = 4 }, /turf/open/floor/wood, /area/awaymission/beach) @@ -876,7 +877,7 @@ /turf/open/floor/eighties, /area/awaymission/beach) "lb" = ( -/obj/structure/railing/corner/end/flip{ +/obj/structure/railing/corner/end{ dir = 4 }, /turf/open/floor/wood/parquet, @@ -1177,7 +1178,9 @@ "oX" = ( /obj/structure/closet/secure_closet/personal/cabinet, /obj/machinery/button/door/directional/west{ - id = "beach_room_7" + id = "beach_room_7"; + normaldoorcontrol = 1; + specialfunctions = 4 }, /obj/item/clothing/suit/apron/overalls, /turf/open/floor/wood, @@ -1316,7 +1319,9 @@ /area/awaymission/beach) "qC" = ( /obj/machinery/button/door/directional/west{ - id = "beach_room_1" + id = "beach_room_1"; + normaldoorcontrol = 1; + specialfunctions = 4 }, /turf/open/floor/wood, /area/awaymission/beach) @@ -1456,7 +1461,9 @@ /area/awaymission/beach) "tx" = ( /obj/machinery/button/door/directional/north{ - id = "beach_room_3" + id = "beach_room_3"; + normaldoorcontrol = 1; + specialfunctions = 4 }, /turf/open/floor/wood, /area/awaymission/beach) @@ -1545,7 +1552,9 @@ "um" = ( /obj/structure/table/bronze, /obj/machinery/button/door/directional/south{ - id = "beach_room_11" + id = "beach_room_11"; + normaldoorcontrol = 1; + specialfunctions = 4 }, /obj/item/storage/toolbox/fishing{ pixel_y = 2 @@ -1697,7 +1706,9 @@ /obj/structure/table/bronze, /obj/structure/sign/poster/random/directional/east, /obj/machinery/button/door/directional/south{ - id = "beach_room_8" + id = "beach_room_8"; + normaldoorcontrol = 1; + specialfunctions = 4 }, /obj/item/camera{ pixel_y = 5 @@ -1747,6 +1758,9 @@ pixel_y = -8; pixel_x = -3 }, +/obj/structure/railing/corner/end{ + dir = 4 + }, /turf/open/floor/wood/parquet, /area/awaymission/beach) "wA" = ( @@ -1900,7 +1914,6 @@ /turf/open/floor/iron/dark/diagonal, /area/awaymission/beach) "yO" = ( -/obj/effect/turf_decal/siding/wood, /obj/structure/table, /obj/item/storage/toolbox/mechanical{ pixel_y = 12; @@ -1929,7 +1942,9 @@ "yZ" = ( /obj/machinery/space_heater, /obj/machinery/button/door/directional/north{ - id = "beach_room_2" + id = "beach_room_2"; + normaldoorcontrol = 1; + specialfunctions = 4 }, /turf/open/floor/wood, /area/awaymission/beach) @@ -2330,7 +2345,9 @@ "DV" = ( /obj/structure/table/bronze, /obj/machinery/button/door/directional/south{ - id = "beach_room_4" + id = "beach_room_4"; + normaldoorcontrol = 1; + specialfunctions = 4 }, /obj/item/storage/toolbox/fishing{ pixel_y = 2 @@ -2414,6 +2431,9 @@ /obj/structure/railing/corner/end{ dir = 8 }, +/obj/effect/turf_decal/siding/wood/corner{ + dir = 1 + }, /turf/open/water/beach, /area/awaymission/beach) "EG" = ( @@ -2595,13 +2615,13 @@ /turf/open/floor/wood/large, /area/awaymission/beach) "FU" = ( -/obj/structure/railing/corner/end/flip{ - dir = 4 - }, /obj/item/cigbutt{ pixel_y = -6; pixel_x = -12 }, +/obj/structure/railing/corner/end{ + dir = 4 + }, /turf/open/floor/wood/parquet, /area/awaymission/beach) "FY" = ( @@ -3161,7 +3181,9 @@ /area/awaymission/beach) "Nd" = ( /obj/machinery/button/door/directional/south{ - id = "beach_room_5" + id = "beach_room_5"; + normaldoorcontrol = 1; + specialfunctions = 4 }, /turf/open/floor/wood, /area/awaymission/beach) @@ -3255,6 +3277,9 @@ /obj/structure/railing{ dir = 1 }, +/obj/effect/turf_decal/siding/wood{ + dir = 1 + }, /turf/open/water/beach, /area/awaymission/beach) "OD" = ( @@ -3264,7 +3289,9 @@ "OE" = ( /obj/structure/closet/secure_closet/personal/cabinet, /obj/machinery/button/door/directional/west{ - id = "beach_room_6" + id = "beach_room_6"; + normaldoorcontrol = 1; + specialfunctions = 4 }, /obj/item/clothing/suit/jacket/leather/biker, /turf/open/floor/wood, @@ -3452,6 +3479,12 @@ }, /turf/open/floor/wood/large, /area/awaymission/beach) +"Rc" = ( +/obj/effect/turf_decal/siding/wood/corner{ + dir = 1 + }, +/turf/closed/wall/mineral/wood, +/area/awaymission/beach) "Rj" = ( /turf/open/misc/beach/coast{ dir = 6 @@ -3886,7 +3919,9 @@ "XV" = ( /obj/structure/closet/secure_closet/personal/cabinet, /obj/machinery/button/door/directional/north{ - id = "beach_room_9" + id = "beach_room_9"; + normaldoorcontrol = 1; + specialfunctions = 4 }, /obj/item/claymore/cutlass{ desc = "A piratey, foam sword used by kids to train themselves in the business of \"negotiating\" the transfer of treasure."; @@ -14450,7 +14485,7 @@ mP Lg un tD -xv +Rc TX bi bi diff --git a/_maps/map_files/Deltastation/DeltaStation2.dmm b/_maps/map_files/Deltastation/DeltaStation2.dmm index dc37382b416..0a0dde54ab5 100644 --- a/_maps/map_files/Deltastation/DeltaStation2.dmm +++ b/_maps/map_files/Deltastation/DeltaStation2.dmm @@ -3123,6 +3123,13 @@ }, /turf/open/floor/iron, /area/station/engineering/atmos) +"aMz" = ( +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/structure/disposalpipe/segment, +/obj/effect/turf_decal/tile/neutral/fourcorners, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/turf/open/floor/iron, +/area/station/cargo/sorting) "aMB" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -10291,13 +10298,6 @@ /obj/effect/turf_decal/bot, /turf/open/floor/iron, /area/station/engineering/storage/tech) -"cxv" = ( -/obj/structure/disposalpipe/segment, -/obj/structure/cable, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/effect/turf_decal/delivery, -/turf/open/floor/iron, -/area/station/maintenance/fore) "cxM" = ( /obj/structure/disposalpipe/segment, /obj/effect/turf_decal/stripes/line, @@ -14486,6 +14486,21 @@ /obj/effect/mapping_helpers/burnt_floor, /turf/open/floor/plating, /area/station/commons/toilet/restrooms) +"dAA" = ( +/obj/structure/disposalpipe/segment, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/effect/decal/cleanable/dirt, +/obj/machinery/door/airlock/maintenance_hatch{ + name = "Cargo Maintenance" + }, +/obj/effect/turf_decal/stripes/line, +/obj/effect/turf_decal/stripes/line{ + dir = 1 + }, +/obj/effect/mapping_helpers/airlock/access/all/supply/general, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/turf/open/floor/iron, +/area/station/maintenance/fore) "dAX" = ( /obj/machinery/light/small/directional/west, /obj/structure/sign/poster/official/work_for_a_future/directional/south, @@ -17145,17 +17160,6 @@ }, /turf/open/floor/iron, /area/station/command/heads_quarters/qm) -"eke" = ( -/obj/structure/cable, -/obj/structure/disposalpipe/junction/yjunction{ - dir = 8 - }, -/obj/effect/decal/cleanable/dirt, -/obj/effect/turf_decal/tile/neutral/half/contrasted{ - dir = 4 - }, -/turf/open/floor/iron, -/area/station/maintenance/fore) "ekM" = ( /obj/effect/decal/cleanable/dirt, /obj/effect/decal/cleanable/cobweb/cobweb2, @@ -20388,11 +20392,6 @@ /obj/effect/mapping_helpers/airlock/access/all/security/general, /turf/open/floor/iron, /area/station/security/checkpoint/escape) -"eYZ" = ( -/obj/structure/disposalpipe/segment, -/obj/effect/turf_decal/tile/brown/anticorner/contrasted, -/turf/open/floor/iron, -/area/station/cargo/sorting) "eZe" = ( /obj/machinery/vending/wardrobe/viro_wardrobe, /obj/structure/sign/poster/official/cleanliness/directional/west, @@ -22598,16 +22597,6 @@ /obj/effect/decal/cleanable/dirt, /turf/open/floor/plating, /area/station/maintenance/department/science/xenobiology) -"fCm" = ( -/obj/machinery/door/poddoor/shutters/preopen{ - dir = 4; - id = "chemisttop"; - name = "Pharmacy Shutters" - }, -/obj/machinery/smartfridge/chemistry/preloaded, -/obj/machinery/door/firedoor, -/turf/open/floor/iron/white, -/area/station/medical/pharmacy) "fCn" = ( /obj/machinery/door/airlock/medical{ name = "Medical Break Room" @@ -22893,6 +22882,13 @@ /obj/effect/spawner/random/maintenance, /turf/open/floor/iron/dark, /area/station/service/abandoned_gambling_den) +"fGC" = ( +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/structure/disposalpipe/segment, +/obj/effect/turf_decal/delivery, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/turf/open/floor/iron, +/area/station/cargo/storage) "fGD" = ( /obj/machinery/light/directional/south, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -22917,6 +22913,12 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/closed/wall/r_wall, /area/station/engineering/atmos/mix) +"fGW" = ( +/obj/structure/cable, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/turf/open/floor/plating, +/area/station/maintenance/fore) "fGY" = ( /obj/structure/disposalpipe/segment, /obj/effect/decal/cleanable/dirt, @@ -24459,6 +24461,19 @@ /obj/effect/turf_decal/tile/neutral/fourcorners, /turf/open/floor/iron, /area/station/maintenance/port/aft) +"gaH" = ( +/obj/structure/disposalpipe/segment{ + dir = 9 + }, +/obj/effect/decal/cleanable/dirt, +/obj/structure/chair/office, +/obj/machinery/status_display/supply{ + pixel_x = 32 + }, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/turf/open/floor/iron, +/area/station/cargo/sorting) "gaT" = ( /obj/item/kirbyplants/random, /obj/effect/mapping_helpers/broken_floor, @@ -25154,39 +25169,6 @@ }, /turf/open/floor/iron, /area/station/hallway/primary/central/fore) -"giO" = ( -/obj/structure/table/reinforced, -/obj/machinery/door/firedoor, -/obj/structure/desk_bell{ - pixel_x = 7; - pixel_y = 6 - }, -/obj/item/folder/yellow{ - pixel_x = -3; - pixel_y = -6 - }, -/obj/item/pen{ - pixel_x = -3; - pixel_y = -2 - }, -/obj/machinery/door/poddoor/shutters/preopen{ - dir = 4; - id = "chemisttop"; - name = "Pharmacy Shutters" - }, -/obj/effect/turf_decal/stripes/line{ - dir = 8 - }, -/obj/effect/turf_decal/stripes/line{ - dir = 4 - }, -/obj/machinery/door/window/left/directional/west{ - name = "Pharmacy Desk"; - req_access = list("pharmacy"); - dir = 4 - }, -/turf/open/floor/iron/dark, -/area/station/medical/pharmacy) "giY" = ( /obj/effect/decal/cleanable/dirt, /obj/structure/sign/poster/contraband/random/directional/north, @@ -25665,6 +25647,13 @@ /obj/machinery/airalarm/directional/east, /turf/open/floor/iron, /area/station/engineering/main) +"gow" = ( +/obj/structure/disposalpipe/segment, +/obj/effect/turf_decal/tile/brown/anticorner/contrasted, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/turf/open/floor/iron, +/area/station/cargo/sorting) "gox" = ( /obj/effect/turf_decal/trimline/neutral/filled/corner, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -37501,12 +37490,6 @@ /obj/effect/turf_decal/tile/neutral/anticorner/contrasted, /turf/open/floor/iron, /area/station/security/courtroom) -"jnd" = ( -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/structure/disposalpipe/segment, -/obj/effect/turf_decal/delivery, -/turf/open/floor/iron, -/area/station/cargo/storage) "jni" = ( /obj/effect/decal/cleanable/dirt, /obj/effect/mapping_helpers/airlock/access/all/science/robotics, @@ -37654,20 +37637,6 @@ /obj/item/clothing/suit/toggle/labcoat, /turf/open/floor/plating, /area/station/maintenance/port/aft) -"joP" = ( -/obj/structure/disposalpipe/segment, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/effect/decal/cleanable/dirt, -/obj/machinery/door/airlock/maintenance_hatch{ - name = "Cargo Maintenance" - }, -/obj/effect/turf_decal/stripes/line, -/obj/effect/turf_decal/stripes/line{ - dir = 1 - }, -/obj/effect/mapping_helpers/airlock/access/all/supply/general, -/turf/open/floor/iron, -/area/station/maintenance/fore) "joU" = ( /obj/structure/table, /obj/item/paper_bin, @@ -42895,6 +42864,13 @@ /obj/effect/turf_decal/tile/neutral/fourcorners, /turf/open/floor/iron, /area/station/hallway/primary/central/aft) +"kFJ" = ( +/obj/structure/cable, +/obj/effect/decal/cleanable/dirt, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/turf/open/floor/plating, +/area/station/maintenance/fore) "kFK" = ( /obj/structure/cable, /turf/open/floor/iron/white, @@ -45336,6 +45312,27 @@ }, /turf/open/floor/iron/herringbone, /area/station/cargo/miningoffice) +"llk" = ( +/obj/structure/table/reinforced, +/obj/machinery/door/firedoor, +/obj/item/folder/yellow{ + pixel_x = -6 + }, +/obj/item/pen{ + pixel_x = -6 + }, +/obj/effect/turf_decal/delivery, +/obj/machinery/door/window/right/directional/south{ + name = "Delivery Office Desk"; + req_access = list("shipping") + }, +/obj/structure/desk_bell{ + pixel_x = 7 + }, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/turf/open/floor/iron, +/area/station/cargo/sorting) "llm" = ( /obj/structure/chair/office/tactical{ dir = 8 @@ -46293,6 +46290,18 @@ /obj/effect/turf_decal/tile/neutral/fourcorners, /turf/open/floor/iron, /area/station/commons/toilet/locker) +"lxX" = ( +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/structure/disposalpipe/segment, +/obj/machinery/camera/directional/east{ + c_tag = "Cargo Bay - Delivery Office"; + name = "cargo camera" + }, +/obj/effect/turf_decal/tile/brown, +/obj/machinery/light/directional/east, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/turf/open/floor/iron, +/area/station/cargo/sorting) "lyd" = ( /obj/machinery/flasher{ id = "justiceflash"; @@ -47395,6 +47404,14 @@ }, /turf/open/floor/plating, /area/station/security/prison/safe) +"lKs" = ( +/obj/structure/disposalpipe/segment, +/obj/structure/cable, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/effect/turf_decal/delivery, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/turf/open/floor/iron, +/area/station/maintenance/fore) "lKw" = ( /obj/structure/cable, /obj/machinery/power/apc/auto_name/directional/north, @@ -52138,6 +52155,16 @@ /obj/effect/turf_decal/tile/neutral/fourcorners, /turf/open/floor/iron/dark, /area/station/service/kitchen/abandoned) +"mXI" = ( +/obj/structure/cable, +/obj/structure/disposalpipe/segment, +/obj/effect/decal/cleanable/dirt, +/obj/effect/turf_decal/delivery, +/obj/effect/turf_decal/tile/neutral/anticorner/contrasted, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/turf/open/floor/iron, +/area/station/maintenance/fore) "mXQ" = ( /obj/structure/window/reinforced/spawner/directional/south, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -53652,6 +53679,12 @@ /obj/machinery/light/small/directional/north, /turf/open/floor/iron/dark, /area/station/commons/fitness/recreation) +"ntU" = ( +/obj/structure/table/reinforced, +/obj/machinery/microwave/engineering/cell_included, +/obj/structure/sign/poster/random/directional/west, +/turf/open/floor/wood, +/area/station/engineering/break_room) "ntX" = ( /obj/effect/turf_decal/trimline/blue/filled/line{ dir = 1 @@ -58305,12 +58338,6 @@ /obj/effect/turf_decal/tile/neutral/fourcorners, /turf/open/floor/iron, /area/station/maintenance/department/medical/morgue) -"oFk" = ( -/obj/structure/cable, -/obj/effect/decal/cleanable/dirt, -/obj/effect/spawner/random/structure/steam_vent, -/turf/open/floor/plating, -/area/station/maintenance/fore) "oFr" = ( /obj/structure/window/reinforced/spawner/directional/east, /obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ @@ -63493,6 +63520,39 @@ /obj/effect/landmark/event_spawn, /turf/open/floor/iron/grimy, /area/station/command/heads_quarters/hos) +"pTz" = ( +/obj/structure/table/reinforced, +/obj/machinery/door/firedoor, +/obj/structure/desk_bell{ + pixel_x = 7; + pixel_y = 6 + }, +/obj/item/folder/yellow{ + pixel_x = -3; + pixel_y = -6 + }, +/obj/item/pen{ + pixel_x = -3; + pixel_y = -2 + }, +/obj/machinery/door/poddoor/shutters/preopen{ + dir = 4; + id = "chemisttop"; + name = "Pharmacy Shutters" + }, +/obj/effect/turf_decal/stripes/line{ + dir = 8 + }, +/obj/effect/turf_decal/stripes/line{ + dir = 4 + }, +/obj/machinery/door/window/left/directional/west{ + name = "Pharmacy Desk"; + req_access = list("pharmacy"); + dir = 4 + }, +/turf/open/floor/iron/dark, +/area/station/medical/pharmacy) "pTB" = ( /obj/effect/decal/cleanable/dirt, /obj/structure/cable, @@ -67508,6 +67568,13 @@ /obj/effect/landmark/event_spawn, /turf/open/floor/iron/grimy, /area/station/service/library) +"qSr" = ( +/obj/structure/cable, +/obj/effect/decal/cleanable/dirt, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/turf/open/floor/iron, +/area/station/maintenance/fore) "qSG" = ( /obj/machinery/portable_atmospherics/canister/anesthetic_mix, /obj/machinery/light/small/blacklight/directional/north, @@ -68603,6 +68670,16 @@ /obj/effect/landmark/start/hangover, /turf/open/floor/iron/white, /area/station/medical/medbay) +"riZ" = ( +/obj/machinery/door/poddoor/shutters/preopen{ + dir = 4; + id = "chemisttop"; + name = "Pharmacy Shutters" + }, +/obj/machinery/smartfridge/chemistry/preloaded, +/obj/machinery/door/firedoor, +/turf/open/floor/iron/white, +/area/station/medical/pharmacy) "rjd" = ( /obj/structure/table/wood, /obj/item/flashlight/lamp/green, @@ -71680,14 +71757,6 @@ /obj/effect/mapping_helpers/burnt_floor, /turf/open/floor/plating, /area/station/maintenance/fore) -"rUV" = ( -/obj/structure/cable, -/obj/effect/decal/cleanable/dirt, -/obj/effect/turf_decal/tile/neutral/half/contrasted{ - dir = 8 - }, -/turf/open/floor/iron, -/area/station/maintenance/fore) "rUW" = ( /obj/item/kirbyplants/organic/plant21, /obj/effect/turf_decal/stripes/line{ @@ -72310,17 +72379,6 @@ /obj/effect/turf_decal/tile/neutral/fourcorners, /turf/open/floor/iron/dark, /area/station/service/chapel) -"scv" = ( -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/structure/disposalpipe/segment, -/obj/machinery/camera/directional/east{ - c_tag = "Cargo Bay - Delivery Office"; - name = "cargo camera" - }, -/obj/effect/turf_decal/tile/brown, -/obj/machinery/light/directional/east, -/turf/open/floor/iron, -/area/station/cargo/sorting) "scy" = ( /obj/machinery/atmospherics/components/trinary/mixer{ dir = 4 @@ -72839,12 +72897,6 @@ }, /turf/open/floor/iron, /area/station/maintenance/port) -"sjJ" = ( -/obj/structure/table/reinforced, -/obj/machinery/microwave/engineering/cell_included, -/obj/structure/sign/poster/random/directional/west, -/turf/open/floor/wood, -/area/station/engineering/break_room) "ske" = ( /obj/effect/spawner/random/entertainment/arcade, /obj/effect/turf_decal/tile/neutral/fourcorners, @@ -73339,12 +73391,6 @@ /obj/effect/turf_decal/tile/neutral/fourcorners, /turf/open/floor/iron, /area/station/hallway/primary/central/aft) -"sqW" = ( -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/structure/disposalpipe/segment, -/obj/effect/turf_decal/tile/neutral/fourcorners, -/turf/open/floor/iron, -/area/station/cargo/sorting) "sqX" = ( /obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2{ dir = 1 @@ -82076,25 +82122,6 @@ /obj/effect/turf_decal/stripes/white/line, /turf/open/floor/wood, /area/station/engineering/break_room) -"uzn" = ( -/obj/structure/table/reinforced, -/obj/machinery/door/firedoor, -/obj/item/folder/yellow{ - pixel_x = -6 - }, -/obj/item/pen{ - pixel_x = -6 - }, -/obj/effect/turf_decal/delivery, -/obj/machinery/door/window/right/directional/south{ - name = "Delivery Office Desk"; - req_access = list("shipping") - }, -/obj/structure/desk_bell{ - pixel_x = 7 - }, -/turf/open/floor/iron, -/area/station/cargo/sorting) "uzo" = ( /obj/structure/chair/office/light, /obj/structure/disposalpipe/segment{ @@ -82547,6 +82574,16 @@ /obj/effect/spawner/random/engineering/toolbox, /turf/open/floor/plating, /area/station/maintenance/department/electrical) +"uEx" = ( +/obj/structure/cable, +/obj/effect/decal/cleanable/dirt, +/obj/effect/turf_decal/tile/neutral/half/contrasted{ + dir = 8 + }, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/turf/open/floor/iron, +/area/station/maintenance/fore) "uED" = ( /obj/effect/turf_decal/tile/neutral/fourcorners, /turf/open/floor/iron, @@ -83980,6 +84017,14 @@ /obj/effect/turf_decal/stripes/corner, /turf/open/floor/iron/dark, /area/station/ai_monitored/security/armory) +"uVK" = ( +/obj/structure/cable, +/obj/effect/decal/cleanable/dirt, +/obj/effect/spawner/random/structure/steam_vent, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/turf/open/floor/plating, +/area/station/maintenance/fore) "uVZ" = ( /obj/structure/cable, /obj/machinery/duct, @@ -86033,17 +86078,6 @@ "vxs" = ( /turf/closed/wall/r_wall, /area/station/security/prison/visit) -"vxt" = ( -/obj/structure/disposalpipe/segment{ - dir = 9 - }, -/obj/effect/decal/cleanable/dirt, -/obj/structure/chair/office, -/obj/machinery/status_display/supply{ - pixel_x = 32 - }, -/turf/open/floor/iron, -/area/station/cargo/sorting) "vxu" = ( /obj/effect/turf_decal/siding/green{ dir = 1 @@ -87113,14 +87147,6 @@ }, /turf/open/floor/iron/white, /area/station/medical/pharmacy) -"vKx" = ( -/obj/structure/cable, -/obj/structure/disposalpipe/segment, -/obj/effect/decal/cleanable/dirt, -/obj/effect/turf_decal/delivery, -/obj/effect/turf_decal/tile/neutral/anticorner/contrasted, -/turf/open/floor/iron, -/area/station/maintenance/fore) "vKI" = ( /obj/item/radio/intercom/directional/west, /obj/effect/turf_decal/trimline/blue/filled/line{ @@ -90124,6 +90150,19 @@ }, /turf/open/floor/iron, /area/station/hallway/primary/central/fore) +"wxQ" = ( +/obj/structure/cable, +/obj/structure/disposalpipe/junction/yjunction{ + dir = 8 + }, +/obj/effect/decal/cleanable/dirt, +/obj/effect/turf_decal/tile/neutral/half/contrasted{ + dir = 4 + }, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/turf/open/floor/iron, +/area/station/maintenance/fore) "wyh" = ( /obj/structure/disposalpipe/segment{ dir = 10 @@ -119146,7 +119185,7 @@ uiP vkg wlS vQj -sjJ +ntU cJX fhr kTd @@ -136923,8 +136962,8 @@ uNY squ pEU cwh -fCm -giO +riZ +pTz cwh cwh udd @@ -138639,8 +138678,8 @@ pKn vsA fsl elS -eke -vKx +wxQ +mXI cCb wQv oDR @@ -138897,7 +138936,7 @@ sPo vxL jdL jdL -vkN +qSr jdL mDP szg @@ -139154,7 +139193,7 @@ hEQ weX iLF jdL -rUV +uEx jdL gJI ttP @@ -139411,7 +139450,7 @@ vyG dRo tpI jdL -fYK +fGW jdL lgc dfk @@ -139668,7 +139707,7 @@ uTB wak xor jdL -oFk +uVK jdL lDi lHC @@ -139925,7 +139964,7 @@ nmb kYn djn jdL -eNn +kFJ jdL aix wHa @@ -139951,12 +139990,12 @@ mZU whb uBZ pso -sqW -sqW -scv -eYZ -vxt -uzn +aMz +aMz +lxX +gow +gaH +llk eUH dvy lSl @@ -140182,7 +140221,7 @@ xwO liM xGK jdL -eNn +kFJ jdL ncT hTl @@ -140439,9 +140478,9 @@ sma tyU kvK sKC -cxv -joP -jnd +lKs +dAA +fGC udk uyt iRP diff --git a/_maps/map_files/IceBoxStation/IceBoxStation.dmm b/_maps/map_files/IceBoxStation/IceBoxStation.dmm index bdde1b185ee..21ce5c6368c 100644 --- a/_maps/map_files/IceBoxStation/IceBoxStation.dmm +++ b/_maps/map_files/IceBoxStation/IceBoxStation.dmm @@ -1,12 +1,4 @@ //MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE -"aaf" = ( -/obj/structure/table/glass, -/obj/machinery/microwave/engineering/cell_included, -/obj/effect/turf_decal/tile/brown/anticorner/contrasted{ - dir = 4 - }, -/turf/open/floor/iron/white, -/area/station/medical/break_room) "aak" = ( /obj/structure/stairs/south, /obj/structure/railing{ @@ -1053,12 +1045,6 @@ /obj/structure/cable, /turf/open/floor/iron, /area/station/hallway/secondary/entry) -"arO" = ( -/obj/effect/turf_decal/tile/blue, -/obj/machinery/light/directional/south, -/obj/structure/extinguisher_cabinet/directional/south, -/turf/open/floor/iron, -/area/station/hallway/primary/starboard) "arT" = ( /obj/machinery/computer/security/labor{ dir = 4 @@ -2827,6 +2813,15 @@ /obj/structure/cable, /turf/open/floor/iron, /area/station/hallway/primary/central) +"aTJ" = ( +/obj/effect/spawner/structure/window/reinforced, +/obj/machinery/door/poddoor/shutters/preopen{ + id = "pharmacy_shutters"; + name = "Pharmacy Shutters"; + dir = 4 + }, +/turf/open/floor/plating, +/area/station/medical/pharmacy) "aTT" = ( /obj/structure/closet/toolcloset, /obj/effect/turf_decal/tile/yellow/half/contrasted, @@ -8253,6 +8248,30 @@ }, /turf/open/floor/circuit, /area/station/ai_monitored/turret_protected/ai) +"cvp" = ( +/obj/structure/table/reinforced, +/obj/machinery/door/firedoor, +/obj/machinery/door/window/right/directional/east{ + name = "Pharmacy Desk"; + req_access = list("pharmacy") + }, +/obj/item/folder/white{ + pixel_x = -5 + }, +/obj/item/pen{ + pixel_x = -5 + }, +/obj/structure/desk_bell{ + pixel_x = 7 + }, +/obj/effect/turf_decal/tile/yellow/fourcorners, +/obj/machinery/door/poddoor/shutters/preopen{ + id = "pharmacy_shutters"; + name = "Pharmacy Shutters"; + dir = 4 + }, +/turf/open/floor/iron, +/area/station/medical/pharmacy) "cvq" = ( /obj/machinery/atmospherics/components/unary/vent_pump/on/layer4, /obj/effect/turf_decal/tile/red/half/contrasted{ @@ -10714,30 +10733,6 @@ }, /turf/open/floor/glass/reinforced, /area/station/science/xenobiology) -"dff" = ( -/obj/structure/table/reinforced, -/obj/machinery/door/firedoor, -/obj/machinery/door/window/right/directional/east{ - name = "Pharmacy Desk"; - req_access = list("pharmacy") - }, -/obj/item/folder/white{ - pixel_x = -5 - }, -/obj/item/pen{ - pixel_x = -5 - }, -/obj/structure/desk_bell{ - pixel_x = 7 - }, -/obj/effect/turf_decal/tile/yellow/fourcorners, -/obj/machinery/door/poddoor/shutters/preopen{ - id = "pharmacy_shutters"; - name = "Pharmacy Shutters"; - dir = 4 - }, -/turf/open/floor/iron, -/area/station/medical/pharmacy) "dfq" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/cyan/visible, /turf/closed/wall/r_wall, @@ -15604,11 +15599,6 @@ /obj/effect/turf_decal/tile/neutral, /turf/open/floor/iron, /area/station/commons/dorms) -"eGz" = ( -/obj/structure/cable, -/obj/effect/spawner/structure/window/reinforced, -/turf/open/floor/plating, -/area/station/security/prison/visit) "eGA" = ( /obj/machinery/computer/prisoner/management{ dir = 1 @@ -15921,6 +15911,14 @@ /obj/structure/cable, /turf/open/floor/iron, /area/station/cargo/storage) +"eMi" = ( +/obj/structure/cable, +/obj/machinery/door/airlock/security/glass{ + name = "Permabrig Visitation" + }, +/obj/effect/mapping_helpers/airlock/access/any/security/brig, +/turf/open/floor/plating, +/area/station/security/prison/visit) "eMr" = ( /obj/effect/spawner/structure/window/reinforced, /obj/machinery/atmospherics/pipe/bridge_pipe/cyan/visible, @@ -16957,24 +16955,6 @@ /obj/effect/decal/cleanable/dirt, /turf/open/floor/plating, /area/station/maintenance/department/chapel) -"fdO" = ( -/obj/structure/table/glass, -/obj/item/stack/cable_coil, -/obj/item/stack/cable_coil, -/obj/item/screwdriver{ - pixel_x = 2; - pixel_y = 11 - }, -/obj/item/grenade/chem_grenade, -/obj/item/grenade/chem_grenade, -/obj/item/grenade/chem_grenade, -/obj/item/grenade/chem_grenade, -/obj/effect/turf_decal/tile/yellow/half/contrasted{ - dir = 1 - }, -/obj/structure/extinguisher_cabinet/directional/north, -/turf/open/floor/iron/white, -/area/station/medical/pharmacy) "fdP" = ( /obj/structure/bonfire, /obj/item/melee/roastingstick, @@ -17173,16 +17153,6 @@ }, /turf/open/floor/iron, /area/station/engineering/lobby) -"fib" = ( -/obj/machinery/smartfridge/chemistry/preloaded, -/obj/machinery/door/firedoor, -/obj/machinery/door/poddoor/shutters/preopen{ - id = "pharmacy_shutters2"; - name = "Pharmacy Shutters"; - dir = 4 - }, -/turf/open/floor/iron/white, -/area/station/medical/pharmacy) "fij" = ( /obj/structure/cable, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -17897,28 +17867,6 @@ /obj/item/storage/box/prisoner, /turf/open/floor/iron/showroomfloor, /area/station/security/processing) -"ftB" = ( -/obj/machinery/camera{ - c_tag = "Medbay Pharmacy"; - dir = 9; - network = list("ss13","medbay") - }, -/obj/effect/turf_decal/tile/yellow/half/contrasted{ - dir = 1 - }, -/obj/machinery/shower/directional/south, -/obj/structure/railing{ - dir = 4 - }, -/obj/structure/fluff{ - desc = "What, you think the water just magically soaks into the metallic flooring?"; - icon = 'icons/obj/mining_zones/survival_pod.dmi'; - icon_state = "fan_tiny"; - name = "shower drain" - }, -/obj/effect/turf_decal/stripes/white/end, -/turf/open/floor/iron/white, -/area/station/medical/pharmacy) "ftJ" = ( /obj/structure/table/reinforced, /obj/machinery/door/poddoor/shutters/preopen{ @@ -22254,25 +22202,6 @@ /obj/item/reagent_containers/dropper, /turf/open/floor/iron/cafeteria, /area/station/science/lab) -"gNA" = ( -/obj/structure/table/reinforced, -/obj/item/folder/white, -/obj/item/pen, -/obj/machinery/door/firedoor, -/obj/machinery/door/window/right/directional/east{ - base_state = "left"; - icon_state = "left"; - name = "Pharmacy Desk"; - req_access = list("pharmacy") - }, -/obj/effect/turf_decal/tile/yellow/fourcorners, -/obj/machinery/door/poddoor/shutters/preopen{ - id = "pharmacy_shutters2"; - name = "Pharmacy Shutters"; - dir = 4 - }, -/turf/open/floor/iron, -/area/station/medical/pharmacy) "gNH" = ( /obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ dir = 8 @@ -29812,6 +29741,16 @@ /obj/effect/turf_decal/tile/yellow/opposingcorners, /turf/open/floor/iron/white, /area/station/maintenance/port/fore) +"jho" = ( +/obj/machinery/smartfridge/chemistry/preloaded, +/obj/machinery/door/firedoor, +/obj/machinery/door/poddoor/shutters/preopen{ + id = "pharmacy_shutters2"; + name = "Pharmacy Shutters"; + dir = 4 + }, +/turf/open/floor/iron/white, +/area/station/medical/pharmacy) "jhy" = ( /obj/effect/turf_decal/tile/brown, /turf/open/floor/iron, @@ -33600,15 +33539,6 @@ /obj/structure/cable, /turf/open/floor/plating, /area/station/ai_monitored/turret_protected/aisat/maint) -"kpb" = ( -/obj/machinery/disposal/bin, -/obj/structure/disposalpipe/trunk, -/obj/effect/turf_decal/tile/yellow/half/contrasted{ - dir = 1 - }, -/obj/machinery/firealarm/directional/north, -/turf/open/floor/iron/white, -/area/station/medical/pharmacy) "kpf" = ( /obj/effect/turf_decal/tile/neutral/diagonal_edge, /obj/machinery/oven/range, @@ -35279,16 +35209,6 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/iron/dark, /area/station/medical/cryo) -"kNg" = ( -/obj/machinery/smartfridge/chemistry/preloaded, -/obj/machinery/door/firedoor, -/obj/machinery/door/poddoor/shutters/preopen{ - id = "pharmacy_shutters"; - name = "Pharmacy Shutters"; - dir = 4 - }, -/turf/open/floor/iron/white, -/area/station/medical/pharmacy) "kNi" = ( /obj/structure/cable, /obj/structure/disposalpipe/segment{ @@ -37394,6 +37314,12 @@ /obj/effect/decal/cleanable/robot_debris, /turf/open/floor/iron/dark/textured_large, /area/station/bitrunning/den) +"lts" = ( +/obj/effect/turf_decal/tile/blue, +/obj/machinery/light/directional/south, +/obj/structure/extinguisher_cabinet/directional/south, +/turf/open/floor/iron, +/area/station/hallway/primary/starboard) "ltE" = ( /obj/structure/closet/crate/freezer, /obj/item/reagent_containers/blood/random, @@ -39638,6 +39564,14 @@ /obj/structure/cable, /turf/open/floor/wood/parquet, /area/station/service/bar/atrium) +"meF" = ( +/obj/machinery/chem_dispenser, +/obj/structure/window/reinforced/spawner/directional/west, +/obj/machinery/light/directional/north, +/obj/effect/turf_decal/tile/yellow/full, +/obj/item/radio/intercom/directional/north, +/turf/open/floor/iron/white/smooth_large, +/area/station/medical/pharmacy) "meG" = ( /obj/item/kirbyplants/random, /obj/structure/cable, @@ -41094,6 +41028,28 @@ /obj/structure/cable/layer3, /turf/open/floor/iron/dark, /area/station/ai_monitored/turret_protected/aisat/hallway) +"mEi" = ( +/obj/machinery/camera{ + c_tag = "Medbay Pharmacy"; + dir = 9; + network = list("ss13","medbay") + }, +/obj/effect/turf_decal/tile/yellow/half/contrasted{ + dir = 1 + }, +/obj/machinery/shower/directional/south, +/obj/structure/railing{ + dir = 4 + }, +/obj/structure/fluff{ + desc = "What, you think the water just magically soaks into the metallic flooring?"; + icon = 'icons/obj/mining_zones/survival_pod.dmi'; + icon_state = "fan_tiny"; + name = "shower drain" + }, +/obj/effect/turf_decal/stripes/white/end, +/turf/open/floor/iron/white, +/area/station/medical/pharmacy) "mEv" = ( /obj/structure/rack, /obj/effect/turf_decal/tile/neutral/fourcorners, @@ -42406,6 +42362,15 @@ "naX" = ( /turf/closed/wall/mineral/iron, /area/station/engineering/atmos/mix) +"nbd" = ( +/obj/machinery/disposal/bin, +/obj/structure/disposalpipe/trunk, +/obj/effect/turf_decal/tile/yellow/half/contrasted{ + dir = 1 + }, +/obj/machinery/firealarm/directional/north, +/turf/open/floor/iron/white, +/area/station/medical/pharmacy) "nbi" = ( /obj/item/radio/intercom/directional/west, /obj/effect/turf_decal/tile/yellow{ @@ -43049,14 +43014,6 @@ /obj/effect/spawner/random/trash/mess, /turf/open/floor/plating, /area/station/maintenance/department/medical/morgue) -"njP" = ( -/obj/machinery/chem_mass_spec, -/obj/effect/turf_decal/tile/yellow/anticorner/contrasted{ - dir = 8 - }, -/obj/structure/sign/warning/no_smoking/directional/west, -/turf/open/floor/iron/white, -/area/station/medical/pharmacy) "njT" = ( /obj/effect/turf_decal/stripes/line{ dir = 6 @@ -55827,14 +55784,6 @@ /obj/effect/turf_decal/tile/bar/opposingcorners, /turf/open/floor/iron, /area/station/service/bar) -"qYp" = ( -/obj/machinery/chem_dispenser, -/obj/structure/window/reinforced/spawner/directional/west, -/obj/machinery/light/directional/north, -/obj/effect/turf_decal/tile/yellow/full, -/obj/item/radio/intercom/directional/north, -/turf/open/floor/iron/white/smooth_large, -/area/station/medical/pharmacy) "qYw" = ( /obj/effect/turf_decal/stripes/line{ dir = 8 @@ -60841,6 +60790,14 @@ "sAS" = ( /turf/closed/wall, /area/station/commons/storage/art) +"sAT" = ( +/obj/machinery/chem_mass_spec, +/obj/effect/turf_decal/tile/yellow/anticorner/contrasted{ + dir = 8 + }, +/obj/structure/sign/warning/no_smoking/directional/west, +/turf/open/floor/iron/white, +/area/station/medical/pharmacy) "sBi" = ( /obj/structure/cable, /obj/effect/decal/cleanable/dirt, @@ -62634,6 +62591,16 @@ /obj/machinery/power/apc/auto_name/directional/west, /turf/open/floor/plating, /area/station/maintenance/solars/starboard/aft) +"tfp" = ( +/obj/machinery/smartfridge/chemistry/preloaded, +/obj/machinery/door/firedoor, +/obj/machinery/door/poddoor/shutters/preopen{ + id = "pharmacy_shutters"; + name = "Pharmacy Shutters"; + dir = 4 + }, +/turf/open/floor/iron/white, +/area/station/medical/pharmacy) "tfu" = ( /obj/structure/sign/warning/electric_shock, /turf/closed/wall, @@ -63281,6 +63248,25 @@ /obj/structure/window/reinforced/spawner/directional/south, /turf/open/floor/iron/white/textured, /area/station/security/medical) +"tpY" = ( +/obj/structure/table/reinforced, +/obj/item/folder/white, +/obj/item/pen, +/obj/machinery/door/firedoor, +/obj/machinery/door/window/right/directional/east{ + base_state = "left"; + icon_state = "left"; + name = "Pharmacy Desk"; + req_access = list("pharmacy") + }, +/obj/effect/turf_decal/tile/yellow/fourcorners, +/obj/machinery/door/poddoor/shutters/preopen{ + id = "pharmacy_shutters2"; + name = "Pharmacy Shutters"; + dir = 4 + }, +/turf/open/floor/iron, +/area/station/medical/pharmacy) "tqk" = ( /obj/structure/table, /obj/item/paper_bin{ @@ -65841,6 +65827,24 @@ /obj/structure/beebox, /turf/open/floor/grass, /area/station/service/hydroponics) +"uhn" = ( +/obj/structure/table/glass, +/obj/item/stack/cable_coil, +/obj/item/stack/cable_coil, +/obj/item/screwdriver{ + pixel_x = 2; + pixel_y = 11 + }, +/obj/item/grenade/chem_grenade, +/obj/item/grenade/chem_grenade, +/obj/item/grenade/chem_grenade, +/obj/item/grenade/chem_grenade, +/obj/effect/turf_decal/tile/yellow/half/contrasted{ + dir = 1 + }, +/obj/structure/extinguisher_cabinet/directional/north, +/turf/open/floor/iron/white, +/area/station/medical/pharmacy) "uhs" = ( /obj/structure/railing/corner, /obj/machinery/camera/directional/south{ @@ -69575,7 +69579,9 @@ /area/station/engineering/atmos) "vtk" = ( /obj/machinery/newscaster/directional/east, -/obj/structure/bed/pod, +/obj/structure/bed/medical/anchored{ + dir = 4 + }, /obj/effect/turf_decal/tile/blue/full, /turf/open/floor/iron/large, /area/station/medical/treatment_center) @@ -74760,15 +74766,6 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/open/floor/plating, /area/station/maintenance/port/aft) -"wWn" = ( -/obj/effect/spawner/structure/window/reinforced, -/obj/machinery/door/poddoor/shutters/preopen{ - id = "pharmacy_shutters"; - name = "Pharmacy Shutters"; - dir = 4 - }, -/turf/open/floor/plating, -/area/station/medical/pharmacy) "wWJ" = ( /turf/open/floor/iron/dark, /area/station/medical/morgue) @@ -78275,6 +78272,14 @@ }, /turf/open/floor/iron/dark/smooth_large, /area/station/engineering/main) +"xZo" = ( +/obj/structure/table/glass, +/obj/machinery/microwave/engineering/cell_included, +/obj/effect/turf_decal/tile/brown/anticorner/contrasted{ + dir = 4 + }, +/turf/open/floor/iron/white, +/area/station/medical/break_room) "xZA" = ( /turf/open/floor/iron/checker, /area/station/science/lab) @@ -170047,7 +170052,7 @@ yiL yiL yiL eDq -eGz +eMi dAZ emM wob @@ -243858,7 +243863,7 @@ bai azw jqE kZb -njP +sAT azw fMg fqW @@ -244627,7 +244632,7 @@ lso dEV bai azw -fdO +uhn fTC xSu azw @@ -244882,9 +244887,9 @@ exw exw cwh dEV -arO +lts azw -ftB +mEi eyc qPt uTc @@ -245402,8 +245407,8 @@ cJw dip bHO azw -gNA -fib +tpY +jho azw eiY tZm @@ -245655,7 +245660,7 @@ vwO hHg bai azw -kpb +nbd uTk sJA sHc @@ -245912,7 +245917,7 @@ lso aAa bai azw -qYp +meF vYH nah azw @@ -246426,9 +246431,9 @@ mqq kjK bai azw -wWn -dff -kNg +aTJ +cvp +tfp azw gIY iBj @@ -251337,7 +251342,7 @@ xMM nqd ttO mFE -aaf +xZo pWY rQI phj diff --git a/_maps/map_files/VoidRaptor/VoidRaptor.dmm b/_maps/map_files/VoidRaptor/VoidRaptor.dmm index eedc9a22ce0..3d65047a8f1 100644 --- a/_maps/map_files/VoidRaptor/VoidRaptor.dmm +++ b/_maps/map_files/VoidRaptor/VoidRaptor.dmm @@ -38755,6 +38755,7 @@ id = "garbage" }, /obj/machinery/light/small/directional/south, +/obj/item/radio/intercom/directional/south, /turf/open/floor/iron/smooth_large, /area/station/maintenance/disposal) "kWE" = ( @@ -52565,11 +52566,7 @@ "oLT" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/machinery/computer/pod/old/mass_driver_controller/trash{ - pixel_x = 24; - pixel_y = -7 - }, -/obj/machinery/airalarm/directional/east{ - pixel_x = 32 + pixel_x = 24 }, /obj/structure/cable, /turf/open/floor/catwalk_floor/iron_smooth, @@ -53765,6 +53762,9 @@ dir = 6; id = "garbage" }, +/obj/machinery/airalarm/directional/east{ + pixel_x = 32 + }, /turf/open/floor/iron/smooth_large, /area/station/maintenance/disposal) "pci" = ( @@ -59343,7 +59343,6 @@ dir = 4 }, /obj/machinery/light/small/directional/north, -/obj/item/radio/intercom/directional/north, /obj/effect/turf_decal/stripes/end{ dir = 8 }, diff --git a/_maps/shuttles/skyrat/pirate_nri_raider.dmm b/_maps/shuttles/skyrat/pirate_nri_raider.dmm index 36fc58bbf66..5c44bc377d4 100644 --- a/_maps/shuttles/skyrat/pirate_nri_raider.dmm +++ b/_maps/shuttles/skyrat/pirate_nri_raider.dmm @@ -385,10 +385,6 @@ }, /obj/item/clothing/under/costume/nri/engineer, /obj/item/clothing/mask/balaclavaadjust, -/obj/item/clothing/suit/armor/vest/warden/peacekeeper{ - name = "advanced imperial jacket"; - desc = "A dark blue jacket with blue rank pips and body armor strapped on top." - }, /obj/item/clothing/under/syndicate/rus_army/cin_surplus/marine, /obj/item/clothing/glasses/meson/engine, /obj/item/storage/belt/military/cin_surplus/marine, @@ -824,10 +820,6 @@ /obj/item/clothing/under/costume/nri/medic, /obj/item/clothing/glasses/hud/security/sunglasses/peacekeeper, /obj/item/clothing/mask/balaclavaadjust, -/obj/item/clothing/suit/armor/vest/warden/peacekeeper{ - name = "advanced imperial jacket"; - desc = "A dark blue jacket with blue rank pips and body armor strapped on top." - }, /obj/item/clothing/under/syndicate/rus_army/cin_surplus/marine, /obj/item/storage/belt/military/cin_surplus/marine, /obj/item/clothing/suit/armor/vest/cin_surplus_vest, @@ -954,10 +946,6 @@ /obj/item/clothing/under/costume/nri/captain, /obj/item/clothing/glasses/hud/security/sunglasses/peacekeeper, /obj/item/clothing/mask/balaclavaadjust, -/obj/item/clothing/suit/armor/vest/warden/peacekeeper{ - name = "advanced imperial jacket"; - desc = "A dark blue jacket with blue rank pips and body armor strapped on top." - }, /obj/item/clothing/under/syndicate/rus_army/cin_surplus/marine, /obj/item/storage/belt/military/cin_surplus/marine, /obj/item/clothing/suit/armor/vest/cin_surplus_vest, diff --git a/code/__DEFINES/admin.dm b/code/__DEFINES/admin.dm index 00ffee31d26..1c5e79377b8 100644 --- a/code/__DEFINES/admin.dm +++ b/code/__DEFINES/admin.dm @@ -80,19 +80,19 @@ #define ADMIN_SEE_ZLEVEL_LAYOUT "(SEE Z-LEVEL LAYOUT)" /atom/proc/Admin_Coordinates_Readable(area_name, admin_jump_ref) - var/turf/T = Safe_COORD_Location() - return T ? "[area_name ? "[get_area_name(T, TRUE)] " : " "]([T.x],[T.y],[T.z])[admin_jump_ref ? " [ADMIN_JMP(T)]" : ""]" : "nonexistent location" + var/turf/turf_at_coords = Safe_COORD_Location() + return turf_at_coords ? "[area_name ? "[get_area_name(turf_at_coords, TRUE)] " : " "]([turf_at_coords.x],[turf_at_coords.y],[turf_at_coords.z])[admin_jump_ref ? " [ADMIN_JMP(turf_at_coords)]" : ""]" : "nonexistent location" /atom/proc/Safe_COORD_Location() - var/atom/A = drop_location() - if(!A) + var/atom/drop_atom = drop_location() + if(!drop_atom) return //not a valid atom. - var/turf/T = get_step(A, 0) //resolve where the thing is. - if(!T) //incase it's inside a valid drop container, inside another container. ie if a mech picked up a closet and has it inside it's internal storage. - var/atom/last_try = A.loc?.drop_location() //one last try, otherwise fuck it. + var/turf/drop_turf = get_step(drop_atom, 0) //resolve where the thing is. + if(!drop_turf) //incase it's inside a valid drop container, inside another container. ie if a mech picked up a closet and has it inside it's internal storage. + var/atom/last_try = drop_atom.loc?.drop_location() //one last try, otherwise fuck it. if(last_try) - T = get_step(last_try, 0) - return T + drop_turf = get_step(last_try, 0) + return drop_turf /turf/Safe_COORD_Location() return src diff --git a/code/__DEFINES/colors.dm b/code/__DEFINES/colors.dm index 802abe2c349..2b253c90aad 100644 --- a/code/__DEFINES/colors.dm +++ b/code/__DEFINES/colors.dm @@ -46,6 +46,7 @@ #define COLOR_SOFT_RED "#FA8282" #define COLOR_CULT_RED "#960000" #define COLOR_BUBBLEGUM_RED "#950A0A" +#define COLOR_CARP_RIFT_RED "#ff330030" #define COLOR_YELLOW "#FFFF00" #define COLOR_VIVID_YELLOW "#FBFF23" diff --git a/code/__DEFINES/dcs/flags.dm b/code/__DEFINES/dcs/flags.dm index 7543157319f..9b181e226a9 100644 --- a/code/__DEFINES/dcs/flags.dm +++ b/code/__DEFINES/dcs/flags.dm @@ -23,11 +23,15 @@ /// When this is used your Detach proc should have the same signature as your Attach proc #define ELEMENT_COMPLEX_DETACH (1 << 2) /** - * Stops lists used as arguments for the element from being sorted by the dcs_check_list_arguments unit test. - * For when changing the position of the keys is undesiderable, like for color matrices. + * Elements with this flag will have their datum lists arguments compared as is, + * without the contents being sorted alpha-numerically first. + * This is good for those elements where the position of the keys matter, like in the case of color matrices. */ #define ELEMENT_DONT_SORT_LIST_ARGS (1<<3) -/// Elements with this flag will be ignored by the test (I would rather put some faith than have contributors stringify connect loc lists). +/** + * Elements with this flag will be ignored by the dcs_check_list_arguments test. + * A good example is connect_loc, for which it's pratically undoable unless we force every signal proc to have a different name. + */ #define ELEMENT_NO_LIST_UNIT_TEST (1<<4) // How multiple components of the exact same type are handled in the same datum diff --git a/code/__DEFINES/dcs/signals/signals_atom/signals_atom_x_act.dm b/code/__DEFINES/dcs/signals/signals_atom/signals_atom_x_act.dm index e1811a24af3..7a02dbddabb 100644 --- a/code/__DEFINES/dcs/signals/signals_atom/signals_atom_x_act.dm +++ b/code/__DEFINES/dcs/signals/signals_atom/signals_atom_x_act.dm @@ -2,6 +2,10 @@ // When the signal is called: (signal arguments) // All signals send the source datum of the signal as the first argument +///from the [EX_ACT] wrapper macro: (severity, target) +#define COMSIG_ATOM_PRE_EX_ACT "atom_pre_ex_act" + /// if returned, don't let the explosion act on this atom + #define COMPONENT_CANCEL_EX_ACT (1<<0) ///from the [EX_ACT] wrapper macro: (severity, target) #define COMSIG_ATOM_EX_ACT "atom_ex_act" ///from base of atom/emp_act(): (severity). return EMP protection flags diff --git a/code/__DEFINES/dcs/signals/signals_mob/signals_mob_carbon.dm b/code/__DEFINES/dcs/signals/signals_mob/signals_mob_carbon.dm index 1d5ab544d10..dd6f6fdccc4 100644 --- a/code/__DEFINES/dcs/signals/signals_mob/signals_mob_carbon.dm +++ b/code/__DEFINES/dcs/signals/signals_mob/signals_mob_carbon.dm @@ -33,7 +33,7 @@ ///from base of /obj/item/bodypart/proc/try_attach_limb(): (new_limb, special) #define COMSIG_CARBON_ATTACH_LIMB "carbon_attach_limb" /// Called from bodypart being attached /obj/item/bodypart/proc/try_attach_limb(mob/living/carbon/new_owner, special) -#define COMSIG_BODYPART_ATTACHED "bodypart_removed" +#define COMSIG_BODYPART_ATTACHED "bodypart_attached" ///from base of /obj/item/bodypart/proc/try_attach_limb(): (new_limb, special) #define COMSIG_CARBON_POST_ATTACH_LIMB "carbon_post_attach_limb" ///from /obj/item/bodypart/proc/receive_damage, sent from the limb owner (limb, brute, burn) @@ -132,10 +132,6 @@ #define COMSIG_HUMAN_CORETEMP_CHANGE "human_coretemp_change" ///from /datum/species/handle_fire. Called when the human is set on fire and burning clothes and stuff #define COMSIG_HUMAN_BURNING "human_burning" -///from mob/living/carbon/human/UnarmedAttack(): (atom/target, proximity, modifiers) -#define COMSIG_HUMAN_EARLY_UNARMED_ATTACK "human_early_unarmed_attack" -///from mob/living/carbon/human/UnarmedAttack(): (atom/target, proximity, modifiers) -#define COMSIG_HUMAN_MELEE_UNARMED_ATTACK "human_melee_unarmed_attack" ///from /mob/living/carbon/human/proc/check_shields(): (atom/hit_by, damage, attack_text, attack_type, armour_penetration, damage_type) #define COMSIG_HUMAN_CHECK_SHIELDS "human_check_shields" #define SHIELD_BLOCK (1<<0) 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 b70f7f9013d..ceebe7f304b 100644 --- a/code/__DEFINES/dcs/signals/signals_mob/signals_mob_living.dm +++ b/code/__DEFINES/dcs/signals/signals_mob/signals_mob_living.dm @@ -133,7 +133,11 @@ #define COMSIG_LIVING_SLAM_TABLE "living_slam_table" ///from /obj/item/hand_item/slapper/attack(): (source=mob/living/slapper, mob/living/slapped) #define COMSIG_LIVING_SLAP_MOB "living_slap_mob" -///(NOT on humans) from mob/living/*/UnarmedAttack(): (mob/living/source, atom/target, proximity, modifiers) +/// from /mob/living/*/UnarmedAttack(), before sending [COMSIG_LIVING_UNARMED_ATTACK]: (mob/living/source, atom/target, proximity, modifiers) +/// The only reason this exists is so hulk can fire before Fists of the North Star. +/// Note that this is called before [/mob/living/proc/can_unarmed_attack] is called, so be wary of that. +#define COMSIG_LIVING_EARLY_UNARMED_ATTACK "human_pre_attack_hand" +/// from mob/living/*/UnarmedAttack(): (mob/living/source, atom/target, proximity, modifiers) #define COMSIG_LIVING_UNARMED_ATTACK "living_unarmed_attack" ///From base of mob/living/MobBump() (mob/living) #define COMSIG_LIVING_MOB_BUMP "living_mob_bump" diff --git a/code/__DEFINES/dcs/signals/signals_mob/signals_mob_simple.dm b/code/__DEFINES/dcs/signals/signals_mob/signals_mob_simple.dm index 65d96ea8c4c..8b19c1f0054 100644 --- a/code/__DEFINES/dcs/signals/signals_mob/signals_mob_simple.dm +++ b/code/__DEFINES/dcs/signals/signals_mob/signals_mob_simple.dm @@ -7,7 +7,7 @@ // /mob/living/simple_animal/hostile signals ///before attackingtarget has happened, source is the attacker and target is the attacked #define COMSIG_HOSTILE_PRE_ATTACKINGTARGET "hostile_pre_attackingtarget" - #define COMPONENT_HOSTILE_NO_ATTACK (1<<0) //cancel the attack, only works before attack happens + #define COMPONENT_HOSTILE_NO_ATTACK COMPONENT_CANCEL_ATTACK_CHAIN //cancel the attack, only works before attack happens ///after attackingtarget has happened, source is the attacker and target is the attacked, extra argument for if the attackingtarget was successful #define COMSIG_HOSTILE_POST_ATTACKINGTARGET "hostile_post_attackingtarget" ///from base of mob/living/basic/regal_rat: (mob/living/basic/regal_rat/king) diff --git a/code/__DEFINES/explosions.dm b/code/__DEFINES/explosions.dm index 0ce9644af1c..a1645b659d1 100644 --- a/code/__DEFINES/explosions.dm +++ b/code/__DEFINES/explosions.dm @@ -23,8 +23,10 @@ if(!(target.flags_1 & PREVENT_CONTENTS_EXPLOSION_1)) { \ target.contents_explosion(##args);\ };\ - SEND_SIGNAL(target, COMSIG_ATOM_EX_ACT, ##args);\ - target.ex_act(##args); + if(!(SEND_SIGNAL(target, COMSIG_ATOM_PRE_EX_ACT, ##args) & COMPONENT_CANCEL_EX_ACT)) { \ + SEND_SIGNAL(target, COMSIG_ATOM_EX_ACT, ##args);\ + target.ex_act(##args);\ + } // Internal explosion argument list keys. // Must match the arguments to [/datum/controller/subsystem/explosions/proc/propagate_blastwave] diff --git a/code/__DEFINES/megafauna.dm b/code/__DEFINES/megafauna.dm new file mode 100644 index 00000000000..981b8d49f52 --- /dev/null +++ b/code/__DEFINES/megafauna.dm @@ -0,0 +1,4 @@ +/// Temperature of drake fire hotspots +#define DRAKE_FIRE_TEMP 500 +/// Volume of drake fire hotspots +#define DRAKE_FIRE_EXPOSURE 50 diff --git a/code/__DEFINES/projectiles.dm b/code/__DEFINES/projectiles.dm index 3bc745756aa..a82ac8422c5 100644 --- a/code/__DEFINES/projectiles.dm +++ b/code/__DEFINES/projectiles.dm @@ -73,3 +73,9 @@ #define RETURN_POINT_VECTOR(ATOM, ANGLE, SPEED) (new /datum/point/vector(ATOM, null, null, null, null, ANGLE, SPEED)) #define RETURN_POINT_VECTOR_INCREMENT(ATOM, ANGLE, SPEED, AMT) (new /datum/point/vector(ATOM, null, null, null, null, ANGLE, SPEED, AMT)) + +/// The amount of energy that a standard energy weapon cell can hold +#define STANDARD_CELL_CHARGE 1000 +/// Macro to turn a number of laser shots into an energy cost, based on the above define +/// e.g. LASER_SHOTS(12, STANDARD_CELL_CHARGE) means 12 shots +#define LASER_SHOTS(X, MAX_CHARGE) (((100 * MAX_CHARGE) - ((100 * MAX_CHARGE) % X)) / (100 * X)) // I wish I could just use round, but it can't be used in datum members diff --git a/code/__DEFINES/reagents.dm b/code/__DEFINES/reagents.dm index 848d8127390..b668afc4d7f 100644 --- a/code/__DEFINES/reagents.dm +++ b/code/__DEFINES/reagents.dm @@ -89,6 +89,12 @@ #define CHEMICAL_QUANTISATION_LEVEL 0.0001 ///Default pH for reagents datum #define CHEMICAL_NORMAL_PH 7.000 +///Minimum pH attainable by a solution +#define CHEMICAL_MIN_PH 0 +///Maximum pH attainable by a solution +#define CHEMICAL_MAX_PH 14 +///Ionizing strength of strong acidic/basic buffer (volume/holder.total_volume)*strength. So for 1u added to 50u the ph will change by 0.4 +#define BUFFER_IONIZING_STRENGTH 30 ///The maximum temperature a reagent holder can attain #define CHEMICAL_MAXIMUM_TEMPERATURE 99999 diff --git a/code/__DEFINES/span.dm b/code/__DEFINES/span.dm index 7b23869988b..361c4d41b81 100644 --- a/code/__DEFINES/span.dm +++ b/code/__DEFINES/span.dm @@ -74,6 +74,7 @@ #define span_message(str) ("" + str + "") #define span_mind_control(str) ("" + str + "") #define span_minorannounce(str) ("" + str + "") +#define span_minoralert(str) ("" + str + "") #define span_monkey(str) ("" + str + "") #define span_name(str) ("" + str + "") #define span_narsie(str) ("" + str + "") @@ -85,6 +86,9 @@ #define span_papyrus(str) ("" + str + "") #define span_phobia(str) ("" + str + "") #define span_prefix(str) ("" + str + "") +#define span_priorityalert(str) ("" + str + "") +#define span_priorityannounce(str) ("" + str + "") +#define span_prioritytitle(str) ("" + str + "") #define span_purple(str) ("" + str + "") #define span_radio(str) ("" + str + "") #define span_reallybig(str) ("" + str + "") diff --git a/code/__DEFINES/traits.dm b/code/__DEFINES/traits.dm index e8e44e96867..0c55033e60a 100644 --- a/code/__DEFINES/traits.dm +++ b/code/__DEFINES/traits.dm @@ -939,6 +939,8 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai #define DISEASE_TRAIT "disease" #define SPECIES_TRAIT "species" #define ORGAN_TRAIT "organ" +/// Trait given by augmented limbs +#define AUGMENTATION_TRAIT "augments" /// Trait given by organ gained via abductor surgery #define ABDUCTOR_GLAND_TRAIT "abductor_gland" /// cannot be removed without admin intervention @@ -1326,3 +1328,10 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai ///Trait given by /datum/element/relay_attacker #define TRAIT_RELAYING_ATTACKER "relaying_attacker" + +/// Trait given while using /datum/action/cooldown/mob_cooldown/wing_buffet +#define TRAIT_WING_BUFFET "wing_buffet" +/// Trait given while tired after using /datum/action/cooldown/mob_cooldown/wing_buffet +#define TRAIT_WING_BUFFET_TIRED "wing_buffet_tired" +/// Trait given to a dragon who fails to defend their rifts +#define TRAIT_RIFT_FAILURE "fail_dragon_loser" diff --git a/code/__HELPERS/_lists.dm b/code/__HELPERS/_lists.dm index fb1603d650d..32e4135b965 100644 --- a/code/__HELPERS/_lists.dm +++ b/code/__HELPERS/_lists.dm @@ -429,9 +429,9 @@ return var/list/result = new if(skiprep) - for(var/e in first) - if(!(e in result) && !(e in second)) - UNTYPED_LIST_ADD(result, e) + for(var/entry in first) + if(!(entry in result) && !(entry in second)) + UNTYPED_LIST_ADD(result, entry) else result = first - second return result @@ -765,9 +765,9 @@ inserted_list.Cut(to_index, to_index + 1) else if(to_index > from_index) - var/a = to_index + var/temp = to_index to_index = from_index - from_index = a + from_index = temp for(var/i in 1 to len) inserted_list.Swap(from_index++, to_index++) diff --git a/code/__HELPERS/_string_lists.dm b/code/__HELPERS/_string_lists.dm index e0ff247a1c3..4d4a7ff94c8 100644 --- a/code/__HELPERS/_string_lists.dm +++ b/code/__HELPERS/_string_lists.dm @@ -13,8 +13,8 @@ GLOBAL_VAR(string_filename_current_key) if((filepath in GLOB.string_cache) && (key in GLOB.string_cache[filepath])) var/response = pick(GLOB.string_cache[filepath][key]) - var/regex/r = regex("@pick\\((\\D+?)\\)", "g") - response = r.Replace(response, GLOBAL_PROC_REF(strings_subkey_lookup)) + var/regex/needs_replacing = regex("@pick\\((\\D+?)\\)", "g") + response = needs_replacing.Replace(response, GLOBAL_PROC_REF(strings_subkey_lookup)) return response else CRASH("strings list not found: [STRING_DIRECTORY]/[filepath], index=[key]") diff --git a/code/__HELPERS/global_lists.dm b/code/__HELPERS/global_lists.dm index 994aa6cfa81..616469ecabf 100644 --- a/code/__HELPERS/global_lists.dm +++ b/code/__HELPERS/global_lists.dm @@ -56,9 +56,9 @@ /// Inits GLOB.species_list. Not using GLOBAL_LIST_INIT b/c it depends on GLOB.string_lists /proc/init_species_list() - for(var/spath in subtypesof(/datum/species)) - var/datum/species/S = new spath() - GLOB.species_list[S.id] = spath + for(var/species_path in subtypesof(/datum/species)) + var/datum/species/species = new species_path() + GLOB.species_list[species.id] = species_path sort_list(GLOB.species_list, GLOBAL_PROC_REF(cmp_typepaths_asc)) /// Inits GLOB.surgeries diff --git a/code/__HELPERS/icons.dm b/code/__HELPERS/icons.dm index 9ca77550be0..c2b2f1e33b2 100644 --- a/code/__HELPERS/icons.dm +++ b/code/__HELPERS/icons.dm @@ -210,26 +210,26 @@ world // Take the minimum color of two icons; combine transparency as if blending with ICON_ADD /icon/proc/MinColors(icon) - var/icon/I = new(src) - I.Opaque() - I.Blend(icon, ICON_SUBTRACT) - Blend(I, ICON_SUBTRACT) + var/icon/new_icon = new(src) + new_icon.Opaque() + new_icon.Blend(icon, ICON_SUBTRACT) + Blend(new_icon, ICON_SUBTRACT) // Take the maximum color of two icons; combine opacity as if blending with ICON_OR /icon/proc/MaxColors(icon) - var/icon/I + var/icon/new_icon if(isicon(icon)) - I = new(icon) + new_icon = new(icon) else // solid color - I = new(src) - I.Blend("#000000", ICON_OVERLAY) - I.SwapColor("#000000", null) - I.Blend(icon, ICON_OVERLAY) - var/icon/J = new(src) - J.Opaque() - I.Blend(J, ICON_SUBTRACT) - Blend(I, ICON_OR) + new_icon = new(src) + new_icon.Blend("#000000", ICON_OVERLAY) + new_icon.SwapColor("#000000", null) + new_icon.Blend(icon, ICON_OVERLAY) + var/icon/blend_icon = new(src) + blend_icon.Opaque() + new_icon.Blend(blend_icon, ICON_SUBTRACT) + Blend(new_icon, ICON_OR) // make this icon fully opaque--transparent pixels become black /icon/proc/Opaque(background = "#000000") @@ -247,10 +247,10 @@ world AddAlphaMask(mask) /icon/proc/AddAlphaMask(mask) - var/icon/M = new(mask) - M.Blend("#ffffff", ICON_SUBTRACT) + var/icon/mask_icon = new(mask) + mask_icon.Blend("#ffffff", ICON_SUBTRACT) // apply mask - Blend(M, ICON_ADD) + Blend(mask_icon, ICON_ADD) /* HSV format is represented as "#hhhssvv" or "#hhhssvvaa" @@ -843,15 +843,15 @@ world #undef PROCESS_OVERLAYS_OR_UNDERLAYS -/proc/getIconMask(atom/A)//By yours truly. Creates a dynamic mask for a mob/whatever. /N - var/icon/alpha_mask = new(A.icon,A.icon_state)//So we want the default icon and icon state of A. - for(var/V in A.overlays)//For every image in overlays. var/image/I will not work, don't try it. - var/image/I = V - if(I.layer>A.layer) +/proc/getIconMask(atom/atom_to_mask)//By yours truly. Creates a dynamic mask for a mob/whatever. /N + var/icon/alpha_mask = new(atom_to_mask.icon, atom_to_mask.icon_state)//So we want the default icon and icon state of atom_to_mask. + for(var/iterated_image in atom_to_mask.overlays)//For every image in overlays. var/image/image will not work, don't try it. + var/image/image = iterated_image + if(image.layer > atom_to_mask.layer) continue//If layer is greater than what we need, skip it. - var/icon/image_overlay = new(I.icon,I.icon_state)//Blend only works with icon objects. + var/icon/image_overlay = new(image.icon, image.icon_state)//Blend only works with icon objects. //Also, icons cannot directly set icon_state. Slower than changing variables but whatever. - alpha_mask.Blend(image_overlay,ICON_OR)//OR so they are lumped together in a nice overlay. + alpha_mask.Blend(image_overlay, ICON_OR)//OR so they are lumped together in a nice overlay. return alpha_mask//And now return the mask. /** @@ -892,17 +892,17 @@ world opacity_icon.AddAlphaMask(alpha_mask)//Likely the main source of lag for this proc. Probably not designed to run each tick. opacity_icon.ChangeOpacity(0.4)//Front end for MapColors so it's fast. 0.5 means half opacity and looks the best in my opinion. for(var/i in 1 to 5)//And now we add it as overlays. It's faster than creating an icon and then merging it. - var/image/I = image("icon" = opacity_icon, "icon_state" = A.icon_state, "layer" = layer+0.8)//So it's above other stuff but below weapons and the like. + var/image/camo_image = image("icon" = opacity_icon, "icon_state" = A.icon_state, "layer" = layer+0.8)//So it's above other stuff but below weapons and the like. switch(i)//Now to determine offset so the result is somewhat blurred. if(2) - I.pixel_x-- + camo_image.pixel_x-- if(3) - I.pixel_x++ + camo_image.pixel_x++ if(4) - I.pixel_y-- + camo_image.pixel_y-- if(5) - I.pixel_y++ - add_overlay(I)//And finally add the overlay. + camo_image.pixel_y++ + add_overlay(camo_image)//And finally add the overlay. /proc/getHologramIcon(icon/A, safety = TRUE, opacity = 0.5)//If safety is on, a new icon is not created. var/icon/flat_icon = safety ? A : new(A)//Has to be a new icon to not constantly change the same icon. @@ -958,54 +958,54 @@ world GLOBAL_LIST_EMPTY(friendly_animal_types) // Pick a random animal instead of the icon, and use that instead -/proc/getRandomAnimalImage(atom/A) +/proc/getRandomAnimalImage(atom/animal) if(!GLOB.friendly_animal_types.len) - for(var/T in typesof(/mob/living/simple_animal)) - var/mob/living/simple_animal/SA = T - if(initial(SA.gold_core_spawnable) == FRIENDLY_SPAWN) - GLOB.friendly_animal_types += SA + for(var/typepath in typesof(/mob/living/simple_animal)) + var/mob/living/simple_animal/simple_animal = typepath + if(initial(simple_animal.gold_core_spawnable) == FRIENDLY_SPAWN) + GLOB.friendly_animal_types += simple_animal - var/mob/living/simple_animal/SA = pick(GLOB.friendly_animal_types) + var/mob/living/simple_animal/simple_animal = pick(GLOB.friendly_animal_types) - var/icon = initial(SA.icon) - var/icon_state = initial(SA.icon_state) + var/icon = initial(simple_animal.icon) + var/icon_state = initial(simple_animal.icon_state) - var/image/final_image = image(icon, icon_state=icon_state, loc = A) + var/image/final_image = image(icon, icon_state=icon_state, loc = animal) - if(ispath(SA, /mob/living/basic/butterfly)) - final_image.color = rgb(rand(0,255), rand(0,255), rand(0,255)) + if(ispath(simple_animal, /mob/living/basic/butterfly)) + final_image.color = rgb(rand(0, 255), rand(0, 255), rand(0, 255)) // For debugging - final_image.text = initial(SA.name) + final_image.text = initial(simple_animal.name) return final_image //Interface for using DrawBox() to draw 1 pixel on a coordinate. //Returns the same icon specifed in the argument, but with the pixel drawn -/proc/DrawPixel(icon/I,colour,drawX,drawY) - if(!I) +/proc/DrawPixel(icon/icon_to_use, colour, drawX, drawY) + if(!icon_to_use) return 0 - var/Iwidth = I.Width() - var/Iheight = I.Height() + var/icon_width = icon_to_use.Width() + var/icon_height = icon_to_use.Height() - if(drawX > Iwidth || drawX <= 0) + if(drawX > icon_width || drawX <= 0) return 0 - if(drawY > Iheight || drawY <= 0) + if(drawY > icon_height || drawY <= 0) return 0 - I.DrawBox(colour,drawX, drawY) - return I + icon_to_use.DrawBox(colour, drawX, drawY) + return icon_to_use //Interface for easy drawing of one pixel on an atom. /atom/proc/DrawPixelOn(colour, drawX, drawY) - var/icon/I = new(icon) - var/icon/J = DrawPixel(I, colour, drawX, drawY) - if(J) //Only set the icon if it succeeded, the icon without the pixel is 1000x better than a black square. - icon = J - return J - return 0 + var/icon/icon_one = new(icon) + var/icon/result = DrawPixel(icon_one, colour, drawX, drawY) + if(result) //Only set the icon if it succeeded, the icon without the pixel is 1000x better than a black square. + icon = result + return result + return FALSE /// # If you already have a human and need to get its flat icon, call `get_flat_existing_human_icon()` instead. /// For creating consistent icons for human looking simple animals. @@ -1024,9 +1024,9 @@ GLOBAL_LIST_EMPTY(friendly_animal_types) body.equip_outfit_and_loadout(outfit, prefs, TRUE) //SKYRAT EDIT CHANGE var/icon/out_icon = icon('icons/effects/effects.dmi', "nothing") - for(var/D in showDirs) - var/icon/partial = getFlatIcon(body, defdir=D) - out_icon.Insert(partial,dir=D) + for(var/direction in showDirs) + var/icon/partial = getFlatIcon(body, defdir = direction) + out_icon.Insert(partial, dir = direction) humanoid_icon_cache[icon_id] = out_icon dummy_key? unset_busy_human_dummy(dummy_key) : qdel(body) @@ -1088,6 +1088,23 @@ GLOBAL_LIST_EMPTY(friendly_animal_types) /proc/generate_asset_name(file) return "asset.[md5(fcopy_rsc(file))]" +/// Gets a dummy savefile for usage in icon generation. +/// Savefiles generated from this proc will be empty. +/proc/get_dummy_savefile(from_failure = FALSE) + var/static/next_id = 0 + if(next_id++ > 9) + next_id = 0 + var/savefile_path = "tmp/dummy-save-[next_id].sav" + try + if(fexists(savefile_path)) + fdel(savefile_path) + return new /savefile(savefile_path) + catch(var/exception/error) + // if we failed to create a dummy once, try again; maybe someone slept somewhere they shouldnt have + if(from_failure) // this *is* the retry, something fucked up + CRASH("get_dummy_savefile failed to create a dummy savefile: '[error]'") + return get_dummy_savefile(from_failure = TRUE) + /** * Converts an icon to base64. Operates by putting the icon in the iconCache savefile, * exporting it as text, and then parsing the base64 from that. @@ -1096,14 +1113,11 @@ GLOBAL_LIST_EMPTY(friendly_animal_types) /proc/icon2base64(icon/icon) if (!isicon(icon)) return FALSE - var/savefile/dummySave = new("tmp/dummySave.sav") + var/savefile/dummySave = get_dummy_savefile() WRITE_FILE(dummySave["dummy"], icon) var/iconData = dummySave.ExportText("dummy") var/list/partial = splittext(iconData, "{") - . = replacetext(copytext_char(partial[2], 3, -5), "\n", "") //if cleanup fails we want to still return the correct base64 - dummySave.Unlock() - dummySave = null - fdel("tmp/dummySave.sav") //if you get the idea to try and make this more optimized, make sure to still call unlock on the savefile after every write to unlock it. + return replacetext(copytext_char(partial[2], 3, -5), "\n", "") //if cleanup fails we want to still return the correct base64 ///given a text string, returns whether it is a valid dmi icons folder path /proc/is_valid_dmi_file(icon_path) @@ -1257,39 +1271,38 @@ GLOBAL_LIST_EMPTY(friendly_animal_types) return SSassets.transport.get_asset_url(key) return "" - -/proc/icon2base64html(thing) - if (!thing) +/proc/icon2base64html(target) + if (!target) return var/static/list/bicon_cache = list() - if (isicon(thing)) - var/icon/I = thing - var/icon_base64 = icon2base64(I) + if (isicon(target)) + var/icon/target_icon = target + var/icon_base64 = icon2base64(target_icon) - if (I.Height() > world.icon_size || I.Width() > world.icon_size) + if (target_icon.Height() > world.icon_size || target_icon.Width() > world.icon_size) var/icon_md5 = md5(icon_base64) icon_base64 = bicon_cache[icon_md5] if (!icon_base64) // Doesn't exist yet, make it. - bicon_cache[icon_md5] = icon_base64 = icon2base64(I) + bicon_cache[icon_md5] = icon_base64 = icon2base64(target_icon) return "" // Either an atom or somebody fucked up and is gonna get a runtime, which I'm fine with. - var/atom/A = thing - var/key = "[istype(A.icon, /icon) ? "[REF(A.icon)]" : A.icon]:[A.icon_state]" + var/atom/target_atom = target + var/key = "[istype(target_atom.icon, /icon) ? "[REF(target_atom.icon)]" : target_atom.icon]:[target_atom.icon_state]" if (!bicon_cache[key]) // Doesn't exist, make it. - var/icon/I = icon(A.icon, A.icon_state, SOUTH, 1) - if (ishuman(thing)) // Shitty workaround for a BYOND issue. - var/icon/temp = I - I = icon() - I.Insert(temp, dir = SOUTH) + var/icon/target_icon = icon(target_atom.icon, target_atom.icon_state, SOUTH, 1) + if (ishuman(target)) // Shitty workaround for a BYOND issue. + var/icon/temp = target_icon + target_icon = icon() + target_icon.Insert(temp, dir = SOUTH) - bicon_cache[key] = icon2base64(I) + bicon_cache[key] = icon2base64(target_icon) - return "" + return "" //Costlier version of icon2html() that uses getFlatIcon() to account for overlays, underlays, etc. Use with extreme moderation, ESPECIALLY on mobs. /proc/costly_icon2html(thing, target, sourceonly = FALSE) @@ -1301,8 +1314,8 @@ GLOBAL_LIST_EMPTY(friendly_animal_types) if (isicon(thing)) return icon2html(thing, target) - var/icon/I = getFlatIcon(thing) - return icon2html(I, target, sourceonly = sourceonly) + var/icon/flat_icon = getFlatIcon(thing) + return icon2html(flat_icon, target, sourceonly = sourceonly) GLOBAL_LIST_EMPTY(transformation_animation_objects) @@ -1340,18 +1353,18 @@ GLOBAL_LIST_EMPTY(transformation_animation_objects) animate(alpha=0) GLOB.transformation_animation_objects[src] = transformation_objects - for(var/A in transformation_objects) - vis_contents += A - addtimer(CALLBACK(src, PROC_REF(_reset_transformation_animation),filter_index),time) + for(var/transformation_object in transformation_objects) + vis_contents += transformation_object + addtimer(CALLBACK(src, PROC_REF(_reset_transformation_animation), filter_index), time) /* * Resets filters and removes transformation animations helper objects from vis contents. */ /atom/movable/proc/_reset_transformation_animation(filter_index) var/list/transformation_objects = GLOB.transformation_animation_objects[src] - for(var/A in transformation_objects) - vis_contents -= A - qdel(A) + for(var/transformation_object in transformation_objects) + vis_contents -= transformation_object + qdel(transformation_object) transformation_objects.Cut() GLOB.transformation_animation_objects -= src if(filters && length(filters) >= filter_index) diff --git a/code/__HELPERS/priority_announce.dm b/code/__HELPERS/priority_announce.dm index 7f343f00da5..e759f43e675 100644 --- a/code/__HELPERS/priority_announce.dm +++ b/code/__HELPERS/priority_announce.dm @@ -1,4 +1,3 @@ -/* - SKYRAT EDIT REMOVAL - MOVED TO MODULAR modular_skyrat\modules\alerts\code\priority_announce.dm /** * Make a big red text announcement to * @@ -38,23 +37,25 @@ else if(SSstation.announcer.event_sounds[sound]) sound = SSstation.announcer.event_sounds[sound] + announcement += "

" + if(type == "Priority") - announcement += "

Priority Announcement

" + announcement += "[span_priorityannounce("Priority Announcement")]" if (title && length(title) > 0) - announcement += "

[title]

" + announcement += "[span_prioritytitle("
[title]")]" else if(type == "Captain") - announcement += "

Captain Announces

" + announcement += "[span_priorityannounce("Captain Announces")]" GLOB.news_network.submit_article(text, "Captain's Announcement", "Station Announcements", null) else if(type == "Syndicate Captain") - announcement += "

Syndicate Captain Announces

" + announcement += "[span_priorityannounce("Syndicate Captain Announces")]" else if(!sender_override) - announcement += "

[command_name()] Update

" + announcement += "[span_priorityannounce("[command_name()] Update")]" else - announcement += "

[sender_override]

" + announcement += "[span_priorityannounce("[sender_override]")]" if (title && length(title) > 0) - announcement += "

[title]

" + announcement += "[span_prioritytitle("
[title]")]" if(!sender_override) if(title == "") @@ -64,20 +65,32 @@ ///If the announcer overrides alert messages, use that message. if(SSstation.announcer.custom_alert_message && !has_important_message) - announcement += SSstation.announcer.custom_alert_message + announcement += "[span_priorityalert("
[SSstation.announcer.custom_alert_message]
")]" else - announcement += "
[span_alert(text)]
" - announcement += "
" + announcement += "[span_priorityalert("
[text]
")]" + + announcement += "

" if(!players) players = GLOB.player_list + // SKYRAT EDIT CHANGE BEGIN - ANNOUNCEMENTS + /* Original + if(target.client.prefs.read_preference(/datum/preference/toggle/sound_announcements)) + SEND_SOUND(target, sound_to_play) + */ + if(!sound) + sound = SSstation.announcer.get_rand_alert_sound() + else if(SSstation.announcer.event_sounds[sound]) + var/list/announcer_key = SSstation.announcer.event_sounds[sound] + sound = pick(announcer_key) var/sound_to_play = sound(sound) for(var/mob/target in players) if(!isnewplayer(target) && target.can_hear()) to_chat(target, announcement) - if(target.client.prefs.read_preference(/datum/preference/toggle/sound_announcements)) - SEND_SOUND(target, sound_to_play) + + alert_sound_to_playing(sound_to_play, players = players) + // SKYRAT EDIT CHANGE END - ANNOUNCEMENTS /proc/print_command_report(text = "", title = null, announce=TRUE) if(!title) @@ -86,11 +99,11 @@ if(announce) priority_announce("A report has been downloaded and printed out at all communications consoles.", "Incoming Classified Message", SSstation.announcer.get_rand_report_sound(), has_important_message = TRUE) - var/datum/comm_message/M = new - M.title = title - M.content = text + var/datum/comm_message/message = new + message.title = title + message.content = text - SScommunications.send_message(M) + SScommunications.send_message(message) /** * Sends a minor annoucement to players. @@ -122,8 +135,20 @@ if(!target.can_hear()) continue - to_chat(target, "[span_minorannounce("[title]
[message]")]
") + to_chat(target, "
[span_minorannounce(title)]
") + to_chat(target, "[span_minoralert(message)]


") + // SKYRAT EDIT CHANGE START - ANNOUNCEMENTS + /* Original if(should_play_sound && target.client?.prefs.read_preference(/datum/preference/toggle/sound_announcements)) var/sound_to_play = sound_override || (alert ? 'sound/misc/notice1.ogg' : 'sound/misc/notice2.ogg') SEND_SOUND(target, sound(sound_to_play)) -*/ // SKYRAT EDIT REMOVAL END + */ + if(sound_override) + if(SSstation.announcer.event_sounds[sound_override]) + var/list/announcement_key = SSstation.announcer.event_sounds[sound_override] + sound_override = pick(announcement_key) + + var/sound_to_play = sound_override || (alert ? 'modular_skyrat/modules/alerts/sound/alerts/alert1.ogg' : 'sound/misc/notice2.ogg') + alert_sound_to_playing(sound_to_play, players = players) + // SKYRAT EDIT CHANGE END - ANNOUNCEMENTS + diff --git a/code/_globalvars/lists/mobs.dm b/code/_globalvars/lists/mobs.dm index 5ee1f4e6439..135fb00dea1 100644 --- a/code/_globalvars/lists/mobs.dm +++ b/code/_globalvars/lists/mobs.dm @@ -12,6 +12,37 @@ GLOBAL_LIST_INIT(dangerous_turfs, typecacheof(list( /turf/open/space, /turf/open/openspace))) +/// List of types of abstract mob which shouldn't usually exist in the world on its own if we're spawning random mobs +GLOBAL_LIST_INIT(abstract_mob_types, list( + /mob/living/basic/blob_minion, + /mob/living/basic/construct, + /mob/living/basic/heretic_summon, + /mob/living/basic/mining, + /mob/living/basic/pet, + /mob/living/basic, + /mob/living/basic/spider, + /mob/living/carbon/alien/adult, + /mob/living/carbon/alien, + /mob/living/carbon/human/consistent, + /mob/living/carbon/human/dummy/consistent, + /mob/living/carbon/human/dummy, + /mob/living/carbon/human/species, + /mob/living/carbon, + /mob/living/silicon, + /mob/living/simple_animal/bot, + /mob/living/simple_animal/hostile/asteroid/elite, + /mob/living/simple_animal/hostile/asteroid, + /mob/living/simple_animal/hostile/construct, + /mob/living/simple_animal/hostile/guardian, + /mob/living/simple_animal/hostile/megafauna, + /mob/living/simple_animal/hostile/mimic, // Cannot exist if spawned without being passed an item reference + /mob/living/simple_animal/hostile/retaliate, + /mob/living/simple_animal/hostile, + /mob/living/simple_animal/pet, + /mob/living/simple_animal/soulscythe, // As mimic, can't exist if spawned outside an item + /mob/living/simple_animal, +)) + //Since it didn't really belong in any other category, I'm putting this here //This is for procs to replace all the goddamn 'in world's that are chilling around the code diff --git a/code/_globalvars/traits.dm b/code/_globalvars/traits.dm index da03288a0ca..8fd711279a5 100644 --- a/code/_globalvars/traits.dm +++ b/code/_globalvars/traits.dm @@ -216,6 +216,7 @@ GLOBAL_LIST_INIT(traits_by_type, list( "TRAIT_XRAY_HEARING" = TRAIT_XRAY_HEARING, "TRAIT_TENTACLE_IMMUNE" = TRAIT_TENTACLE_IMMUNE, "TRAIT_OVERWATCH_IMMUNE" = TRAIT_OVERWATCH_IMMUNE, + "TRAIT_NO_TRANSFORM" = TRAIT_NO_TRANSFORM, ), /obj/item/bodypart = list( "TRAIT_PARALYSIS" = TRAIT_PARALYSIS, diff --git a/code/_onclick/click.dm b/code/_onclick/click.dm index 4b24b20c846..667611f1075 100644 --- a/code/_onclick/click.dm +++ b/code/_onclick/click.dm @@ -277,7 +277,10 @@ /** - * Translates into [atom/proc/attack_hand], etc. + * UnarmedAttack: The higest level of mob click chain discounting click itself. + * + * This handles, just "clicking on something" without an item. It translates + * into [atom/proc/attack_hand], [atom/proc/attack_animal] etc. * * Note: proximity_flag here is used to distinguish between normal usage (flag=1), * and usage when clicking on things telekinetically (flag=0). This proc will diff --git a/code/_onclick/other_mobs.dm b/code/_onclick/other_mobs.dm index aeb42361c05..ce281bb4ecf 100644 --- a/code/_onclick/other_mobs.dm +++ b/code/_onclick/other_mobs.dm @@ -9,33 +9,66 @@ else if (secondary_result != SECONDARY_ATTACK_CALL_NORMAL) CRASH("resolve_right_click_attack (probably attack_hand_secondary) did not return a SECONDARY_ATTACK_* define.") -/* - Humans: - Adds an exception for gloves, to allow special glove types like the ninja ones. +/** + * Checks if this mob is in a valid state to punch someone. + */ +/mob/living/proc/can_unarmed_attack() + return !HAS_TRAIT(src, TRAIT_HANDS_BLOCKED) + +/mob/living/carbon/can_unarmed_attack() + . = ..() + if(!.) + return FALSE - Otherwise pretty standard. -*/ -/mob/living/carbon/human/UnarmedAttack(atom/A, proximity_flag, list/modifiers) - if(HAS_TRAIT(src, TRAIT_HANDS_BLOCKED)) - if(src == A) - check_self_for_injuries() - return if(!has_active_hand()) //can't attack without a hand. var/obj/item/bodypart/check_arm = get_active_hand() if(check_arm?.bodypart_disabled) to_chat(src, span_warning("Your [check_arm.name] is in no condition to be used.")) - return + return FALSE to_chat(src, span_notice("You look at your arm and sigh.")) - return + return FALSE - //This signal is needed to prevent gloves of the north star + hulk. - if(SEND_SIGNAL(src, COMSIG_HUMAN_EARLY_UNARMED_ATTACK, A, proximity_flag, modifiers) & COMPONENT_CANCEL_ATTACK_CHAIN) - return - SEND_SIGNAL(src, COMSIG_HUMAN_MELEE_UNARMED_ATTACK, A, proximity_flag, modifiers) + return TRUE + +/mob/living/UnarmedAttack(atom/attack_target, proximity_flag, list/modifiers) + // The sole reason for this signal needing to exist is making FotNS incompatible with Hulk. + // Note that it is send before [proc/can_unarmed_attack] is called, keep this in mind. + var/sigreturn = SEND_SIGNAL(src, COMSIG_LIVING_EARLY_UNARMED_ATTACK, attack_target, modifiers) + if(sigreturn & COMPONENT_CANCEL_ATTACK_CHAIN) + return TRUE + if(sigreturn & COMPONENT_SKIP_ATTACK) + return FALSE - if(!right_click_attack_chain(A, modifiers) && !dna?.species?.spec_unarmedattack(src, A, modifiers)) //Because species like monkeys dont use attack hand - A.attack_hand(src, modifiers) + if(!can_unarmed_attack(attack_target)) + return FALSE + + sigreturn = SEND_SIGNAL(src, COMSIG_LIVING_UNARMED_ATTACK, attack_target, proximity_flag, modifiers) + if(sigreturn & COMPONENT_CANCEL_ATTACK_CHAIN) + return TRUE + if(sigreturn & COMPONENT_SKIP_ATTACK) + return FALSE + + if(!right_click_attack_chain(attack_target, modifiers)) + resolve_unarmed_attack(attack_target, modifiers) + return TRUE + +/mob/living/carbon/human/UnarmedAttack(atom/attack_target, proximity_flag, list/modifiers) + // Humans can always check themself regardless of having their hands blocked or w/e + if(src == attack_target) + check_self_for_injuries() + return TRUE + + return ..() + +/mob/living/carbon/resolve_unarmed_attack(atom/attack_target, list/modifiers) + return attack_target.attack_paw(src, modifiers) + +/mob/living/carbon/human/resolve_unarmed_attack(atom/attack_target, list/modifiers) + if(!ISADVANCEDTOOLUSER(src)) + return ..() + + return attack_target.attack_hand(src, modifiers) /mob/living/carbon/human/resolve_right_click_attack(atom/target, list/modifiers) return target.attack_hand_secondary(src, modifiers) @@ -119,17 +152,6 @@ Animals & All Unspecified */ -// If the UnarmedAttack chain is blocked -#define LIVING_UNARMED_ATTACK_BLOCKED(target_atom) (HAS_TRAIT(src, TRAIT_HANDS_BLOCKED) \ - || SEND_SIGNAL(src, COMSIG_LIVING_UNARMED_ATTACK, target_atom, proximity_flag, modifiers) & COMPONENT_CANCEL_ATTACK_CHAIN) - -/mob/living/UnarmedAttack(atom/attack_target, proximity_flag, list/modifiers) - if(LIVING_UNARMED_ATTACK_BLOCKED(attack_target)) - return FALSE - if(!right_click_attack_chain(attack_target, modifiers)) - resolve_unarmed_attack(attack_target, modifiers) - return TRUE - /** * Called when the unarmed attack hasn't been stopped by the LIVING_UNARMED_ATTACK_BLOCKED macro or the right_click_attack_chain proc. * This will call an attack proc that can vary from mob type to mob type on the target. @@ -295,8 +317,6 @@ GiveTarget(attack_target) INVOKE_ASYNC(src, PROC_REF(AttackingTarget), attack_target) -#undef LIVING_UNARMED_ATTACK_BLOCKED - /* New Players: Have no reason to click on anything at all. diff --git a/code/controllers/subsystem/events.dm b/code/controllers/subsystem/events.dm index c5223ca6963..98f847e4be6 100644 --- a/code/controllers/subsystem/events.dm +++ b/code/controllers/subsystem/events.dm @@ -2,15 +2,19 @@ SUBSYSTEM_DEF(events) name = "Events" init_order = INIT_ORDER_EVENTS runlevels = RUNLEVEL_GAME - - var/list/control = list() //list of all datum/round_event_control. Used for selecting events based on weight and occurrences. - var/list/running = list() //list of all existing /datum/round_event + ///list of all datum/round_event_control. Used for selecting events based on weight and occurrences. + var/list/control = list() + ///list of all existing /datum/round_event currently being run. + var/list/running = list() + ///cache of currently running events, for lag checking. var/list/currentrun = list() - - var/scheduled = 0 //The next world.time that a naturally occuring random event can be selected. - var/frequency_lower = 1800 //3 minutes lower bound. - var/frequency_upper = 6000 //10 minutes upper bound. Basically an event will happen every 3 to 10 minutes. - + ///The next world.time that a naturally occuring random event can be selected. + var/scheduled = 0 + ///The lower bound for how soon another random event can be scheduled. + var/frequency_lower = 2.5 MINUTES + ///The upper bound for how soon another random event can be scheduled. + var/frequency_upper = 7 MINUTES + ///Will wizard events be included in the event pool? var/wizardmode = FALSE var/list/previously_run = list() //SKYRAT EDIT ADDITION @@ -61,50 +65,45 @@ SUBSYSTEM_DEF(events) if(!CONFIG_GET(flag/allow_random_events)) return - var/players_amt = get_active_player_count(alive_check = 1, afk_check = 1, human_check = 1) + var/players_amt = get_active_player_count(alive_check = TRUE, afk_check = TRUE, human_check = TRUE) // Only alive, non-AFK human players count towards this. - var/sum_of_weights = 0 - for(var/datum/round_event_control/E in control) - if(!E.can_spawn_event(players_amt)) + var/list/event_roster = list() + + for(var/datum/round_event_control/event_to_check in control) + if(!event_to_check.can_spawn_event(players_amt)) continue //SKYRAT EDIT ADDITION - if(threat_override && !E.alert_observers) + if(threat_override && !event_to_check.alert_observers) continue //SKYRAT EDIT END - if(E.weight < 0) //for round-start events etc. - var/res = TriggerEvent(E) + if(event_to_check.weight < 0) //for round-start events etc. + var/res = TriggerEvent(event_to_check) if(res == EVENT_INTERRUPTED) continue //like it never happened if(res == EVENT_CANT_RUN) return - sum_of_weights += E.weight - - sum_of_weights = rand(0,sum_of_weights) //reusing this variable. It now represents the 'weight' we want to select - - for(var/datum/round_event_control/E in control) - if(!E.can_spawn_event(players_amt)) - continue - sum_of_weights -= E.weight + else + event_roster[event_to_check] = event_to_check.weight - if(sum_of_weights <= 0) //we've hit our goal - if(TriggerEvent(E)) - return + var/datum/round_event_control/event_to_run = pick_weight(event_roster) + TriggerEvent(event_to_run) -/datum/controller/subsystem/events/proc/TriggerEvent(datum/round_event_control/E) - . = E.preRunEvent() +///Does the last pre-flight checks for the passed event, and runs it if the event is ready. +/datum/controller/subsystem/events/proc/TriggerEvent(datum/round_event_control/event_to_trigger) + . = event_to_trigger.preRunEvent() if(. == EVENT_CANT_RUN)//we couldn't run this event for some reason, set its max_occurrences to 0 - E.max_occurrences = 0 + event_to_trigger.max_occurrences = 0 else if(. == EVENT_READY) - E.run_event(random = TRUE) - + event_to_trigger.run_event(random = TRUE) +///Toggles whether or not wizard events will be in the event pool, and sends a notification to the admins. /datum/controller/subsystem/events/proc/toggleWizardmode() wizardmode = !wizardmode message_admins("Summon Events has been [wizardmode ? "enabled, events will occur every [SSevents.frequency_lower / 600] to [SSevents.frequency_upper / 600] minutes" : "disabled"]!") log_game("Summon Events was [wizardmode ? "enabled" : "disabled"]!") - +///Sets the event frequency bounds back to their initial value. /datum/controller/subsystem/events/proc/resetFrequency() frequency_lower = initial(frequency_lower) frequency_upper = initial(frequency_upper) diff --git a/code/controllers/subsystem/ticker.dm b/code/controllers/subsystem/ticker.dm index 1aaf01ee85f..97b2c85b2aa 100644 --- a/code/controllers/subsystem/ticker.dm +++ b/code/controllers/subsystem/ticker.dm @@ -300,7 +300,7 @@ SUBSYSTEM_DEF(ticker) to_chat(world, span_notice("and...")) for(var/holidayname in GLOB.holidays) var/datum/holiday/holiday = GLOB.holidays[holidayname] - to_chat(world, "

[holiday.greet()]

") + to_chat(world, span_info(holiday.greet())) PostSetup() diff --git a/code/datums/actions/mobs/fire_breath.dm b/code/datums/actions/mobs/fire_breath.dm index 254a6081425..45b6538c018 100644 --- a/code/datums/actions/mobs/fire_breath.dm +++ b/code/datums/actions/mobs/fire_breath.dm @@ -2,63 +2,121 @@ name = "Fire Breath" button_icon = 'icons/effects/magic.dmi' button_icon_state = "fireball" - desc = "Allows you to shoot fire towards a target." + desc = "Breathe a line of flames towards the target." cooldown_time = 3 SECONDS /// The range of the fire var/fire_range = 15 /// The sound played when you use this ability var/fire_sound = 'sound/magic/fireball.ogg' - /// If the fire should be icey fire - var/ice_breath = FALSE + /// Time to wait between spawning each fire turf + var/fire_delay = 1.5 DECISECONDS + /// How hot is our fire + var/fire_temperature = DRAKE_FIRE_TEMP + /// 'How much' fire do we expose the turf to? + var/fire_volume = DRAKE_FIRE_EXPOSURE + /// How much damage do you take when engulfed? + var/fire_damage = 20 + /// How much damage to mechs take when engulfed? + var/mech_damage = 45 /datum/action/cooldown/mob_cooldown/fire_breath/Activate(atom/target_atom) - StartCooldown(360 SECONDS, 360 SECONDS) attack_sequence(target_atom) StartCooldown() return TRUE +/// Apply our specific fire breathing shape, in proc form so we can override it in subtypes /datum/action/cooldown/mob_cooldown/fire_breath/proc/attack_sequence(atom/target) playsound(owner.loc, fire_sound, 200, TRUE) - fire_line(target, 0) + fire_line(target) +/// Breathe fire in a line towards the target, optionally rotated at an offset from the target /datum/action/cooldown/mob_cooldown/fire_breath/proc/fire_line(atom/target, offset) - SLEEP_CHECK_DEATH(0, owner) - var/list/turfs = line_target(offset, fire_range, target) - // This proc sleeps - INVOKE_ASYNC(GLOBAL_PROC, GLOBAL_PROC_REF(dragon_fire_line), owner, /* burn_turfs = */ turfs, /* frozen = */ ice_breath) + if (isnull(target)) + return + var/turf/target_turf = get_ranged_target_turf_direct(owner, target, fire_range, offset) + var/list/turfs = get_line(owner, target_turf) - get_turf(owner) + INVOKE_ASYNC(src, PROC_REF(progressive_fire_line), turfs) -/datum/action/cooldown/mob_cooldown/fire_breath/proc/line_target(offset, range, atom/target) - if(!target) +/// Creates fire with a delay on the list of targetted turfs +/datum/action/cooldown/mob_cooldown/fire_breath/proc/progressive_fire_line(list/burn_turfs) + if (QDELETED(owner) || owner.stat == DEAD) return - var/turf/T = get_ranged_target_turf_direct(owner, target, range, offset) - return (get_line(owner, T) - get_turf(owner)) + // Guys we have already hit, no double dipping + var/list/hit_list = list(owner) // also don't burn ourselves + for(var/turf/target_turf in burn_turfs) + if (target_turf.is_blocked_turf(exclude_mobs = TRUE)) + return + burn_turf(target_turf, hit_list, owner) + sleep(fire_delay) + +/// Finally spawn the actual fire, spawns the fire hotspot in case you want to recolour it or something +/datum/action/cooldown/mob_cooldown/fire_breath/proc/burn_turf(turf/fire_turf, list/hit_list, mob/living/source) + var/obj/effect/hotspot/fire_hotspot = new /obj/effect/hotspot(fire_turf) + fire_turf.hotspot_expose(fire_temperature, fire_volume, TRUE) + + for(var/mob/living/barbecued in fire_turf.contents) + if(barbecued in hit_list) + continue + hit_list |= barbecued + on_burn_mob(barbecued, source) + + for(var/obj/vehicle/sealed/mecha/robotron in fire_turf.contents) + if(robotron in hit_list) + continue + hit_list |= robotron + robotron.take_damage(mech_damage, BURN, FIRE) + return fire_hotspot + +/// Do something unpleasant to someone we set on fire +/datum/action/cooldown/mob_cooldown/fire_breath/proc/on_burn_mob(mob/living/barbecued, mob/living/source) + to_chat(barbecued, span_userdanger("You are burned by [source]'s fire breath!")) + barbecued.adjustFireLoss(fire_damage) + +/// Shoot three lines of fire in a sort of fork pattern approximating a cone /datum/action/cooldown/mob_cooldown/fire_breath/cone name = "Fire Cone" - desc = "Allows you to shoot fire towards a target with surrounding lines of fire." + desc = "Breathe several lines of fire directed at a target." /// The angles relative to the target that shoot lines of fire var/list/angles = list(-40, 0, 40) /datum/action/cooldown/mob_cooldown/fire_breath/cone/attack_sequence(atom/target) playsound(owner.loc, fire_sound, 200, TRUE) for(var/offset in angles) - INVOKE_ASYNC(src, PROC_REF(fire_line), target, offset) + fire_line(target, offset) +/// Shoot fire in a whole bunch of directions /datum/action/cooldown/mob_cooldown/fire_breath/mass_fire name = "Mass Fire" button_icon = 'icons/effects/fire.dmi' button_icon_state = "1" - desc = "Allows you to shoot fire in all directions." + desc = "Breathe flames in all directions." cooldown_time = 3 SECONDS + click_to_activate = FALSE + /// How many fire lines do we produce to turn a full circle? + var/sectors = 12 + /// How long do we wait between each spin? + var/breath_delay = 2.5 SECONDS + /// How many full circles do we perform? + var/total_spins = 3 + +/datum/action/cooldown/mob_cooldown/fire_breath/mass_fire/Activate(atom/target_atom) + target_atom = get_step(owner, owner.dir) // Just shoot it forwards, we don't need to click on someone for this one + return ..() /datum/action/cooldown/mob_cooldown/fire_breath/mass_fire/attack_sequence(atom/target) - shoot_mass_fire(target, 12, 2.5 SECONDS, 3) + var/queued_spins = 0 + for (var/i in 1 to total_spins) + var/delay = queued_spins * breath_delay + queued_spins++ + addtimer(CALLBACK(src, PROC_REF(fire_spin), target, queued_spins), delay) -/datum/action/cooldown/mob_cooldown/fire_breath/mass_fire/proc/shoot_mass_fire(atom/target, spiral_count, delay_time, times) - SLEEP_CHECK_DEATH(0, owner) - for(var/i = 1 to times) - playsound(owner.loc, fire_sound, 200, TRUE) - var/increment = 360 / spiral_count - for(var/j = 1 to spiral_count) - INVOKE_ASYNC(src, PROC_REF(fire_line), target, j * increment + i * increment / 2) - SLEEP_CHECK_DEATH(delay_time, owner) +/// Breathe fire in a circle, with a slight angle offset based on which of our several circles it is +/datum/action/cooldown/mob_cooldown/fire_breath/mass_fire/proc/fire_spin(target, spin_count) + if (QDELETED(owner) || owner.stat == DEAD) + return // Too dead to spin + playsound(owner.loc, fire_sound, 200, TRUE) + var/angle_increment = 360 / sectors + var/additional_offset = spin_count * angle_increment / 2 + for (var/i in 1 to sectors) + fire_line(target, (angle_increment * i) + (additional_offset)) diff --git a/code/datums/actions/mobs/mobcooldown.dm b/code/datums/actions/mobs/mobcooldown.dm index 17561f2f45a..a495859494f 100644 --- a/code/datums/actions/mobs/mobcooldown.dm +++ b/code/datums/actions/mobs/mobcooldown.dm @@ -3,7 +3,7 @@ button_icon = 'icons/mob/actions/actions_items.dmi' button_icon_state = "sniper_zoom" desc = "Click this ability to attack." - check_flags = AB_CHECK_CONSCIOUS + check_flags = AB_CHECK_CONSCIOUS | AB_CHECK_INCAPACITATED cooldown_time = 5 SECONDS text_cooldown = TRUE click_to_activate = TRUE diff --git a/code/datums/actions/mobs/sneak.dm b/code/datums/actions/mobs/sneak.dm index 3fed4f4d500..738bb7b70cf 100644 --- a/code/datums/actions/mobs/sneak.dm +++ b/code/datums/actions/mobs/sneak.dm @@ -5,7 +5,6 @@ button_icon_state = "sniper_zoom" background_icon_state = "bg_alien" overlay_icon_state = "bg_alien_border" - check_flags = AB_CHECK_CONSCIOUS | AB_CHECK_INCAPACITATED | AB_CHECK_INCAPACITATED cooldown_time = 0.5 SECONDS melee_cooldown_time = 0 SECONDS click_to_activate = FALSE diff --git a/code/datums/ai/babies/babies_behaviors.dm b/code/datums/ai/babies/babies_behaviors.dm index 716922cc7b2..553b192a180 100644 --- a/code/datums/ai/babies/babies_behaviors.dm +++ b/code/datums/ai/babies/babies_behaviors.dm @@ -32,7 +32,7 @@ partner = other //shyness check. we're not shy in front of things that share a faction with us. - else if(isliving(other) && !pawn_mob.faction_check_mob(other)) + else if(isliving(other) && !pawn_mob.faction_check_atom(other)) finish_action(controller, FALSE) return diff --git a/code/datums/ai/basic_mobs/targetting_datums/basic_targetting_datum.dm b/code/datums/ai/basic_mobs/targetting_datums/basic_targetting_datum.dm index bc4a554bc02..1d6fde335cb 100644 --- a/code/datums/ai/basic_mobs/targetting_datums/basic_targetting_datum.dm +++ b/code/datums/ai/basic_mobs/targetting_datums/basic_targetting_datum.dm @@ -81,7 +81,7 @@ /datum/targetting_datum/basic/proc/faction_check(datum/ai_controller/controller, mob/living/living_mob, mob/living/the_target) if (controller.blackboard[BB_ALWAYS_IGNORE_FACTION] || controller.blackboard[BB_TEMPORARILY_IGNORE_FACTION]) return FALSE - return living_mob.faction_check_mob(the_target, exact_match = check_factions_exactly) + return living_mob.faction_check_atom(the_target, exact_match = check_factions_exactly) /// Subtype more forgiving for items. /// Careful, this can go wrong and keep a mob hyper-focused on an item it can't lose aggro on diff --git a/code/datums/ai/generic/find_and_set.dm b/code/datums/ai/generic/find_and_set.dm index dc941ec33fa..43337674969 100644 --- a/code/datums/ai/generic/find_and_set.dm +++ b/code/datums/ai/generic/find_and_set.dm @@ -129,7 +129,7 @@ continue if (living_pawn.see_invisible < dead_pal.invisibility) continue - if (!living_pawn.faction_check_mob(dead_pal)) + if (!living_pawn.faction_check_atom(dead_pal)) continue nearby_bodies += dead_pal diff --git a/code/datums/components/butchering.dm b/code/datums/components/butchering.dm index 689de30db37..183203ed709 100644 --- a/code/datums/components/butchering.dm +++ b/code/datums/components/butchering.dm @@ -257,16 +257,16 @@ if(!(slot & source.slot_flags)) return butchering_enabled = TRUE - RegisterSignal(user, COMSIG_HUMAN_EARLY_UNARMED_ATTACK, PROC_REF(butcher_target)) + RegisterSignal(user, COMSIG_LIVING_UNARMED_ATTACK, PROC_REF(butcher_target)) ///Same as disable_butchering but for worn items /datum/component/butchering/wearable/proc/worn_disable_butchering(obj/item/source, mob/user) SIGNAL_HANDLER butchering_enabled = FALSE - UnregisterSignal(user, COMSIG_HUMAN_EARLY_UNARMED_ATTACK) + UnregisterSignal(user, COMSIG_LIVING_UNARMED_ATTACK) /datum/component/butchering/wearable/proc/butcher_target(mob/user, atom/target, proximity) SIGNAL_HANDLER if(!isliving(target)) - return - onItemAttack(parent, target, user) + return NONE + return onItemAttack(parent, target, user) diff --git a/code/datums/components/fantasy/suffixes.dm b/code/datums/components/fantasy/suffixes.dm index c8809efae49..69d9d0a7ebb 100644 --- a/code/datums/components/fantasy/suffixes.dm +++ b/code/datums/components/fantasy/suffixes.dm @@ -103,30 +103,35 @@ . = ..() // This is set up to be easy to add to these lists as I expect it will need modifications var/static/list/possible_mobtypes - if(!possible_mobtypes) - // The base list of allowed mob/species types - possible_mobtypes = zebra_typecacheof(list( - /mob/living/simple_animal = TRUE, - /mob/living/carbon = TRUE, - /datum/species = TRUE, - // Some types to remove them and their subtypes - /mob/living/carbon/human/species = FALSE, - /mob/living/simple_animal/hostile/asteroid/elite = FALSE, - /mob/living/simple_animal/hostile/megafauna = FALSE, - )) - // Some particular types to disallow if they're too broad/abstract - // Not in the above typecache generator because it includes subtypes and this doesn't. - possible_mobtypes -= list( - /mob/living/simple_animal/hostile, + if(isnull(possible_mobtypes)) + possible_mobtypes = list() + var/list/mob_subtype_whitelist = list( + /mob/living/basic, + /mob/living/carbon, + /mob/living/simple_animal, ) + for(var/type in mob_subtype_whitelist) + possible_mobtypes += subtypesof(type) - var/mob/picked_mobtype = pick(possible_mobtypes) - // This works even with the species picks since we're only accessing the name + var/list/mob_subtype_blacklist = list( + /mob/living/simple_animal/hostile/asteroid/elite, + /mob/living/simple_animal/hostile/megafauna, + ) + for(var/type in mob_subtype_blacklist) + possible_mobtypes -= subtypesof(type) + + possible_mobtypes -= GLOB.abstract_mob_types + var/mob/picked_mobtype = pick(possible_mobtypes) var/obj/item/master = comp.parent - var/max_mobs = max(CEILING(comp.quality/2, 1), 1) - var/spawn_delay = 300 - 30 * comp.quality - comp.appliedComponents += master.AddComponent(/datum/component/summoning, list(picked_mobtype), 100, max_mobs, spawn_delay) + var/max_mobs = max(CEILING(comp.quality / 2, 1), 1) + var/spawn_delay = 30 SECONDS - (3 SECONDS * comp.quality) + comp.appliedComponents += master.AddComponent(\ + /datum/component/summoning,\ + mob_types = list(picked_mobtype),\ + max_mobs = max_mobs,\ + spawn_delay = spawn_delay,\ + ) return "[newName] of [initial(picked_mobtype.name)] summoning" /datum/fantasy_affix/shrapnel diff --git a/code/datums/components/focused_attacker.dm b/code/datums/components/focused_attacker.dm index eda6bd17979..8635973f263 100644 --- a/code/datums/components/focused_attacker.dm +++ b/code/datums/components/focused_attacker.dm @@ -24,12 +24,12 @@ /datum/component/focused_attacker/RegisterWithParent() if (isliving(parent)) - RegisterSignals(parent, list(COMSIG_LIVING_UNARMED_ATTACK, COMSIG_HUMAN_MELEE_UNARMED_ATTACK), PROC_REF(pre_mob_attack)) + RegisterSignal(parent, COMSIG_LIVING_UNARMED_ATTACK, PROC_REF(pre_mob_attack)) else RegisterSignal(parent, COMSIG_ITEM_PRE_ATTACK, PROC_REF(pre_item_attack)) /datum/component/focused_attacker/UnregisterFromParent() - UnregisterSignal(parent, list(COMSIG_LIVING_UNARMED_ATTACK, COMSIG_HUMAN_MELEE_UNARMED_ATTACK, COMSIG_ITEM_PRE_ATTACK)) + UnregisterSignal(parent, list(COMSIG_LIVING_UNARMED_ATTACK, COMSIG_ITEM_PRE_ATTACK)) /// Before a mob attacks, try increasing its attack power /datum/component/focused_attacker/proc/pre_mob_attack(mob/living/attacker, atom/target) diff --git a/code/datums/components/mob_chain.dm b/code/datums/components/mob_chain.dm index 8312d9d5504..2ff7c4f1967 100644 --- a/code/datums/components/mob_chain.dm +++ b/code/datums/components/mob_chain.dm @@ -43,7 +43,7 @@ RegisterSignal(parent, COMSIG_QDELETING, PROC_REF(on_deletion)) RegisterSignal(parent, COMSIG_MOVABLE_MOVED, PROC_REF(on_moved)) RegisterSignal(parent, COMSIG_ATOM_CAN_BE_PULLED, PROC_REF(on_pulled)) - RegisterSignals(parent, list(COMSIG_LIVING_UNARMED_ATTACK, COMSIG_HUMAN_EARLY_UNARMED_ATTACK, COMSIG_MOB_ATTACK_RANGED), PROC_REF(on_attack)) + RegisterSignals(parent, list(COMSIG_LIVING_UNARMED_ATTACK, COMSIG_MOB_ATTACK_RANGED), PROC_REF(on_attack)) RegisterSignal(parent, COMSIG_MOVABLE_UPDATE_GLIDE_SIZE, PROC_REF(on_glide_size_changed)) if (vary_icon_state) RegisterSignal(parent, COMSIG_ATOM_UPDATE_ICON_STATE, PROC_REF(on_update_icon_state)) @@ -61,7 +61,6 @@ COMSIG_ATOM_CAN_BE_PULLED, COMSIG_ATOM_UPDATE_ICON_STATE, COMSIG_CARBON_LIMB_DAMAGED, - COMSIG_HUMAN_EARLY_UNARMED_ATTACK, COMSIG_LIVING_ADJUST_BRUTE_DAMAGE, COMSIG_LIVING_ADJUST_BURN_DAMAGE, COMSIG_LIVING_ADJUST_CLONE_DAMAGE, diff --git a/code/datums/components/plumbing/_plumbing.dm b/code/datums/components/plumbing/_plumbing.dm index af27b4bbb46..15c9f24833b 100644 --- a/code/datums/components/plumbing/_plumbing.dm +++ b/code/datums/components/plumbing/_plumbing.dm @@ -114,8 +114,9 @@ //take an equal amount from each supplier var/currentRequest + var/target_volume = reagents.total_volume + amount for(var/datum/component/plumbing/give as anything in valid_suppliers) - currentRequest = amount / suppliersLeft + currentRequest = (target_volume - reagents.total_volume) / suppliersLeft give.transfer_to(src, currentRequest, reagent, net) suppliersLeft-- @@ -131,6 +132,8 @@ else if(reagents.total_volume) //take whatever return TRUE + return FALSE + ///this is where the reagent is actually transferred and is thus the finish point of our process() /datum/component/plumbing/proc/transfer_to(datum/component/plumbing/target, amount, reagent, datum/ductnet/net) if(!reagents || !target || !target.reagents) diff --git a/code/datums/components/plumbing/reaction_chamber.dm b/code/datums/components/plumbing/reaction_chamber.dm index f728ce315e6..42b7abeb2e8 100644 --- a/code/datums/components/plumbing/reaction_chamber.dm +++ b/code/datums/components/plumbing/reaction_chamber.dm @@ -10,7 +10,7 @@ /datum/component/plumbing/reaction_chamber/can_give(amount, reagent, datum/ductnet/net) . = ..() var/obj/machinery/plumbing/reaction_chamber/reaction_chamber = parent - if(!. || !reaction_chamber.emptying || reagents.is_reacting == TRUE) + if(!. || !reaction_chamber.emptying || reagents.is_reacting) return FALSE /datum/component/plumbing/reaction_chamber/send_request(dir) @@ -30,7 +30,7 @@ //compute how much more is needed and round it diff = chamber.required_reagents[required_reagent] - present_amount - if(diff > CHEMICAL_QUANTISATION_LEVEL) + if(diff >= CHEMICAL_QUANTISATION_LEVEL * 10) //should be safe even after rounding process_request(min(diff, MACHINE_REAGENT_TRANSFER), required_reagent, dir) return diff --git a/code/datums/components/pry_open_door.dm b/code/datums/components/pry_open_door.dm deleted file mode 100644 index 17e445d25ca..00000000000 --- a/code/datums/components/pry_open_door.dm +++ /dev/null @@ -1,52 +0,0 @@ -/** - * Attached to a basic mob. - * Causes attacks on doors to attempt to open them. - */ -/datum/component/pry_open_door - /// Odds the attack opens the door - var/open_chance - /// Time it takes to open a door with force - var/force_wait - -/datum/component/pry_open_door/Initialize(open_chance = 100, force_wait = 10 SECONDS) - . = ..() - - if(!isbasicmob(parent)) - return COMPONENT_INCOMPATIBLE - src.open_chance = open_chance - src.force_wait = force_wait - -/datum/component/pry_open_door/RegisterWithParent() - RegisterSignal(parent, COMSIG_HOSTILE_POST_ATTACKINGTARGET, PROC_REF(hostile_attackingtarget)) - -/datum/component/pry_open_door/UnregisterFromParent() - UnregisterSignal(parent, COMSIG_HOSTILE_POST_ATTACKINGTARGET) - -/datum/component/pry_open_door/proc/hostile_attackingtarget(mob/living/basic/attacker, atom/target, success) - SIGNAL_HANDLER - - if(!success) - return - if(istype(target, /obj/machinery/door/airlock) && prob(open_chance)) - var/obj/machinery/door/airlock/airlock_target = target - INVOKE_ASYNC(src, PROC_REF(open_door), attacker, airlock_target) - -/datum/component/pry_open_door/proc/open_door(mob/living/basic/attacker, obj/machinery/door/airlock/airlock_target) - if(airlock_target.locked) - to_chat(attacker, span_warning("The airlock's bolts prevent it from being forced!")) - return - else if(!airlock_target.allowed(attacker) && airlock_target.hasPower()) - attacker.visible_message(span_warning("We start forcing the [airlock_target] open."), \ - span_hear("You hear a metal screeching sound.")) - playsound(airlock_target, 'sound/machines/airlock_alien_prying.ogg', 100, TRUE) - if(!do_after(attacker, force_wait, airlock_target)) - return - if(airlock_target.locked) - return - attacker.visible_message(span_warning("We force the [airlock_target] to open.")) - airlock_target.open(BYPASS_DOOR_CHECKS) - else if(!airlock_target.hasPower()) - attacker.visible_message(span_warning("We force the [airlock_target] to open.")) - airlock_target.open(FORCING_DOOR_CHECKS) - else - airlock_target.open(DEFAULT_DOOR_CHECKS) diff --git a/code/datums/components/punchcooldown.dm b/code/datums/components/punchcooldown.dm index 7c2ae1047fe..80a72784c09 100644 --- a/code/datums/components/punchcooldown.dm +++ b/code/datums/components/punchcooldown.dm @@ -1,6 +1,6 @@ ///Your favourite Jojoke. Used for the gloves of the north star. /datum/component/wearertargeting/punchcooldown - signals = list(COMSIG_HUMAN_MELEE_UNARMED_ATTACK, COMSIG_LIVING_SLAP_MOB) + signals = list(COMSIG_LIVING_UNARMED_ATTACK, COMSIG_LIVING_SLAP_MOB) mobtype = /mob/living/carbon proctype = PROC_REF(reducecooldown) valid_slots = list(ITEM_SLOT_GLOVES) @@ -13,7 +13,7 @@ return RegisterSignal(parent, COMSIG_ITEM_ATTACK_SELF, PROC_REF(changewarcry)) -///Called on COMSIG_HUMAN_MELEE_UNARMED_ATTACK. Yells the warcry and and reduces punch cooldown. +///Called on COMSIG_LIVING_UNARMED_ATTACK. Yells the warcry and and reduces punch cooldown. /datum/component/wearertargeting/punchcooldown/proc/reducecooldown(mob/living/carbon/M, atom/target) if((M.combat_mode && isliving(target)) || istype(M.get_active_held_item(), /obj/item/hand_item/slapper)) M.changeNext_move(CLICK_CD_RAPID) diff --git a/code/datums/components/riding/riding_mob.dm b/code/datums/components/riding/riding_mob.dm index f7b48ecb01b..85aaee4ab7c 100644 --- a/code/datums/components/riding/riding_mob.dm +++ b/code/datums/components/riding/riding_mob.dm @@ -218,7 +218,7 @@ /datum/component/riding/creature/human/RegisterWithParent() . = ..() - RegisterSignal(parent, COMSIG_HUMAN_EARLY_UNARMED_ATTACK, PROC_REF(on_host_unarmed_melee)) + RegisterSignal(parent, COMSIG_LIVING_UNARMED_ATTACK, PROC_REF(on_host_unarmed_melee)) RegisterSignal(parent, COMSIG_LIVING_SET_BODY_POSITION, PROC_REF(check_carrier_fall_over)) /datum/component/riding/creature/human/log_riding(mob/living/living_parent, mob/living/rider) @@ -240,12 +240,13 @@ return ..() /// If the carrier shoves the person they're carrying, force the carried mob off -/datum/component/riding/creature/human/proc/on_host_unarmed_melee(mob/living/carbon/human/human_parent, atom/target, proximity, modifiers) +/datum/component/riding/creature/human/proc/on_host_unarmed_melee(mob/living/source, atom/target, proximity, modifiers) SIGNAL_HANDLER - if(LAZYACCESS(modifiers, RIGHT_CLICK) && (target in human_parent.buckled_mobs)) + if(LAZYACCESS(modifiers, RIGHT_CLICK) && (target in source.buckled_mobs)) force_dismount(target) return COMPONENT_CANCEL_ATTACK_CHAIN + return NONE /// If the carrier gets knocked over, force the rider(s) off and see if someone got hurt /datum/component/riding/creature/human/proc/check_carrier_fall_over(mob/living/carbon/human/human_parent) diff --git a/code/datums/components/shovel_hands.dm b/code/datums/components/shovel_hands.dm index e4ee2d644d3..34eaf8a98b6 100644 --- a/code/datums/components/shovel_hands.dm +++ b/code/datums/components/shovel_hands.dm @@ -14,10 +14,10 @@ /datum/component/shovel_hands/RegisterWithParent() . = ..() - RegisterSignals(parent, list(COMSIG_LIVING_UNARMED_ATTACK, COMSIG_HUMAN_MELEE_UNARMED_ATTACK, COMSIG_HOSTILE_PRE_ATTACKINGTARGET), PROC_REF(dig)) + RegisterSignals(parent, list(COMSIG_LIVING_UNARMED_ATTACK, COMSIG_HOSTILE_PRE_ATTACKINGTARGET), PROC_REF(dig)) /datum/component/shovel_hands/UnregisterFromParent() - UnregisterSignal(parent, list(COMSIG_LIVING_UNARMED_ATTACK, COMSIG_HUMAN_MELEE_UNARMED_ATTACK, COMSIG_HOSTILE_PRE_ATTACKINGTARGET)) + UnregisterSignal(parent, list(COMSIG_LIVING_UNARMED_ATTACK, COMSIG_HOSTILE_PRE_ATTACKINGTARGET)) return ..() /datum/component/shovel_hands/Destroy(force, silent) diff --git a/code/datums/components/shy.dm b/code/datums/components/shy.dm index 845da7e0f7d..5743322dea1 100644 --- a/code/datums/components/shy.dm +++ b/code/datums/components/shy.dm @@ -46,7 +46,7 @@ /datum/component/shy/RegisterWithParent() RegisterSignal(parent, COMSIG_MOB_CLICKON, PROC_REF(on_clickon)) RegisterSignal(parent, COMSIG_LIVING_TRY_PULL, PROC_REF(on_try_pull)) - RegisterSignals(parent, list(COMSIG_LIVING_UNARMED_ATTACK, COMSIG_HUMAN_EARLY_UNARMED_ATTACK), PROC_REF(on_unarmed_attack)) + RegisterSignal(parent, COMSIG_LIVING_UNARMED_ATTACK, PROC_REF(on_unarmed_attack)) RegisterSignal(parent, COMSIG_TRY_STRIP, PROC_REF(on_try_strip)) RegisterSignal(parent, COMSIG_TRY_ALT_ACTION, PROC_REF(on_try_alt_action)) @@ -54,7 +54,7 @@ UnregisterSignal(parent, list( COMSIG_MOB_CLICKON, COMSIG_LIVING_TRY_PULL, - COMSIG_LIVING_UNARMED_ATTACK, COMSIG_HUMAN_EARLY_UNARMED_ATTACK, + COMSIG_LIVING_UNARMED_ATTACK, COMSIG_TRY_STRIP, COMSIG_TRY_ALT_ACTION, )) @@ -137,4 +137,3 @@ return is_shy(target) && COMPONENT_CANT_ALT_ACTION #undef SHY_COMPONENT_CACHE_TIME - diff --git a/code/datums/components/shy_in_room.dm b/code/datums/components/shy_in_room.dm index 2413c9abafd..023dbaff719 100644 --- a/code/datums/components/shy_in_room.dm +++ b/code/datums/components/shy_in_room.dm @@ -17,7 +17,7 @@ /datum/component/shy_in_room/RegisterWithParent() RegisterSignal(parent, COMSIG_MOB_CLICKON, PROC_REF(on_clickon)) RegisterSignal(parent, COMSIG_LIVING_TRY_PULL, PROC_REF(on_try_pull)) - RegisterSignals(parent, list(COMSIG_LIVING_UNARMED_ATTACK, COMSIG_HUMAN_EARLY_UNARMED_ATTACK), PROC_REF(on_unarmed_attack)) + RegisterSignal(parent, COMSIG_LIVING_UNARMED_ATTACK, PROC_REF(on_unarmed_attack)) RegisterSignal(parent, COMSIG_TRY_STRIP, PROC_REF(on_try_strip)) RegisterSignal(parent, COMSIG_TRY_ALT_ACTION, PROC_REF(on_try_alt_action)) @@ -27,7 +27,6 @@ COMSIG_MOB_CLICKON, COMSIG_LIVING_TRY_PULL, COMSIG_LIVING_UNARMED_ATTACK, - COMSIG_HUMAN_EARLY_UNARMED_ATTACK, COMSIG_TRY_STRIP, COMSIG_TRY_ALT_ACTION, )) @@ -73,4 +72,3 @@ /datum/component/shy_in_room/proc/on_try_alt_action(datum/source, atom/target) SIGNAL_HANDLER return is_shy(target) && COMPONENT_CANT_ALT_ACTION - diff --git a/code/datums/components/style/style.dm b/code/datums/components/style/style.dm index 42f5de156e0..b6b9770ec48 100644 --- a/code/datums/components/style/style.dm +++ b/code/datums/components/style/style.dm @@ -107,7 +107,7 @@ RegisterSignal(parent, COMSIG_MOB_EMOTED("flip"), PROC_REF(on_flip)) RegisterSignal(parent, COMSIG_MOB_EMOTED("spin"), PROC_REF(on_spin)) RegisterSignal(parent, COMSIG_MOB_ITEM_ATTACK, PROC_REF(on_attack)) - RegisterSignal(parent, COMSIG_HUMAN_MELEE_UNARMED_ATTACK, PROC_REF(on_punch)) + RegisterSignal(parent, COMSIG_LIVING_UNARMED_ATTACK, PROC_REF(on_punch)) RegisterSignal(SSdcs, COMSIG_GLOB_MOB_DEATH, PROC_REF(on_death)) RegisterSignal(parent, COMSIG_LIVING_RESONATOR_BURST, PROC_REF(on_resonator_burst)) RegisterSignal(parent, COMSIG_LIVING_PROJECTILE_PARRIED, PROC_REF(on_projectile_parry)) @@ -134,7 +134,7 @@ UnregisterSignal(parent, COMSIG_MOB_MINED) UnregisterSignal(parent, COMSIG_MOB_APPLY_DAMAGE) UnregisterSignal(parent, list(COMSIG_MOB_EMOTED("flip"), COMSIG_MOB_EMOTED("spin"))) - UnregisterSignal(parent, list(COMSIG_MOB_ITEM_ATTACK, COMSIG_HUMAN_MELEE_UNARMED_ATTACK)) + UnregisterSignal(parent, list(COMSIG_MOB_ITEM_ATTACK, COMSIG_LIVING_UNARMED_ATTACK)) UnregisterSignal(SSdcs, COMSIG_GLOB_MOB_DEATH) UnregisterSignal(parent, COMSIG_LIVING_RESONATOR_BURST) UnregisterSignal(parent, COMSIG_LIVING_PROJECTILE_PARRIED) diff --git a/code/datums/components/summoning.dm b/code/datums/components/summoning.dm index 54eea882e8a..220a4baca5f 100644 --- a/code/datums/components/summoning.dm +++ b/code/datums/components/summoning.dm @@ -1,16 +1,32 @@ /datum/component/summoning + /// Types of mob we can create var/list/mob_types = list() - var/spawn_chance // chance for the mob to spawn on hit in percent + /// Percentage chance to spawn a mob + var/spawn_chance + /// Maximum mobs we can have active at once var/max_mobs - var/spawn_delay // delay in spawning between mobs (deciseconds) + /// Cooldown between spawning mobs + var/spawn_delay + /// Text to display when spawning a mob var/spawn_text + /// Sound to play when spawning a mob var/spawn_sound + /// Factions to assign to a summoned mob var/list/faction - - var/last_spawned_time = 0 + /// Cooldown tracker for when we can summon another mob + COOLDOWN_DECLARE(summon_cooldown) + /// List containing all of our mobs var/list/spawned_mobs = list() -/datum/component/summoning/Initialize(mob_types, spawn_chance=100, max_mobs=3, spawn_delay=100, spawn_text="appears out of nowhere", spawn_sound='sound/magic/summon_magic.ogg', faction) +/datum/component/summoning/Initialize( + mob_types, + spawn_chance = 100, + max_mobs = 3, + spawn_delay = 10 SECONDS, + spawn_text = "appears out of nowhere", + spawn_sound = 'sound/magic/summon_magic.ogg', + list/faction, +) if(!isitem(parent) && !ishostile(parent) && !isgun(parent) && !ismachinery(parent) && !isstructure(parent) && !isprojectilespell(parent)) return COMPONENT_INCOMPATIBLE @@ -54,26 +70,22 @@ do_spawn_mob(get_turf(target), firer) /datum/component/summoning/proc/do_spawn_mob(atom/spawn_location, summoner) - if(spawned_mobs.len >= max_mobs) - return - if(last_spawned_time > world.time) + if(length(spawned_mobs) >= max_mobs || !COOLDOWN_FINISHED(src, summon_cooldown) || !prob(spawn_chance)) return - if(!prob(spawn_chance)) - return - last_spawned_time = world.time + spawn_delay + COOLDOWN_START(src, summon_cooldown, spawn_delay) var/chosen_mob_type = pick(mob_types) - var/mob/living/simple_animal/L = new chosen_mob_type(spawn_location) - if(ishostile(L)) - var/mob/living/simple_animal/hostile/H = L - H.friends += summoner // do not attack our summon boy - spawned_mobs += L + var/mob/living/summoned = new chosen_mob_type(spawn_location) + if(ishostile(summoned)) + var/mob/living/simple_animal/hostile/angry_boy = summoned + angry_boy.friends |= summoner // do not attack our summon boy + spawned_mobs |= summoned if(faction != null) - L.faction = faction - RegisterSignal(L, COMSIG_LIVING_DEATH, PROC_REF(on_spawned_death)) // so we can remove them from the list, etc (for mobs with corpses) - playsound(spawn_location,spawn_sound, 50, TRUE) - spawn_location.visible_message(span_danger("[L] [spawn_text].")) + summoned.faction = faction.Copy() + RegisterSignals(summoned, list(COMSIG_LIVING_DEATH, COMSIG_QDELETING), PROC_REF(on_spawned_death)) + spawn_location.visible_message(span_danger("[summoned] [spawn_text]!")) +/// When a spawned thing dies, remove it from our list /datum/component/summoning/proc/on_spawned_death(mob/killed, gibbed) SIGNAL_HANDLER - + UnregisterSignal(killed, list(COMSIG_LIVING_DEATH, COMSIG_QDELETING)) spawned_mobs -= killed diff --git a/code/datums/components/torn_wall.dm b/code/datums/components/torn_wall.dm new file mode 100644 index 00000000000..ebe0fe9a0a6 --- /dev/null +++ b/code/datums/components/torn_wall.dm @@ -0,0 +1,99 @@ + +#define TORN_WALL_RUINED 2 +#define TORN_WALL_DAMAGED 1 +#define TORN_WALL_INITIAL 0 + +/** + * Component applied to a wall to progressively destroy it. + * If component is applied to something which already has it, stage increases. + * Wall is destroyed on third application. + * Can be fixed using a welder + */ +/datum/component/torn_wall + dupe_mode = COMPONENT_DUPE_UNIQUE_PASSARGS + var/current_stage = TORN_WALL_INITIAL + +/datum/component/torn_wall/Initialize() + . = ..() + if (!iswallturf(parent) || isindestructiblewall(parent)) + return COMPONENT_INCOMPATIBLE + +/datum/component/torn_wall/RegisterWithParent() + RegisterSignal(parent, COMSIG_ATOM_EXAMINE, PROC_REF(on_examined)) + RegisterSignal(parent, COMSIG_ATOM_TOOL_ACT(TOOL_WELDER), PROC_REF(on_welded)) + RegisterSignal(parent, COMSIG_ATOM_UPDATE_OVERLAYS, PROC_REF(on_update_overlays)) + RegisterSignal(parent, COMSIG_TURF_CHANGE, PROC_REF(on_turf_changed)) + apply_visuals() + +/datum/component/torn_wall/UnregisterFromParent() + var/atom/atom_parent = parent + UnregisterSignal(parent, list( + COMSIG_ATOM_EXAMINE, + COMSIG_ATOM_TOOL_ACT(TOOL_WELDER), + COMSIG_ATOM_UPDATE_OVERLAYS, + COMSIG_TURF_CHANGE, + )) + atom_parent.update_appearance(UPDATE_ICON) + +/datum/component/torn_wall/InheritComponent(datum/component/C, i_am_original) + increase_stage() + +/// Play a fun animation and make our wall look damaged +/datum/component/torn_wall/proc/apply_visuals() + var/atom/atom_parent = parent + playsound(atom_parent, 'sound/effects/bang.ogg', 50, vary = TRUE) + atom_parent.update_appearance(UPDATE_ICON) + atom_parent.Shake(shake_interval = 0.1 SECONDS, duration = 0.5 SECONDS) + +/// Make the effect more dramatic +/datum/component/torn_wall/proc/increase_stage() + current_stage++ + if (current_stage != TORN_WALL_RUINED) + apply_visuals() + return + var/turf/closed/wall/attached_wall = parent + playsound(attached_wall, 'sound/effects/meteorimpact.ogg', 100, vary = TRUE) + attached_wall.dismantle_wall(devastated = TRUE) + +/// Fix it up on weld +/datum/component/torn_wall/proc/on_welded(atom/source, mob/user, obj/item/tool) + SIGNAL_HANDLER + INVOKE_ASYNC(src, PROC_REF(try_repair), source, user, tool) + return COMPONENT_BLOCK_TOOL_ATTACK + +/// Fix us up +/datum/component/torn_wall/proc/try_repair(atom/source, mob/user, obj/item/tool) + source.balloon_alert(user, "repairing...") + if(!tool.use_tool(source, user, 5 SECONDS, amount = 2, volume = 50)) + source.balloon_alert(user, "interrupted!") + return + current_stage-- + if (current_stage < TORN_WALL_INITIAL) + qdel(src) + return + source.update_appearance(UPDATE_ICON) + source.tool_act(user, tool, TOOL_WELDER, is_right_clicking = FALSE) // Keep going + +/// Give them a hint +/datum/component/torn_wall/proc/on_examined(atom/source, mob/user, list/examine_list) + SIGNAL_HANDLER + var/intensity = (current_stage == TORN_WALL_INITIAL) ? "slightly" : "badly" + examine_list += span_notice("It looks [intensity] damaged.") + examine_list += span_info("You may be able to repair it using a welding tool.") + +/// Show a little crack on here +/datum/component/torn_wall/proc/on_update_overlays(turf/source, list/overlays) + SIGNAL_HANDLER + var/mutable_appearance/crack = mutable_appearance('icons/turf/overlays.dmi', "explodable", source.layer + 0.1) + if (current_stage == TORN_WALL_INITIAL) + crack.alpha *= 0.5 + overlays += crack + +/// If the wall becomes any other turf, delete us. Transforming into a different works fine as a fix. +/datum/component/torn_wall/proc/on_turf_changed() + SIGNAL_HANDLER + qdel(src) + +#undef TORN_WALL_RUINED +#undef TORN_WALL_DAMAGED +#undef TORN_WALL_INITIAL diff --git a/code/datums/diseases/_MobProcs.dm b/code/datums/diseases/_MobProcs.dm index e64e91c5533..1aa8b6654cd 100644 --- a/code/datums/diseases/_MobProcs.dm +++ b/code/datums/diseases/_MobProcs.dm @@ -98,7 +98,7 @@ if(HAS_TRAIT(src, TRAIT_VIRUS_RESISTANCE) && prob(75)) return - if(((disease.spread_flags & DISEASE_SPREAD_AIRBORNE) || force_spread) && prob((50*disease.spreading_modifier) - 1)) + if(((disease.spread_flags & DISEASE_SPREAD_AIRBORNE) || force_spread) && prob(min((50*disease.spreading_modifier - 1), 50))) ForceContractDisease(disease) /mob/living/carbon/AirborneContractDisease(datum/disease/disease, force_spread) diff --git a/code/datums/elements/amputating_limbs.dm b/code/datums/elements/amputating_limbs.dm index 16a99e96f6c..8684a76f47f 100644 --- a/code/datums/elements/amputating_limbs.dm +++ b/code/datums/elements/amputating_limbs.dm @@ -32,16 +32,16 @@ src.minimum_stat = minimum_stat src.snip_chance = snip_chance src.target_zones = target_zones - RegisterSignals(target, list(COMSIG_LIVING_UNARMED_ATTACK, COMSIG_HUMAN_MELEE_UNARMED_ATTACK, COMSIG_HOSTILE_PRE_ATTACKINGTARGET), PROC_REF(try_amputate)) + RegisterSignals(target, list(COMSIG_LIVING_UNARMED_ATTACK, COMSIG_HOSTILE_PRE_ATTACKINGTARGET), PROC_REF(try_amputate)) /datum/element/amputating_limbs/Detach(datum/source) - UnregisterSignal(source, list(COMSIG_LIVING_UNARMED_ATTACK, COMSIG_HUMAN_MELEE_UNARMED_ATTACK, COMSIG_HOSTILE_PRE_ATTACKINGTARGET)) + UnregisterSignal(source, list(COMSIG_LIVING_UNARMED_ATTACK, COMSIG_HOSTILE_PRE_ATTACKINGTARGET)) return ..() /// Called when you click on literally anything with your hands, see if it is an injured carbon and then try to cut it up -/datum/element/amputating_limbs/proc/try_amputate(mob/living/surgeon, atom/victim) +/datum/element/amputating_limbs/proc/try_amputate(mob/living/surgeon, atom/victim, proximity, modifiers) SIGNAL_HANDLER - if (!iscarbon(victim) || HAS_TRAIT(victim, TRAIT_NODISMEMBER) || !prob(snip_chance)) + if (!proximity || !iscarbon(victim) || HAS_TRAIT(victim, TRAIT_NODISMEMBER) || !prob(snip_chance)) return var/mob/living/carbon/limbed_victim = victim diff --git a/code/datums/elements/basic_eating.dm b/code/datums/elements/basic_eating.dm index 86f4be63cac..08c2ed0c192 100644 --- a/code/datums/elements/basic_eating.dm +++ b/code/datums/elements/basic_eating.dm @@ -37,7 +37,12 @@ /datum/element/basic_eating/proc/on_unarm_attack(mob/living/eater, atom/target, proximity, modifiers) SIGNAL_HANDLER - try_eating(eater, target) + if(!proximity) + return NONE + + if(try_eating(eater, target)) + return COMPONENT_CANCEL_ATTACK_CHAIN + return NONE /datum/element/basic_eating/proc/on_pre_attackingtarget(mob/living/eater, atom/target) SIGNAL_HANDLER @@ -45,7 +50,7 @@ /datum/element/basic_eating/proc/try_eating(mob/living/eater, atom/target) if(!is_type_in_list(target, food_types)) - return + return FALSE var/eat_verb = pick("bite","chew","nibble","gnaw","gobble","chomp") if (heal_amt > 0) @@ -54,16 +59,17 @@ eater.heal_overall_damage(heal_amt) eater.visible_message(span_notice("[eater] [eat_verb]s [target]."), span_notice("You [eat_verb] [target][healed ? ", restoring some health" : ""].")) finish_eating(eater, target) - return + return TRUE if (damage_amount > 0 && damage_type) eater.apply_damage(damage_amount, damage_type) eater.visible_message(span_notice("[eater] [eat_verb]s [target], and seems to hurt itself."), span_notice("You [eat_verb] [target], hurting yourself in the process.")) finish_eating(eater, target) - return + return TRUE eater.visible_message(span_notice("[eater] [eat_verb]s [target]."), span_notice("You [eat_verb] [target].")) finish_eating(eater, target) + return TRUE /datum/element/basic_eating/proc/finish_eating(mob/living/eater, atom/target) playsound(eater.loc,'sound/items/eatfood.ogg', rand(10,50), TRUE) diff --git a/code/datums/elements/dextrous.dm b/code/datums/elements/dextrous.dm index 335c7c196d1..526dfa974af 100644 --- a/code/datums/elements/dextrous.dm +++ b/code/datums/elements/dextrous.dm @@ -50,8 +50,10 @@ /// Try picking up items /datum/element/dextrous/proc/on_hand_clicked(mob/living/hand_haver, atom/target, proximity, modifiers) SIGNAL_HANDLER + if(!proximity) + return NONE if (!isitem(target) && hand_haver.combat_mode) - return + return NONE if (LAZYACCESS(modifiers, RIGHT_CLICK)) INVOKE_ASYNC(target, TYPE_PROC_REF(/atom, attack_hand_secondary), hand_haver, modifiers) else diff --git a/code/datums/elements/door_pryer.dm b/code/datums/elements/door_pryer.dm new file mode 100644 index 00000000000..a17687407e3 --- /dev/null +++ b/code/datums/elements/door_pryer.dm @@ -0,0 +1,70 @@ +/** + * Attached to a basic mob. + * Causes attacks on doors to attempt to open them. + */ +/datum/element/door_pryer + element_flags = ELEMENT_BESPOKE + argument_hash_start_idx = 2 + /// Time it takes to open a door with force + var/pry_time + /// Interaction key for if we force a door open + var/interaction_key + +/datum/element/door_pryer/Attach(datum/target, pry_time = 10 SECONDS, interaction_key = null) + . = ..() + if (!isliving(target)) + return ELEMENT_INCOMPATIBLE + src.pry_time = pry_time + src.interaction_key = interaction_key + RegisterSignal(target, COMSIG_LIVING_UNARMED_ATTACK, PROC_REF(on_attack)) + +/datum/element/door_pryer/Detach(datum/source) + . = ..() + UnregisterSignal(source, COMSIG_LIVING_UNARMED_ATTACK) + +/// If we're targetting an airlock, open it +/datum/element/door_pryer/proc/on_attack(mob/living/basic/attacker, atom/target, proximity_flag) + SIGNAL_HANDLER + if(!proximity_flag || !istype(target, /obj/machinery/door/airlock)) + return NONE + var/obj/machinery/door/airlock/airlock_target = target + if (!airlock_target.density) + return NONE // It's already open numbnuts + + if(DOING_INTERACTION_WITH_TARGET(attacker, target) || (!isnull(interaction_key) && DOING_INTERACTION(attacker, interaction_key))) + attacker.balloon_alert(attacker, "busy!") + return COMPONENT_CANCEL_ATTACK_CHAIN + + if (airlock_target.locked || airlock_target.welded || airlock_target.seal) + if (!attacker.combat_mode) + airlock_target.balloon_alert(attacker, "it's sealed!") + return COMPONENT_CANCEL_ATTACK_CHAIN + return // Attack the door + + INVOKE_ASYNC(src, PROC_REF(open_door), attacker, airlock_target) + return COMPONENT_CANCEL_ATTACK_CHAIN + +/// Try opening the door, and if we can't then try forcing it +/datum/element/door_pryer/proc/open_door(mob/living/basic/attacker, obj/machinery/door/airlock/airlock_target) + if (!airlock_target.hasPower()) + attacker.visible_message(span_warning("[attacker] forces the [airlock_target] to open.")) + airlock_target.open(FORCING_DOOR_CHECKS) + return + + if (airlock_target.allowed(attacker)) + airlock_target.open(DEFAULT_DOOR_CHECKS) + return + + attacker.visible_message(\ + message = span_warning("[attacker] starts forcing the [airlock_target] open!"), + blind_message = span_hear("You hear a metal screeching sound."), + ) + playsound(airlock_target, 'sound/machines/airlock_alien_prying.ogg', 100, TRUE) + airlock_target.balloon_alert(attacker, "prying...") + if(!do_after(attacker, pry_time, airlock_target)) + airlock_target.balloon_alert(attacker, "interrupted!") + return + if(airlock_target.locked) + return + attacker.visible_message(span_warning("[attacker] forces the [airlock_target] to open.")) + airlock_target.open(BYPASS_DOOR_CHECKS) diff --git a/code/datums/elements/human_biter.dm b/code/datums/elements/human_biter.dm new file mode 100644 index 00000000000..852dea12320 --- /dev/null +++ b/code/datums/elements/human_biter.dm @@ -0,0 +1,28 @@ +/// Allows carbons with heads to attempt to bite mobs if attacking with cuffed hands / missing arms +/datum/element/human_biter + +/datum/element/human_biter/Attach(datum/target) + . = ..() + if(!iscarbon(target)) + return ELEMENT_INCOMPATIBLE + + RegisterSignal(target, COMSIG_LIVING_EARLY_UNARMED_ATTACK, PROC_REF(try_bite)) + +/datum/element/human_biter/Detach(datum/source, ...) + . = ..() + UnregisterSignal(source, COMSIG_LIVING_EARLY_UNARMED_ATTACK) + +/datum/element/human_biter/proc/try_bite(mob/living/carbon/human/source, atom/target, proximity_flag, modifiers) + SIGNAL_HANDLER + + if(!proximity_flag || !source.combat_mode || LAZYACCESS(modifiers, RIGHT_CLICK) || !isliving(target)) + return NONE + + // If we can attack like normal, just go ahead and do that + if(source.can_unarmed_attack()) + return NONE + + if(target.attack_paw(source, modifiers)) + return COMPONENT_CANCEL_ATTACK_CHAIN // bite successful! + + return COMPONENT_SKIP_ATTACK // we will fail anyways if we try to attack normally, so skip the rest diff --git a/code/datums/elements/mob_grabber.dm b/code/datums/elements/mob_grabber.dm index a85c5dc48b2..cc766f24887 100644 --- a/code/datums/elements/mob_grabber.dm +++ b/code/datums/elements/mob_grabber.dm @@ -13,18 +13,19 @@ return ELEMENT_INCOMPATIBLE src.minimum_stat = minimum_stat src.steal_from_others = steal_from_others - RegisterSignals(target, list(COMSIG_LIVING_UNARMED_ATTACK, COMSIG_HUMAN_MELEE_UNARMED_ATTACK, COMSIG_HOSTILE_PRE_ATTACKINGTARGET), PROC_REF(grab_mob)) + RegisterSignals(target, list(COMSIG_LIVING_UNARMED_ATTACK, COMSIG_HOSTILE_PRE_ATTACKINGTARGET), PROC_REF(grab_mob)) /datum/element/mob_grabber/Detach(datum/source) - UnregisterSignal(source, list(COMSIG_LIVING_UNARMED_ATTACK, COMSIG_HUMAN_MELEE_UNARMED_ATTACK, COMSIG_HOSTILE_PRE_ATTACKINGTARGET)) + UnregisterSignal(source, list(COMSIG_LIVING_UNARMED_ATTACK, COMSIG_HOSTILE_PRE_ATTACKINGTARGET)) . = ..() /// Try and grab something we attacked -/datum/element/mob_grabber/proc/grab_mob(mob/living/source, mob/living/target) +/datum/element/mob_grabber/proc/grab_mob(mob/living/source, mob/living/target, proximity, modifiers) SIGNAL_HANDLER - if (!isliving(target) || !source.Adjacent(target) || target.stat < minimum_stat) - return + if (!isliving(target) || !proximity || target.stat < minimum_stat) + return NONE var/atom/currently_pulled = target.pulledby if (!isnull(currently_pulled) && (!steal_from_others || currently_pulled == source)) - return + return NONE INVOKE_ASYNC(target, TYPE_PROC_REF(/mob/living, grabbedby), source) + return COMPONENT_CANCEL_ATTACK_CHAIN diff --git a/code/datums/elements/structure_repair.dm b/code/datums/elements/structure_repair.dm index d3b26eed815..1f57a3d1730 100644 --- a/code/datums/elements/structure_repair.dm +++ b/code/datums/elements/structure_repair.dm @@ -25,11 +25,11 @@ return ..() /// If the target is of a valid type, interrupt the attack chain to repair it instead -/datum/element/structure_repair/proc/try_repair(mob/living/fixer, atom/target) +/datum/element/structure_repair/proc/try_repair(mob/living/fixer, atom/target, proximity) SIGNAL_HANDLER - if (!is_type_in_typecache(target, structure_types_typecache)) - return + if (!proximity || !is_type_in_typecache(target, structure_types_typecache)) + return NONE if (target.get_integrity() >= target.max_integrity) target.balloon_alert(fixer, "not damaged!") diff --git a/code/datums/elements/wall_smasher.dm b/code/datums/elements/wall_smasher.dm index 3c6c1d92da7..ba8a689253c 100644 --- a/code/datums/elements/wall_smasher.dm +++ b/code/datums/elements/wall_smasher.dm @@ -17,7 +17,7 @@ return ELEMENT_INCOMPATIBLE src.strength_flag = strength_flag - RegisterSignals(target, list(COMSIG_LIVING_UNARMED_ATTACK, COMSIG_HUMAN_EARLY_UNARMED_ATTACK), PROC_REF(on_unarm_attack)) // Players + RegisterSignal(target, COMSIG_LIVING_UNARMED_ATTACK, PROC_REF(on_unarm_attack)) // Players RegisterSignal(target, COMSIG_HOSTILE_PRE_ATTACKINGTARGET, PROC_REF(on_pre_attackingtarget)) // AI if (isanimal_or_basicmob(target)) @@ -25,7 +25,7 @@ animal_target.environment_smash = strength_flag /datum/element/wall_smasher/Detach(datum/target) - UnregisterSignal(target, list(COMSIG_LIVING_UNARMED_ATTACK, COMSIG_HUMAN_EARLY_UNARMED_ATTACK, COMSIG_HOSTILE_PRE_ATTACKINGTARGET)) + UnregisterSignal(target, list(COMSIG_LIVING_UNARMED_ATTACK, COMSIG_HOSTILE_PRE_ATTACKINGTARGET)) if (isanimal_or_basicmob(target)) var/mob/living/simple_animal/animal_target = target animal_target.environment_smash = initial(animal_target.environment_smash) @@ -34,19 +34,19 @@ /datum/element/wall_smasher/proc/on_unarm_attack(mob/living/puncher, atom/target, proximity, modifiers) SIGNAL_HANDLER - try_smashing(puncher, target) + return try_smashing(puncher, target) /datum/element/wall_smasher/proc/on_pre_attackingtarget(mob/living/puncher, atom/target) SIGNAL_HANDLER - try_smashing(puncher, target) + return try_smashing(puncher, target) /datum/element/wall_smasher/proc/try_smashing(mob/living/puncher, atom/target) if (!isturf(target)) - return + return NONE if (isfloorturf(target)) - return + return NONE if (isindestructiblewall(target)) - return + return NONE puncher.changeNext_move(CLICK_CD_MELEE) puncher.do_attack_animation(target) diff --git a/code/datums/elements/wall_tearer.dm b/code/datums/elements/wall_tearer.dm new file mode 100644 index 00000000000..e7ca4b3be96 --- /dev/null +++ b/code/datums/elements/wall_tearer.dm @@ -0,0 +1,83 @@ +/// Returned if we can rip up this target +#define WALL_TEAR_ALLOWED TRUE +/// Returned if we can't rip up this target +#define WALL_TEAR_INVALID FALSE +/// Returned if we can't rip up the target but still don't want to attack it +#define WALL_TEAR_FAIL_CANCEL_CHAIN -1 + +/** + * Allows attached mobs to destroy walls over time, a little less unreasonable than the instant wall deletion of wall_smasher + */ +/datum/element/wall_tearer + element_flags = ELEMENT_BESPOKE + argument_hash_start_idx = 2 + /// Whether we can break reinforced walls + var/allow_reinforced + /// How long it takes for us to destroy a wall completely (its a 3 step process so this will be divided by three) + var/tear_time + /// How much longer it takes to break reinforced walls + var/reinforced_multiplier + /// What interaction key do we use for our interaction + var/do_after_key + +/datum/element/wall_tearer/Attach(datum/target, allow_reinforced = TRUE, tear_time = 4 SECONDS, reinforced_multiplier = 3, do_after_key = null) + . = ..() + if (!isliving(target)) + return ELEMENT_INCOMPATIBLE + src.allow_reinforced = allow_reinforced + src.tear_time = tear_time + src.reinforced_multiplier = reinforced_multiplier + src.do_after_key = do_after_key + RegisterSignal(target, COMSIG_LIVING_UNARMED_ATTACK, PROC_REF(on_attacked_wall)) + +/datum/element/wall_tearer/Detach(datum/source) + . = ..() + UnregisterSignal(source, COMSIG_LIVING_UNARMED_ATTACK) + +/// Try to tear up a wall +/datum/element/wall_tearer/proc/on_attacked_wall(mob/living/tearer, atom/target, proximity_flag) + SIGNAL_HANDLER + if (!proximity_flag) + return NONE + if (DOING_INTERACTION_WITH_TARGET(tearer, target) || (!isnull(do_after_key) && DOING_INTERACTION(tearer, do_after_key))) + tearer.balloon_alert(tearer, "busy!") + return COMPONENT_HOSTILE_NO_ATTACK + var/is_valid = validate_target(target, tearer) + if (is_valid != WALL_TEAR_ALLOWED) + return is_valid == WALL_TEAR_FAIL_CANCEL_CHAIN ? COMPONENT_HOSTILE_NO_ATTACK : NONE + INVOKE_ASYNC(src, PROC_REF(rip_and_tear), tearer, target) + return COMPONENT_HOSTILE_NO_ATTACK + +/datum/element/wall_tearer/proc/rip_and_tear(mob/living/tearer, atom/target) + // We need to do this three times to actually destroy it + var/rip_time = (istype(target, /turf/closed/wall/r_wall) ? tear_time * reinforced_multiplier : tear_time) / 3 + if (rip_time > 0) + tearer.visible_message(span_warning("[tearer] begins tearing through [target]!")) + playsound(tearer, 'sound/machines/airlock_alien_prying.ogg', vol = 100, vary = TRUE) + target.balloon_alert(tearer, "tearing...") + if (!do_after(tearer, delay = rip_time, target = target, interaction_key = do_after_key)) + tearer.balloon_alert(tearer, "interrupted!") + return + // Might have been replaced, removed, or reinforced during our do_after + var/is_valid = validate_target(target, tearer) + if (is_valid != WALL_TEAR_ALLOWED) + return + target.AddComponent(/datum/component/torn_wall) + is_valid = validate_target(target, tearer) // And now we might have just destroyed it + if (is_valid == WALL_TEAR_ALLOWED) + tearer.UnarmedAttack(target, proximity_flag = TRUE) + +/// Check if the target atom is a wall we can actually rip up +/datum/element/wall_tearer/proc/validate_target(atom/target, mob/living/tearer) + if (!isclosedturf(target) || isindestructiblewall(target)) + return WALL_TEAR_INVALID + + var/reinforced = istype(target, /turf/closed/wall/r_wall) + if (!allow_reinforced && reinforced) + target.balloon_alert(tearer, "it's too strong!") + return WALL_TEAR_FAIL_CANCEL_CHAIN + return WALL_TEAR_ALLOWED + +#undef WALL_TEAR_ALLOWED +#undef WALL_TEAR_INVALID +#undef WALL_TEAR_FAIL_CANCEL_CHAIN diff --git a/code/datums/looping_sounds/vents.dm b/code/datums/looping_sounds/vents.dm new file mode 100644 index 00000000000..2d0a3443631 --- /dev/null +++ b/code/datums/looping_sounds/vents.dm @@ -0,0 +1,7 @@ +/datum/looping_sound/vent_pump_overclock + start_sound = 'sound/machines/fan_start.ogg' + start_length = 1.5 SECONDS + end_sound = 'sound/machines/fan_stop.ogg' + end_sound = 1.5 SECONDS + mid_sounds = 'sound/machines/fan_loop.ogg' + mid_length = 2 SECONDS diff --git a/code/datums/mutations/chameleon.dm b/code/datums/mutations/chameleon.dm index 0ae69e71f66..4ec73f92a4b 100644 --- a/code/datums/mutations/chameleon.dm +++ b/code/datums/mutations/chameleon.dm @@ -19,7 +19,7 @@ /// SKYRAT EDIT END owner.alpha = CHAMELEON_MUTATION_DEFAULT_TRANSPARENCY RegisterSignal(owner, COMSIG_MOVABLE_MOVED, PROC_REF(on_move)) - RegisterSignal(owner, COMSIG_HUMAN_EARLY_UNARMED_ATTACK, PROC_REF(on_attack_hand)) + RegisterSignal(owner, COMSIG_LIVING_UNARMED_ATTACK, PROC_REF(on_attack_hand)) /datum/mutation/human/chameleon/on_life(seconds_per_tick, times_fired) /// SKYRAT EDIT BEGIN @@ -73,7 +73,7 @@ if(..()) return owner.alpha = 255 - UnregisterSignal(owner, list(COMSIG_MOVABLE_MOVED, COMSIG_HUMAN_EARLY_UNARMED_ATTACK)) + UnregisterSignal(owner, list(COMSIG_MOVABLE_MOVED, COMSIG_LIVING_UNARMED_ATTACK)) /// SKYRAT EDIT BEGIN REMOVE_TRAIT(owner, TRAIT_CHAMELEON_SKIN, GENETIC_MUTATION) /// SKYRAT EDIT END diff --git a/code/datums/mutations/hulk.dm b/code/datums/mutations/hulk.dm index 9ab5d4b86ef..970d850eafa 100644 --- a/code/datums/mutations/hulk.dm +++ b/code/datums/mutations/hulk.dm @@ -29,26 +29,27 @@ part.variable_color = "#00aa00" owner.update_body_parts() owner.add_mood_event("hulk", /datum/mood_event/hulk) - RegisterSignal(owner, COMSIG_HUMAN_EARLY_UNARMED_ATTACK, PROC_REF(on_attack_hand)) + RegisterSignal(owner, COMSIG_LIVING_EARLY_UNARMED_ATTACK, PROC_REF(on_attack_hand)) RegisterSignal(owner, COMSIG_MOB_SAY, PROC_REF(handle_speech)) RegisterSignal(owner, COMSIG_MOB_CLICKON, PROC_REF(check_swing)) /datum/mutation/human/hulk/proc/on_attack_hand(mob/living/carbon/human/source, atom/target, proximity, modifiers) SIGNAL_HANDLER - if(!proximity) - return - if(!source.combat_mode || LAZYACCESS(modifiers, RIGHT_CLICK)) - return - if(target.attack_hulk(owner)) - if(world.time > (last_scream + scream_delay)) - last_scream = world.time - INVOKE_ASYNC(src, PROC_REF(scream_attack), source) - log_combat(source, target, "punched", "hulk powers") - source.do_attack_animation(target, ATTACK_EFFECT_SMASH) - source.changeNext_move(CLICK_CD_MELEE) - + if(!source.combat_mode || !proximity || LAZYACCESS(modifiers, RIGHT_CLICK)) + return NONE + if(!source.can_unarmed_attack()) return COMPONENT_CANCEL_ATTACK_CHAIN + if(!target.attack_hulk(owner)) + return NONE + + if(world.time > (last_scream + scream_delay)) + last_scream = world.time + INVOKE_ASYNC(src, PROC_REF(scream_attack), source) + log_combat(source, target, "punched", "hulk powers") + source.do_attack_animation(target, ATTACK_EFFECT_SMASH) + source.changeNext_move(CLICK_CD_MELEE) + return COMPONENT_CANCEL_ATTACK_CHAIN /datum/mutation/human/hulk/proc/scream_attack(mob/living/carbon/human/source) source.say("WAAAAAAAAAAAAAAGH!", forced="hulk") @@ -90,7 +91,7 @@ part.variable_color = null owner.update_body_parts() owner.clear_mood_event("hulk") - UnregisterSignal(owner, COMSIG_HUMAN_EARLY_UNARMED_ATTACK) + UnregisterSignal(owner, COMSIG_LIVING_EARLY_UNARMED_ATTACK) UnregisterSignal(owner, COMSIG_MOB_SAY) UnregisterSignal(owner, COMSIG_MOB_CLICKON) diff --git a/code/datums/recipe.dm b/code/datums/recipe.dm index de3d3d9b96d..2149c5452ea 100644 --- a/code/datums/recipe.dm +++ b/code/datums/recipe.dm @@ -89,7 +89,6 @@ for (var/obj/O in (container.contents-result_obj)) if (O.reagents) O.reagents.del_reagent(/datum/reagent/consumable/nutriment) - O.reagents.update_total() O.reagents.trans_to(result_obj, O.reagents.total_volume) qdel(O) container.reagents.clear_reagents() diff --git a/code/datums/sprite_accessories.dm b/code/datums/sprite_accessories.dm index 16ce537b840..e0e84baa190 100644 --- a/code/datums/sprite_accessories.dm +++ b/code/datums/sprite_accessories.dm @@ -85,6 +85,7 @@ ////////////////////// /datum/sprite_accessory/hair icon = 'icons/mob/human/human_face.dmi' // default icon for all hairs + var/y_offset = 0 // Y offset to apply so we can have hair that reaches above the player sprite's visual bounding box // please make sure they're sorted alphabetically and, where needed, categorized // try to capitalize the names please~ @@ -103,6 +104,11 @@ name = "Afro (Large)" icon_state = "hair_bigafro" +/datum/sprite_accessory/hair/afro_huge + name = "Afro (Huge)" + icon_state = "hair_hugeafro" + y_offset = 6 + /datum/sprite_accessory/hair/allthefuzz name = "All The Fuzz" icon_state = "hair_allthefuzz" diff --git a/code/datums/weather/weather_types/ash_storm.dm b/code/datums/weather/weather_types/ash_storm.dm index 92a1ba1eed6..bb4e5af63f3 100644 --- a/code/datums/weather/weather_types/ash_storm.dm +++ b/code/datums/weather/weather_types/ash_storm.dm @@ -66,7 +66,7 @@ return FALSE /datum/weather/ash_storm/weather_act(mob/living/victim) - victim.adjustFireLoss(4) + victim.adjustFireLoss(4, required_bodytype = BODYTYPE_ORGANIC) /datum/weather/ash_storm/end() GLOB.ash_storm_sounds -= weak_sounds diff --git a/code/datums/wounds/bones.dm b/code/datums/wounds/bones.dm index 270d2a23f42..d4624acbb92 100644 --- a/code/datums/wounds/bones.dm +++ b/code/datums/wounds/bones.dm @@ -60,9 +60,9 @@ /datum/wound/blunt/bone/set_victim(new_victim) if (victim) - UnregisterSignal(victim, COMSIG_HUMAN_EARLY_UNARMED_ATTACK) + UnregisterSignal(victim, COMSIG_LIVING_UNARMED_ATTACK) if (new_victim) - RegisterSignal(new_victim, COMSIG_HUMAN_EARLY_UNARMED_ATTACK, PROC_REF(attack_with_hurt_hand)) + RegisterSignal(new_victim, COMSIG_LIVING_UNARMED_ATTACK, PROC_REF(attack_with_hurt_hand)) return ..() @@ -113,8 +113,8 @@ /datum/wound/blunt/bone/proc/attack_with_hurt_hand(mob/M, atom/target, proximity) SIGNAL_HANDLER - if(victim.get_active_hand() != limb || !victim.combat_mode || !ismob(target) || severity <= WOUND_SEVERITY_MODERATE) - return + if(victim.get_active_hand() != limb || !proximity || !victim.combat_mode || !ismob(target) || severity <= WOUND_SEVERITY_MODERATE) + return NONE // With a severe or critical wound, you have a 15% or 30% chance to proc pain on hit if(prob((severity - 1) * 15)) @@ -130,6 +130,7 @@ limb.receive_damage(brute=rand(3,7)) return COMPONENT_CANCEL_ATTACK_CHAIN + return NONE /datum/wound/blunt/bone/receive_damage(wounding_type, wounding_dmg, wound_bonus) if(!victim || wounding_dmg < WOUND_MINIMUM_DAMAGE) diff --git a/code/game/atom_defense.dm b/code/game/atom_defense.dm index 1ed6dc4cc5a..90533d05f62 100644 --- a/code/game/atom_defense.dm +++ b/code/game/atom_defense.dm @@ -51,6 +51,13 @@ if(atom_integrity == new_value) return atom_integrity = new_value + on_update_integrity(old_value, new_value) + return new_value + +/// Handle updates to your atom's integrity +/atom/proc/on_update_integrity(old_value, new_value) + SHOULD_NOT_SLEEP(TRUE) + SHOULD_CALL_PARENT(TRUE) SEND_SIGNAL(src, COMSIG_ATOM_INTEGRITY_CHANGED, old_value, new_value) /// This mostly exists to keep atom_integrity private. Might be useful in the future. @@ -58,6 +65,11 @@ SHOULD_BE_PURE(TRUE) return atom_integrity +/// Similar to get_integrity, but returns the percentage as [0-1] instead. +/atom/proc/get_integrity_percentage() + SHOULD_BE_PURE(TRUE) + return round(atom_integrity / max_integrity, 0.01) + ///returns the damage value of the attack after processing the atom's various armor protections /atom/proc/run_atom_armor(damage_amount, damage_type, damage_flag = 0, attack_dir, armour_penetration = 0) if(!uses_integrity) diff --git a/code/game/atoms.dm b/code/game/atoms.dm index d8ce2fb9751..aafeb699ea7 100644 --- a/code/game/atoms.dm +++ b/code/game/atoms.dm @@ -683,7 +683,7 @@ . += "It contains [round(reagents.total_volume, 0.01)] units of various reagents[user_sees_reagents ? ":" : "."]" if(user_sees_reagents) //Show each individual reagent for detailed examination for(var/datum/reagent/current_reagent as anything in reagents.reagent_list) - . += "• [FLOOR(current_reagent.volume, CHEMICAL_QUANTISATION_LEVEL)] units of [current_reagent.name]" + . += "• [round(current_reagent.volume, 0.01)] units of [current_reagent.name]" if(reagents.is_reacting) . += span_warning("It is currently reacting!") . += span_notice("The solution's pH is [round(reagents.ph, 0.01)] and has a temperature of [reagents.chem_temp]K.") diff --git a/code/game/atoms_movable.dm b/code/game/atoms_movable.dm index 41172ff552d..53b248fde38 100644 --- a/code/game/atoms_movable.dm +++ b/code/game/atoms_movable.dm @@ -18,6 +18,8 @@ var/initial_language_holder = /datum/language_holder /// Holds all languages this mob can speak and understand VAR_PRIVATE/datum/language_holder/language_holder + /// The list of factions this atom belongs to + var/list/faction var/verb_say = "says" var/verb_ask = "asks" @@ -1656,3 +1658,20 @@ */ /atom/movable/proc/keybind_face_direction(direction) setDir(direction) + +/** + * Check if the other atom/movable has any factions the same as us. Defined at the atom/movable level so it can be defined for just about anything. + * + * If exact match is set, then all our factions must match exactly + */ +/atom/movable/proc/faction_check_atom(atom/movable/target, exact_match) + if(!exact_match) + return faction_check(faction, target.faction, FALSE) + + var/list/faction_src = LAZYCOPY(faction) + var/list/faction_target = LAZYCOPY(target.faction) + if(!("[REF(src)]" in faction_target)) //if they don't have our ref faction, remove it from our factions list. + faction_src -= "[REF(src)]" //if we don't do this, we'll never have an exact match. + if(!("[REF(target)]" in faction_src)) + faction_target -= "[REF(target)]" //same thing here. + return faction_check(faction_src, faction_target, TRUE) diff --git a/code/game/communications.dm b/code/game/communications.dm index 7b2da607828..41867376684 100644 --- a/code/game/communications.dm +++ b/code/game/communications.dm @@ -141,6 +141,7 @@ GLOBAL_LIST_INIT(reverseradiochannels, list( )) /datum/radio_frequency + /// The frequency of this radio frequency. Of course. var/frequency /// List of filters -> list of devices var/list/list/datum/weakref/devices = list() @@ -189,6 +190,7 @@ GLOBAL_LIST_INIT(reverseradiochannels, list( device.receive_signal(signal) CHECK_TICK +/// Handles adding a listener to the radio frequency. /datum/radio_frequency/proc/add_listener(obj/device, filter as text|null) if (!filter) filter = "_default" @@ -201,6 +203,7 @@ GLOBAL_LIST_INIT(reverseradiochannels, list( devices[filter] = devices_line = list() devices_line += new_listener +/// Handles removing a listener from this radio frequency. /datum/radio_frequency/proc/remove_listener(obj/device) for(var/devices_filter in devices) var/list/devices_line = devices[devices_filter] @@ -210,15 +213,27 @@ GLOBAL_LIST_INIT(reverseradiochannels, list( if(!devices_line.len) devices -= devices_filter +/** + * Proc for reacting to a received `/datum/signal`. To be implemented as needed, + * does nothing by default. + */ /obj/proc/receive_signal(datum/signal/signal) set waitfor = FALSE return /datum/signal + /// The source of this signal. var/obj/source + /// The frequency on which this signal was emitted. var/frequency = 0 + /// The method through which this signal was transmitted. + /// See all of the `TRANSMISSION_X` in `code/__DEFINES/radio.dm` for + /// all of the possible options. var/transmission_method + /// The data carried through this signal. Defaults to `null`, otherwise it's + /// an associative list of (string, any). var/list/data + /// Logging data, used for logging purposes. Makes sense, right? var/logging_data /datum/signal/New(data, transmission_method = TRANSMISSION_RADIO, logging_data = null) diff --git a/code/game/gamemodes/dynamic/dynamic.dm b/code/game/gamemodes/dynamic/dynamic.dm index ce64f200458..96674292430 100644 --- a/code/game/gamemodes/dynamic/dynamic.dm +++ b/code/game/gamemodes/dynamic/dynamic.dm @@ -426,6 +426,24 @@ GLOBAL_LIST_EMPTY(dynamic_forced_rulesets) generate_budgets() set_cooldowns() log_dynamic("Dynamic Mode initialized with a Threat Level of... [threat_level]! ([round_start_budget] round start budget)") + SSblackbox.record_feedback( + "associative", + "dynamic_threat", + 1, + list( + "server_name" = CONFIG_GET(string/serversqlname), + "forced_threat_level" = GLOB.dynamic_forced_threat_level, + "threat_level" = threat_level, + "round_start_budget" = round_start_budget, + "parameters" = list( + "threat_curve_centre" = threat_curve_centre, + "threat_curve_width" = threat_curve_width, + "forced_extended" = GLOB.dynamic_forced_extended, + "no_stacking" = GLOB.dynamic_no_stacking, + "stacking_limit" = GLOB.dynamic_stacking_limit, + ), + ), + ) return TRUE /datum/game_mode/dynamic/proc/setup_shown_threat() diff --git a/code/game/gamemodes/dynamic/dynamic_rulesets_midround.dm b/code/game/gamemodes/dynamic/dynamic_rulesets_midround.dm index 80fcbc54db8..d30f3ffef76 100644 --- a/code/game/gamemodes/dynamic/dynamic_rulesets_midround.dm +++ b/code/game/gamemodes/dynamic/dynamic_rulesets_midround.dm @@ -595,7 +595,7 @@ var/datum/mind/player_mind = new /datum/mind(applicant.key) player_mind.active = TRUE - var/mob/living/simple_animal/hostile/space_dragon/S = new (pick(spawn_locs)) + var/mob/living/basic/space_dragon/S = new (pick(spawn_locs)) player_mind.transfer_to(S) player_mind.add_antag_datum(/datum/antagonist/space_dragon) diff --git a/code/game/machinery/_machinery.dm b/code/game/machinery/_machinery.dm index 494f1cca77e..710b5c7ec09 100644 --- a/code/game/machinery/_machinery.dm +++ b/code/game/machinery/_machinery.dm @@ -681,10 +681,25 @@ /obj/machinery/attack_paw(mob/living/user, list/modifiers) if(!user.combat_mode) return attack_hand(user) + user.changeNext_move(CLICK_CD_MELEE) user.do_attack_animation(src, ATTACK_EFFECT_PUNCH) - var/damage = take_damage(4, BRUTE, MELEE, 1) - user.visible_message(span_danger("[user] smashes [src] with [user.p_their()] paws[damage ? "." : ", without leaving a mark!"]"), null, null, COMBAT_MESSAGE_RANGE) + var/damage = take_damage(damage_amount = 4, damage_type = BRUTE, damage_flag = MELEE, sound_effect = TRUE, attack_dir = get_dir(user, src)) + + var/hit_with_what_noun = "paws" + var/obj/item/bodypart/arm/arm = user.get_active_hand() + if(!isnull(arm)) + hit_with_what_noun = arm.appendage_noun // hit with "their hand" + if(user.usable_hands > 1) + hit_with_what_noun += plural_s(hit_with_what_noun) // hit with "their hands" + + user.visible_message( + span_danger("[user] smashes [src] with [user.p_their()] [hit_with_what_noun][damage ? "." : ", without leaving a mark!"]"), + span_danger("You smash [src] with your [hit_with_what_noun][damage ? "." : ", without leaving a mark!"]"), + span_hear("You hear a [damage ? "smash" : "thud"]."), + COMBAT_MESSAGE_RANGE, + ) + return TRUE /obj/machinery/attack_hulk(mob/living/carbon/user) . = ..() @@ -739,7 +754,7 @@ return update_last_used(user) -/obj/machinery/tool_act(mob/living/user, obj/item/tool, tool_type) +/obj/machinery/tool_act(mob/living/user, obj/item/tool, tool_type, is_right_clicking) if(SEND_SIGNAL(user, COMSIG_TRY_USE_MACHINE, src) & COMPONENT_CANT_USE_MACHINE_TOOLS) return TOOL_ACT_MELEE_CHAIN_BLOCKING . = ..() diff --git a/code/game/machinery/porta_turret/portable_turret.dm b/code/game/machinery/porta_turret/portable_turret.dm index 701d6222369..cacecb6a684 100644 --- a/code/game/machinery/porta_turret/portable_turret.dm +++ b/code/game/machinery/porta_turret/portable_turret.dm @@ -40,6 +40,8 @@ DEFINE_BITFIELD(turret_flags, list( armor_type = /datum/armor/machinery_porta_turret base_icon_state = "standard" blocks_emissive = EMISSIVE_BLOCK_UNIQUE + // Same faction mobs will never be shot at, no matter the other settings + faction = list(FACTION_TURRET) ///if TRUE this will cause the turret to stop working if the stored_gun var is null in process() var/uses_stored = TRUE @@ -89,8 +91,6 @@ DEFINE_BITFIELD(turret_flags, list( var/on = TRUE /// Determines if our projectiles hit our faction var/ignore_faction = FALSE - /// Same faction mobs will never be shot at, no matter the other settings - var/list/faction = list(FACTION_TURRET) /// The spark system, used for generating... sparks? var/datum/effect_system/spark_spread/spark_system /// The turret will try to shoot from a turf in that direction when in a wall diff --git a/code/game/machinery/telecomms/broadcasting.dm b/code/game/machinery/telecomms/broadcasting.dm index 2ba6856ce1f..97ecd19e470 100644 --- a/code/game/machinery/telecomms/broadcasting.dm +++ b/code/game/machinery/telecomms/broadcasting.dm @@ -1,67 +1,26 @@ -/* - - Here is the big, bad function that broadcasts a message given the appropriate - parameters. - - @param M: - Reference to the mob/speaker, stored in signal.data["mob"] - - @param vmask: - Boolean value if the mob is "hiding" its identity via voice mask, stored in - signal.data["vmask"] - - @param vmessage: - If specified, will display this as the message; such as "chimpering" - for monkeys if the mob is not understood. Stored in signal.data["vmessage"]. - - @param radio: - Reference to the radio broadcasting the message, stored in signal.data["radio"] - - @param message: - The actual string message to display to mobs who understood mob M. Stored in - signal.data["message"] - - @param name: - The name to display when a mob receives the message. signal.data["name"] - - @param job: - The name job to display for the AI when it receives the message. signal.data["job"] - - @param realname: - The "real" name associated with the mob. signal.data["realname"] - - @param vname: - If specified, will use this name when mob M is not understood. signal.data["vname"] - - @param data: - If specified: - 1 -- Will only broadcast to intercoms - 2 -- Will only broadcast to intercoms and station-bounced radios - 3 -- Broadcast to syndicate frequency - 4 -- AI can't track down this person. Useful for imitation broadcasts where you can't find the actual mob - - @param compression: - If 0, the signal is audible - If nonzero, the signal may be partially inaudible or just complete gibberish. - - @param level: - The list of Z levels that the sending radio is broadcasting to. Having 0 in the list broadcasts on all levels - - @param freq - The frequency of the signal - -**/ - // Subtype of /datum/signal with additional processing information. /datum/signal/subspace transmission_method = TRANSMISSION_SUBSPACE + /// The type of server this signal is meant to be relayed to. + /// Not exclusive, the bus will usually try to send it through + /// more signals, but for that look for + /// `/obj/machinery/telecomms/bus/receive_information()` var/server_type = /obj/machinery/telecomms/server + /// The signal that was the origin of this one, in case it was a copy. var/datum/signal/subspace/original + /// The levels on which this signal can be received. Generally set by + /// a broadcaster, a relay or a message server. + /// If this list contains `0`, then it will be receivable on every single + /// z-level. var/list/levels /datum/signal/subspace/New(data) src.data = data || list() +/** + * Handles creating a new subspace signal that's a hard copy of this one, linked + * to this current signal via the `original` value, so that it can be traced back. + */ /datum/signal/subspace/proc/copy() var/datum/signal/subspace/copy = new copy.original = src @@ -73,18 +32,26 @@ copy.data = data.Copy() return copy +/** + * Handles marking the current signal, as well as its original signal, + * and their original signals (recursively) as done, in their `data["done"]`. + */ /datum/signal/subspace/proc/mark_done() var/datum/signal/subspace/current = src while (current) current.data["done"] = TRUE current = current.original +/** + * Handles sending this signal to every available receiver and mainframe. + */ /datum/signal/subspace/proc/send_to_receivers() - for(var/obj/machinery/telecomms/receiver/R in GLOB.telecomms_list) - R.receive_signal(src) - for(var/obj/machinery/telecomms/allinone/R in GLOB.telecomms_list) - R.receive_signal(src) + for(var/obj/machinery/telecomms/receiver/receiver in GLOB.telecomms_list) + receiver.receive_signal(src) + for(var/obj/machinery/telecomms/allinone/all_in_one_receiver in GLOB.telecomms_list) + all_in_one_receiver.receive_signal(src) +/// Handles broadcasting this signal out, to be implemented by subtypes. /datum/signal/subspace/proc/broadcast() set waitfor = FALSE @@ -92,9 +59,14 @@ // Despite "subspace" in the name, these transmissions can also be RADIO // (intercoms and SBRs) or SUPERSPACE (CentCom). /datum/signal/subspace/vocal + /// The virtualspeaker associated with this vocal transmission. var/atom/movable/virtualspeaker/virt + /// The language this vocal transmission was sent in. var/datum/language/language +#define COMPRESSION_VOCAL_SIGNAL_MIN 35 +#define COMPRESSION_VOCAL_SIGNAL_MAX 65 + /datum/signal/subspace/vocal/New( obj/source, // the originating radio frequency, // the frequency the signal is taking place on @@ -113,13 +85,16 @@ "name" = speaker.name, "job" = speaker.job, "message" = message, - "compression" = rand(35, 65), + "compression" = rand(COMPRESSION_VOCAL_SIGNAL_MIN, COMPRESSION_VOCAL_SIGNAL_MAX), "language" = lang_instance.name, "spans" = spans, "mods" = message_mods ) levels = SSmapping.get_connected_levels(get_turf(source)) +#undef COMPRESSION_VOCAL_SIGNAL_MIN +#undef COMPRESSION_VOCAL_SIGNAL_MAX + /datum/signal/subspace/vocal/copy() var/datum/signal/subspace/vocal/copy = new(source, frequency, virt, language) copy.original = src @@ -127,6 +102,10 @@ copy.levels = levels return copy +/// Past this amount of compression, the resulting gibberish will actually +/// replace characters, making it even harder to understand. +#define COMPRESSION_REPLACE_CHARACTER_THRESHOLD 30 + /// This is the meat function for making radios hear vocal transmissions. /datum/signal/subspace/vocal/broadcast() set waitfor = FALSE @@ -137,7 +116,7 @@ return var/compression = data["compression"] if(compression > 0) - message = Gibberish(message, compression >= 30) + message = Gibberish(message, compression >= COMPRESSION_REPLACE_CHARACTER_THRESHOLD) var/list/signal_reaches_every_z_level = levels @@ -206,8 +185,8 @@ var/spans_part = "" if(length(spans)) spans_part = "(spans:" - for(var/S in spans) - spans_part = "[spans_part] [S]" + for(var/span in spans) + spans_part = "[spans_part] [span]" spans_part = "[spans_part] ) " var/lang_name = data["language"] @@ -220,4 +199,6 @@ else log_telecomms("[virt.source] [log_text] [loc_name(get_turf(virt.source))]") - QDEL_IN(virt, 50) // Make extra sure the virtualspeaker gets qdeleted + QDEL_IN(virt, 5 SECONDS) // Make extra sure the virtualspeaker gets qdeleted + +#undef COMPRESSION_REPLACE_CHARACTER_THRESHOLD diff --git a/code/game/machinery/telecomms/computers/logbrowser.dm b/code/game/machinery/telecomms/computers/logbrowser.dm index b258a8d6f6e..e202a508ecf 100644 --- a/code/game/machinery/telecomms/computers/logbrowser.dm +++ b/code/game/machinery/telecomms/computers/logbrowser.dm @@ -41,7 +41,7 @@ // Send selected server data var/list/server_out = list() server_out["name"] = SelectedServer.name - server_out["traffic"] = SelectedServer.totaltraffic + server_out["traffic"] = SelectedServer.total_traffic // Get the messages on this server var/list/packets = list() for(var/datum/comm_log_entry/packet in SelectedServer.log_entries) diff --git a/code/game/machinery/telecomms/computers/message.dm b/code/game/machinery/telecomms/computers/message.dm index e2a669804a1..ab2a3f8cefc 100644 --- a/code/game/machinery/telecomms/computers/message.dm +++ b/code/game/machinery/telecomms/computers/message.dm @@ -20,13 +20,16 @@ var/obj/machinery/telecomms/message_server/linkedServer = null /// Sparks effect - For emag var/datum/effect_system/spark_spread/spark_system - /// Computer properties - var/screen = MSG_MON_SCREEN_MAIN // 0 = Main menu, 1 = Message Logs, 2 = Hacked screen, 3 = Custom Message - var/message = "System bootup complete. Please select an option." // The message that shows on the main menu. - var/auth = FALSE // Are they authenticated? - /// Error, Success & Notice messages + /// Computer properties. + /// 0 = Main menu, 1 = Message Logs, 2 = Hacked screen, 3 = Custom Message + var/screen = MSG_MON_SCREEN_MAIN + /// The message that shows on the main menu. + var/message = "System bootup complete. Please select an option." + /// Error message to display in the interface. var/error_message = "" + /// Notice message to display in the interface. var/notice_message = "" + /// Success message to display in the interface. var/success_message = "" /// Decrypt password var/password = "" @@ -89,7 +92,7 @@ "error_message" = error_message, "notice_message" = notice_message, "success_message" = success_message, - "auth" = auth, + "auth" = authenticated, "server_status" = !LINKED_SERVER_NONRESPONSIVE, ) @@ -109,7 +112,7 @@ if(MSG_MON_SCREEN_REQUEST_LOGS) var/list/request_list = list() for(var/datum/data_rc_msg/rc in linkedServer.rc_msgs) - request_list += list(list("ref" = REF(rc), "message" = rc.message, "stamp" = rc.stamp, "id_auth" = rc.id_auth, "departament" = rc.send_dpt)) + request_list += list(list("ref" = REF(rc), "message" = rc.message, "stamp" = rc.stamp, "id_auth" = rc.id_auth, "departament" = rc.sender_department)) data["requests"] = request_list return data @@ -126,15 +129,15 @@ if("auth") var/authPass = params["auth_password"] - if(auth) - auth = FALSE + if(authenticated) + authenticated = FALSE return TRUE if(linkedServer.decryptkey != authPass) error_message = "ALERT: Incorrect decryption key!" return TRUE - auth = TRUE + authenticated = TRUE success_message = "YOU SUCCESFULLY LOGGED IN!" return TRUE @@ -246,14 +249,14 @@ linkedServer.receive_information(signal, null) usr.log_message("(Tablet: [name] | [usr.real_name]) sent \"[message]\" to [signal.format_target()]", LOG_PDA) return TRUE - // Malfunction AI and cyborgs can hack console. This will auth console, but you need to wait password selection + // Malfunction AI and cyborgs can hack console. This will authenticate the console, but you need to wait password selection if("hack") var/time = 10 SECONDS * length(linkedServer.decryptkey) addtimer(CALLBACK(src, PROC_REF(unemag_console)), time) screen = MSG_MON_SCREEN_HACKED error_message = "%$&(£: Critical %$$@ Error // !RestArting! - ?pLeaSe wAit!" linkedServer.toggled = FALSE - auth = TRUE + authenticated = TRUE return TRUE return TRUE @@ -284,6 +287,9 @@ else return INITIALIZE_HINT_LATELOAD +/** + * Handles printing the monitor key for a given server onto this piece of paper. + */ /obj/item/paper/monitorkey/proc/print(obj/machinery/telecomms/message_server/server) add_raw_text("

Daily Key Reset


The new message monitor key is [server.decryptkey].
Please keep this a secret and away from the clown.
If necessary, change the password to a more secure one.") add_overlay("paper_words") diff --git a/code/game/machinery/telecomms/machine_interactions.dm b/code/game/machinery/telecomms/machine_interactions.dm index f3d5f8d8352..f6fa498c3dd 100644 --- a/code/game/machinery/telecomms/machine_interactions.dm +++ b/code/game/machinery/telecomms/machine_interactions.dm @@ -1,15 +1,13 @@ - -/* - - All telecommunications interactions: - -*/ +// This file is separate from telecommunications.dm to isolate the implementation +// of basic interactions with the machines. /obj/machinery/telecomms - var/temp = "" // output message + /// The current temporary frequency used to add new filtered frequencies + /// options. var/tempfreq = FREQ_COMMON + /// The current mob operating the machine. var/mob/living/operator - ///Illegal frequencies that can't be listened to by telecommunication servers. + /// Illegal frequencies that can't be listened to by telecommunication servers. var/list/banned_frequencies = list( FREQ_SYNDICATE, FREQ_CENTCOM, @@ -19,7 +17,7 @@ FREQ_CTF_BLUE, ) -/obj/machinery/telecomms/attackby(obj/item/P, mob/user, params) +/obj/machinery/telecomms/attackby(obj/item/attacking_item, mob/user, params) var/icon_closed = initial(icon_state) var/icon_open = "[initial(icon_state)]_o" @@ -27,13 +25,13 @@ icon_closed = "[initial(icon_state)]_off" icon_open = "[initial(icon_state)]_o_off" - if(default_deconstruction_screwdriver(user, icon_open, icon_closed, P)) + if(default_deconstruction_screwdriver(user, icon_open, icon_closed, attacking_item)) return // Using a multitool lets you access the receiver's interface - else if(P.tool_behaviour == TOOL_MULTITOOL) + else if(attacking_item.tool_behaviour == TOOL_MULTITOOL) attack_hand(user) - else if(default_deconstruction_crowbar(P)) + else if(default_deconstruction_crowbar(attacking_item)) return else return ..() @@ -122,8 +120,8 @@ playsound(src, 'sound/machines/buzz-sigh.ogg', 50, TRUE) return else - for(var/obj/machinery/telecomms/T in links) - remove_link(T) + for(var/obj/machinery/telecomms/linked_machine in links) + remove_link(linked_machine) network = params["value"] links = list() operator.log_message("has changed the network for [src] to [network].", LOG_GAME) @@ -145,13 +143,13 @@ operator.log_message("removed frequency [params["value"]] for [src].", LOG_GAME) . = TRUE if("unlink") - var/obj/machinery/telecomms/T = links[text2num(params["value"])] - if(T) - . = remove_link(T, operator) + var/obj/machinery/telecomms/machine_to_unlink = links[text2num(params["value"])] + if(machine_to_unlink) + . = remove_link(machine_to_unlink, operator) if("link") if(heldmultitool) - var/obj/machinery/telecomms/T = heldmultitool.buffer - . = add_new_link(T, operator) + var/obj/machinery/telecomms/machine_to_link = heldmultitool.buffer + . = add_new_link(machine_to_link, operator) if("buffer") heldmultitool.set_buffer(src) . = TRUE @@ -162,7 +160,7 @@ add_act(action, params) . = TRUE -///adds new_connection to src's links list AND vice versa. also updates links_by_telecomms_type +/// Adds new_connection to src's links list AND vice versa. Also updates `links_by_telecomms_type`. /obj/machinery/telecomms/proc/add_new_link(obj/machinery/telecomms/new_connection, mob/user) if(!istype(new_connection) || new_connection == src) return FALSE @@ -180,7 +178,7 @@ user.log_message("linked [src] for [new_connection].", LOG_GAME) return TRUE -///removes old_connection from src's links list AND vice versa. also updates links_by_telecomms_type +/// Removes old_connection from src's links list AND vice versa. Also updates `links_by_telecomms_type`. /obj/machinery/telecomms/proc/remove_link(obj/machinery/telecomms/old_connection, mob/user) if(!istype(old_connection) || old_connection == src) return FALSE @@ -198,6 +196,11 @@ return TRUE +/** + * Wrapper for adding additional options to a machine's interface. + * + * Returns a list, or `null` if it wasn't implemented by the machine. + */ /obj/machinery/telecomms/proc/add_option() return @@ -214,7 +217,14 @@ data["receiving"] = receiving return data +/** + * Wrapper for adding another time of action for `ui_act()`, rather than + * having you override `ui_act` yourself. + * + * Returns `TRUE` if the action was handled, nothing if not. + */ /obj/machinery/telecomms/proc/add_act(action, params) + return /obj/machinery/telecomms/relay/add_act(action, params) switch(action) @@ -236,20 +246,19 @@ else change_frequency = 0 -// Returns a multitool from a user depending on their mobtype. - +/// Returns a multitool from a user depending on their mobtype. /obj/machinery/telecomms/proc/get_multitool(mob/user) - var/obj/item/multitool/P = null + var/obj/item/multitool/multitool = null // Let's double check if(!issilicon(user) && istype(user.get_active_held_item(), /obj/item/multitool)) - P = user.get_active_held_item() + multitool = user.get_active_held_item() else if(isAI(user)) var/mob/living/silicon/ai/U = user - P = U.aiMulti + multitool = U.aiMulti else if(iscyborg(user) && in_range(user, src)) if(istype(user.get_active_held_item(), /obj/item/multitool)) - P = user.get_active_held_item() - return P + multitool = user.get_active_held_item() + return multitool /obj/machinery/telecomms/proc/canAccess(mob/user) if(issilicon(user) || in_range(user, src)) diff --git a/code/game/machinery/telecomms/machines/allinone.dm b/code/game/machinery/telecomms/machines/allinone.dm index 8296e0d0bd9..22612118033 100644 --- a/code/game/machinery/telecomms/machines/allinone.dm +++ b/code/game/machinery/telecomms/machines/allinone.dm @@ -1,8 +1,7 @@ -/* - Basically just an empty shell for receiving and broadcasting radio messages. Not - very flexible, but it gets the job done. -*/ - +/** + * Basically just an empty shell for receiving and broadcasting radio messages. Not + * very flexible, but it gets the job done. + */ /obj/machinery/telecomms/allinone name = "telecommunications mainframe" icon_state = "comm_server" @@ -41,6 +40,6 @@ sleep(signal.data["slow"]) // simulate the network lag if necessary signal.broadcast() -/obj/machinery/telecomms/allinone/attackby(obj/item/P, mob/user, params) - if(P.tool_behaviour == TOOL_MULTITOOL) +/obj/machinery/telecomms/allinone/attackby(obj/item/attacking_item, mob/user, params) + if(attacking_item.tool_behaviour == TOOL_MULTITOOL) return attack_hand(user) diff --git a/code/game/machinery/telecomms/machines/broadcaster.dm b/code/game/machinery/telecomms/machines/broadcaster.dm index 56b53437e63..a3b4caecf39 100644 --- a/code/game/machinery/telecomms/machines/broadcaster.dm +++ b/code/game/machinery/telecomms/machines/broadcaster.dm @@ -1,13 +1,14 @@ -/* - The broadcaster sends processed messages to all radio devices in the game. They - do not have to be headsets; intercoms and station-bounced radios suffice. - - They receive their message from a server after the message has been logged. -*/ - -GLOBAL_LIST_EMPTY(recentmessages) // global list of recent messages broadcasted : used to circumvent massive radio spam -GLOBAL_VAR_INIT(message_delay, 0) // To make sure restarting the recentmessages list is kept in sync - +/// Global list of recent messages broadcasted : used to circumvent massive radio spam +GLOBAL_LIST_EMPTY(recent_messages) +/// Used to make sure restarting the recent_messages list is kept in sync. +GLOBAL_VAR_INIT(message_delay, FALSE) + +/** + * The broadcaster sends processed messages to all radio devices in the game. They + * do not have to be headsets; intercoms and station-bounced radios suffice. + * + * They receive their message from a server after the message has been logged. + */ /obj/machinery/telecomms/broadcaster name = "subspace broadcaster" icon_state = "broadcaster" @@ -18,15 +19,17 @@ GLOBAL_VAR_INIT(message_delay, 0) // To make sure restarting the recentmessages circuit = /obj/item/circuitboard/machine/telecomms/broadcaster /obj/machinery/telecomms/broadcaster/receive_information(datum/signal/subspace/signal, obj/machinery/telecomms/machine_from) - // Don't broadcast rejected signals if(!istype(signal)) return + + // Don't broadcast rejected signals if(signal.data["reject"]) return if(!signal.data["message"]) return + var/signal_message = "[signal.frequency]:[signal.data["message"]]:[signal.data["name"]]" - if(signal_message in GLOB.recentmessages) + if(signal_message in GLOB.recent_messages) return // Prevents massive radio spam @@ -35,11 +38,11 @@ GLOBAL_VAR_INIT(message_delay, 0) // To make sure restarting the recentmessages if(original && ("compression" in signal.data)) original.data["compression"] = signal.data["compression"] - var/turf/T = get_turf(src) - if (T) - signal.levels |= SSmapping.get_connected_levels(T) + var/turf/current_turf = get_turf(src) + if (current_turf) + signal.levels |= SSmapping.get_connected_levels(current_turf) - GLOB.recentmessages.Add(signal_message) + GLOB.recent_messages.Add(signal_message) if(signal.data["slow"] > 0) sleep(signal.data["slow"]) // simulate the network lag if necessary @@ -55,29 +58,31 @@ GLOBAL_VAR_INIT(message_delay, 0) // To make sure restarting the recentmessages use_power(idle_power_usage) +/** + * Simply resets the message delay and the recent messages list, to ensure that + * recent messages can be sent again. Is called on a one second timer after a + * delay is set, from `/obj/machinery/telecomms/broadcaster/receive_information()` + */ /proc/end_message_delay() GLOB.message_delay = FALSE - GLOB.recentmessages = list() + GLOB.recent_messages = list() /obj/machinery/telecomms/broadcaster/Destroy() // In case message_delay is left on 1, otherwise it won't reset the list and people can't say the same thing twice anymore. if(GLOB.message_delay) - GLOB.message_delay = 0 + GLOB.message_delay = FALSE return ..() - -//Preset Broadcasters +// Preset Broadcasters //--PRESET LEFT--// - /obj/machinery/telecomms/broadcaster/preset_left id = "Broadcaster A" network = "tcommsat" autolinkers = list("broadcasterA") //--PRESET RIGHT--// - /obj/machinery/telecomms/broadcaster/preset_right id = "Broadcaster B" network = "tcommsat" diff --git a/code/game/machinery/telecomms/machines/bus.dm b/code/game/machinery/telecomms/machines/bus.dm index 64a13ccbd71..8ac8297b612 100644 --- a/code/game/machinery/telecomms/machines/bus.dm +++ b/code/game/machinery/telecomms/machines/bus.dm @@ -1,13 +1,13 @@ -/* - The bus mainframe idles and waits for hubs to relay them signals. They act - as junctions for the network. - - They transfer uncompressed subspace packets to processor units, and then take - the processed packet to a server for logging. - - Link to a subspace hub if it can't send to a server. -*/ - +/** + * The bus mainframe idles and waits for hubs to relay them signals. They act + * as junctions for the network. + * + * They transfer uncompressed subspace packets to processor units, and then take + * the processed packet to a server for logging. + * + * Can be linked to a telecommunications hub or a broadcaster in the absence + * of a server, at the cost of some added latency. + */ /obj/machinery/telecomms/bus name = "bus mainframe" icon_state = "bus" @@ -17,7 +17,9 @@ idle_power_usage = BASE_MACHINE_IDLE_CONSUMPTION * 0.01 netspeed = 40 circuit = /obj/item/circuitboard/machine/telecomms/bus - var/change_frequency = 0 + /// The frequency this bus will use to override the received signal's frequency, + /// if not `NONE`. + var/change_frequency = NONE /obj/machinery/telecomms/bus/receive_information(datum/signal/subspace/signal, obj/machinery/telecomms/machine_from) if(!istype(signal) || !is_freq_listening(signal)) @@ -47,7 +49,7 @@ use_power(idle_power_usage) -//Preset Buses +// Preset Buses /obj/machinery/telecomms/bus/preset_one id = "Bus 1" @@ -75,6 +77,8 @@ /obj/machinery/telecomms/bus/preset_four/Initialize(mapload) . = ..() + // We want to include every freely-available frequency on this one, so they + // get processed quickly when used on-station. for(var/i = MIN_FREQ, i <= MAX_FREQ, i += 2) freq_listening |= i diff --git a/code/game/machinery/telecomms/machines/hub.dm b/code/game/machinery/telecomms/machines/hub.dm index e84f1571736..094180a6e70 100644 --- a/code/game/machinery/telecomms/machines/hub.dm +++ b/code/game/machinery/telecomms/machines/hub.dm @@ -1,13 +1,12 @@ -/* - The HUB idles until it receives information. It then passes on that information - depending on where it came from. - - This is the heart of the Telecommunications Network, sending information where it - is needed. It mainly receives information from long-distance Relays and then sends - that information to be processed. Afterwards it gets the uncompressed information - from Servers/Buses and sends that back to the relay, to then be broadcasted. -*/ - +/** + * The HUB idles until it receives information. It then passes on that information + * depending on where it came from. + * + * This is the heart of the Telecommunications Network, sending information where it + * is needed. It mainly receives information from long-distance Relays and then sends + * that information to be processed. Afterwards it gets the uncompressed information + * from Servers/Buses and sends that back to the relay, to then be broadcasted. + */ /obj/machinery/telecomms/hub name = "telecommunication hub" icon_state = "hub" @@ -53,12 +52,31 @@ QDEL_NULL(soundloop) return ..() -//Preset HUB +// Preset HUB /obj/machinery/telecomms/hub/preset id = "Hub" network = "tcommsat" - autolinkers = list("hub", "relay", "s_relay", "m_relay", "r_relay", "h_relay", "science", "medical", - "supply", "service", "common", "command", "engineering", "security", - "receiverA", "receiverB", "broadcasterA", "broadcasterB", "autorelay", "messaging") + autolinkers = list( + "hub", + "relay", + "s_relay", + "m_relay", + "r_relay", + "h_relay", + "science", + "medical", + "supply", + "service", + "common", + "command", + "engineering", + "security", + "receiverA", + "receiverB", + "broadcasterA", + "broadcasterB", + "autorelay", + "messaging", + ) diff --git a/code/game/machinery/telecomms/machines/message_server.dm b/code/game/machinery/telecomms/machines/message_server.dm index 02a146fac31..6faad6f5eab 100644 --- a/code/game/machinery/telecomms/machines/message_server.dm +++ b/code/game/machinery/telecomms/machines/message_server.dm @@ -1,17 +1,12 @@ -/* - The equivalent of the server, for PDA and request console messages. - Without it, PDA and request console messages cannot be transmitted. - PDAs require the rest of the telecomms setup, but request consoles only - require the message server. -*/ - // A decorational representation of SSblackbox, usually placed alongside the message server. Also contains a traitor theft item. /obj/machinery/blackbox_recorder + name = "Blackbox Recorder" icon = 'icons/obj/machines/telecomms.dmi' icon_state = "blackbox" - name = "Blackbox Recorder" density = TRUE armor_type = /datum/armor/machinery_blackbox_recorder + /// The object that's stored in the machine, which is to say, the blackbox itself. + /// When it hasn't already been stolen, of course. var/obj/item/stored /datum/armor/machinery_blackbox_recorder @@ -39,15 +34,15 @@ to_chat(user, span_warning("It seems that the blackbox is missing...")) return -/obj/machinery/blackbox_recorder/attackby(obj/item/I, mob/living/user, params) - if(istype(I, /obj/item/blackbox)) - if(HAS_TRAIT(I, TRAIT_NODROP) || !user.transferItemToLoc(I, src)) - to_chat(user, span_warning("[I] is stuck to your hand!")) +/obj/machinery/blackbox_recorder/attackby(obj/item/attacking_item, mob/living/user, params) + if(istype(attacking_item, /obj/item/blackbox)) + if(HAS_TRAIT(attacking_item, TRAIT_NODROP) || !user.transferItemToLoc(attacking_item, src)) + to_chat(user, span_warning("[attacking_item] is stuck to your hand!")) return - user.visible_message(span_notice("[user] clicks [I] into [src]!"), \ + user.visible_message(span_notice("[user] clicks [attacking_item] into [src]!"), \ span_notice("You press the device into [src], and it clicks into place. The tapes begin spinning again.")) playsound(src, 'sound/machines/click.ogg', 50, TRUE) - stored = I + stored = attacking_item update_appearance() return return ..() @@ -73,26 +68,41 @@ w_class = WEIGHT_CLASS_BULKY resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | ACID_PROOF -#define MESSAGE_SERVER_FUNCTIONING_MESSAGE "This is an automated message. The messaging system is functioning correctly." -// The message server itself. +/** + * The equivalent of the server, for PDA and request console messages. + * Without it, PDA and request console messages cannot be transmitted. + * PDAs require the rest of the telecomms setup, but request consoles only + * require the message server. + */ /obj/machinery/telecomms/message_server - icon_state = "message_server" name = "Messaging Server" desc = "A machine that processes and routes PDA and request console messages." + icon_state = "message_server" telecomms_type = /obj/machinery/telecomms/message_server density = TRUE circuit = /obj/item/circuitboard/machine/telecomms/message_server + /// A list of all the PDA messages that were intercepted and processed by + /// this messaging server. var/list/datum/data_tablet_msg/pda_msgs = list() + /// A list of all the Request Console messages that were intercepted and + /// processed by this messaging server. var/list/datum/data_rc_msg/rc_msgs = list() + /// The password of this messaging server. var/decryptkey = "password" - var/calibrating = 15 MINUTES //Init reads this and adds world.time, then becomes 0 when that time has passed and the machine works + /// Init reads this and adds world.time, then becomes 0 when that time has + /// passed and the machine works. + /// Basically, if it's not 0, it's calibrating and therefore non-functional. + var/calibrating = 15 MINUTES + + +#define MESSAGE_SERVER_FUNCTIONING_MESSAGE "This is an automated message. The messaging system is functioning correctly." /obj/machinery/telecomms/message_server/Initialize(mapload) . = ..() if (!decryptkey) - decryptkey = GenerateKey() + decryptkey = generate_key() if (calibrating) calibrating += world.time @@ -112,12 +122,16 @@ if(calibrating) . += span_warning("It's still calibrating.") -/obj/machinery/telecomms/message_server/proc/GenerateKey() - var/newKey - newKey += pick("the", "if", "of", "as", "in", "a", "you", "from", "to", "an", "too", "little", "snow", "dead", "drunk", "rosebud", "duck", "al", "le") - newKey += pick("diamond", "beer", "mushroom", "assistant", "clown", "captain", "twinkie", "security", "nuke", "small", "big", "escape", "yellow", "gloves", "monkey", "engine", "nuclear", "ai") - newKey += pick("1", "2", "3", "4", "5", "6", "7", "8", "9", "0") - return newKey +/** + * Handles generating a key for the message server, returning it. Doesn't assign + * it in this proc, you have to do so yourself. + */ +/obj/machinery/telecomms/message_server/proc/generate_key() + var/generated_key + generated_key += pick("the", "if", "of", "as", "in", "a", "you", "from", "to", "an", "too", "little", "snow", "dead", "drunk", "rosebud", "duck", "al", "le") + generated_key += pick("diamond", "beer", "mushroom", "assistant", "clown", "captain", "twinkie", "security", "nuke", "small", "big", "escape", "yellow", "gloves", "monkey", "engine", "nuclear", "ai") + generated_key += pick("1", "2", "3", "4", "5", "6", "7", "8", "9", "0") + return generated_key /obj/machinery/telecomms/message_server/process() . = ..() @@ -125,6 +139,8 @@ calibrating = 0 pda_msgs += new /datum/data_tablet_msg("System Administrator", "system", MESSAGE_SERVER_FUNCTIONING_MESSAGE) +#undef MESSAGE_SERVER_FUNCTIONING_MESSAGE + /obj/machinery/telecomms/message_server/receive_information(datum/signal/subspace/messaging/signal, obj/machinery/telecomms/machine_from) // can't log non-message signals if(!istype(signal) || !signal.data["message"] || !on || calibrating) @@ -136,8 +152,8 @@ var/datum/data_tablet_msg/log_message = new(PDAsignal.format_target(), PDAsignal.format_sender(), PDAsignal.format_message(), PDAsignal.format_photo_path()) pda_msgs += log_message else if(istype(signal, /datum/signal/subspace/messaging/rc)) - var/datum/data_rc_msg/msg = new(signal.data["rec_dpt"], signal.data["send_dpt"], signal.data["message"], signal.data["stamped"], signal.data["verified"], signal.data["priority"]) - if(signal.data["send_dpt"]) // don't log messages not from a department but allow them to work + var/datum/data_rc_msg/msg = new(signal.data["receiving_department"], signal.data["sender_department"], signal.data["message"], signal.data["stamped"], signal.data["verified"], signal.data["priority"]) + if(signal.data["sender_department"]) // don't log messages not from a department but allow them to work rc_msgs += msg signal.data["reject"] = FALSE @@ -151,6 +167,14 @@ if(calibrating) . += "message_server_calibrate" +// Preset messaging server +/obj/machinery/telecomms/message_server/preset + id = "Messaging Server" + network = "tcommsat" + autolinkers = list("messaging") + decryptkey = null //random + calibrating = 0 + // Root messaging signal datum /datum/signal/subspace/messaging @@ -160,8 +184,8 @@ /datum/signal/subspace/messaging/New(init_source, init_data) source = init_source data = init_data - var/turf/T = get_turf(source) - levels = SSmapping.get_connected_levels(T) + var/turf/origin_turf = get_turf(source) + levels = SSmapping.get_connected_levels(origin_turf) if(!("reject" in data)) data["reject"] = TRUE @@ -172,20 +196,26 @@ return copy // Tablet message signal datum +/// Returns a string representing the target of this message, formatted properly. /datum/signal/subspace/messaging/tablet_message/proc/format_target() if (data["everyone"]) return "Everyone" + var/datum/computer_file/program/messenger/target_app = data["targets"][1] var/obj/item/modular_computer/target = target_app.computer - return "[target.saved_identification] ([target.saved_job])" + return STRINGIFY_PDA_TARGET(target.saved_identification, target.saved_job) +/// Returns a string representing the sender of this message, formatted properly. /datum/signal/subspace/messaging/tablet_message/proc/format_sender() var/display_name = get_messenger_name(locate(data["ref"])) return display_name ? display_name : STRINGIFY_PDA_TARGET(data["fakename"], data["fakejob"]) +/// Returns the formatted message contained in this message. Use this to apply +/// any processing to it if it needs to be formatted in a specific way. /datum/signal/subspace/messaging/tablet_message/proc/format_message() return data["message"] +/// Returns the formatted photo path contained in this message, if there's one. /datum/signal/subspace/messaging/tablet_message/proc/format_photo_path() return data["photo"] @@ -201,13 +231,19 @@ if(ckey(console.department) == recipient_department || (data["ore_update"] && console.receive_ore_updates)) console.create_message(data) -// Log datums stored by the message server. +/// Log datums stored by the message server. /datum/data_tablet_msg + /// Who sent the message. var/sender = "Unspecified" + /// Who was targeted by the message. var/recipient = "Unspecified" - var/message = "Blank" // transferred message - var/picture_asset_key // attached photo path - var/automated = FALSE // automated message + /// The transfered message. + var/message = "Blank" + /// The attached photo path, if any. + var/picture_asset_key + /// Whether or not it's an automated message. Defaults to `FALSE`. + var/automated = FALSE + /datum/data_tablet_msg/New(param_rec, param_sender, param_message, param_photo) if(param_rec) @@ -219,19 +255,32 @@ if(param_photo) picture_asset_key = param_photo + +#define REQUEST_PRIORITY_NORMAL "Normal" +#define REQUEST_PRIORITY_HIGH "High" +#define REQUEST_PRIORITY_EXTREME "Extreme" +#define REQUEST_PRIORITY_UNDETERMINED "Undetermined" + + /datum/data_rc_msg - var/rec_dpt = "Unspecified" // receiving department - var/send_dpt = "Unspecified" // sending department + /// The department that sent the request. + var/sender_department = "Unspecified" + /// The department that was targeted by the request. + var/receiving_department = "Unspecified" + /// The message of the request. var/message = "Blank" + /// The stamp that authenticated this message, if any. var/stamp = "Unstamped" + /// The ID that authenticated this message, if any. var/id_auth = "Unauthenticated" - var/priority = "Normal" + /// The priority of this request. + var/priority = REQUEST_PRIORITY_NORMAL /datum/data_rc_msg/New(param_rec, param_sender, param_message, param_stamp, param_id_auth, param_priority) if(param_rec) - rec_dpt = param_rec + receiving_department = param_rec if(param_sender) - send_dpt = param_sender + sender_department = param_sender if(param_message) message = param_message if(param_stamp) @@ -241,19 +290,15 @@ if(param_priority) switch(param_priority) if(REQ_NORMAL_MESSAGE_PRIORITY) - priority = "Normal" + priority = REQUEST_PRIORITY_NORMAL if(REQ_HIGH_MESSAGE_PRIORITY) - priority = "High" + priority = REQUEST_PRIORITY_HIGH if(REQ_EXTREME_MESSAGE_PRIORITY) - priority = "Extreme" + priority = REQUEST_PRIORITY_EXTREME else - priority = "Undetermined" + priority = REQUEST_PRIORITY_UNDETERMINED -#undef MESSAGE_SERVER_FUNCTIONING_MESSAGE - -/obj/machinery/telecomms/message_server/preset - id = "Messaging Server" - network = "tcommsat" - autolinkers = list("messaging") - decryptkey = null //random - calibrating = 0 +#undef REQUEST_PRIORITY_NORMAL +#undef REQUEST_PRIORITY_HIGH +#undef REQUEST_PRIORITY_EXTREME +#undef REQUEST_PRIORITY_UNDETERMINED diff --git a/code/game/machinery/telecomms/machines/processor.dm b/code/game/machinery/telecomms/machines/processor.dm index 906635d67ab..00529450746 100644 --- a/code/game/machinery/telecomms/machines/processor.dm +++ b/code/game/machinery/telecomms/machines/processor.dm @@ -1,11 +1,10 @@ -/* - The processor is a very simple machine that decompresses subspace signals and - transfers them back to the original bus. It is essential in producing audible - data. - - Link to servers if bus is not present -*/ - +/** + * The processor is a very simple machine that decompresses subspace signals and + * transfers them back to the original bus. It is essential in producing audible + * data. + * + * They'll link to servers if bus is not present, with some delay added to it. + */ /obj/machinery/telecomms/processor name = "processor unit" icon_state = "processor" @@ -14,16 +13,22 @@ density = TRUE idle_power_usage = BASE_MACHINE_IDLE_CONSUMPTION * 0.01 circuit = /obj/item/circuitboard/machine/telecomms/processor - var/process_mode = 1 // 1 = Uncompress Signals, 0 = Compress Signals + /// Whether this processor is currently compressing the data, + /// or actually decompressing it. Defaults to `FALSE`. + var/compressing = FALSE + +#define COMPRESSION_AMOUNT_COMPRESSING 100 +#define COMPRESSION_AMOUNT_DECOMPRESSING 0 /obj/machinery/telecomms/processor/receive_information(datum/signal/subspace/signal, obj/machinery/telecomms/machine_from) if(!is_freq_listening(signal)) return - if (!process_mode) - signal.data["compression"] = 100 // even more compressed signal - else if (signal.data["compression"]) - signal.data["compression"] = 0 // uncompress subspace signal + if(compressing) + signal.data["compression"] = COMPRESSION_AMOUNT_COMPRESSING // We compress the signal even further. + // Otherwise we just fully decompress it if it was compressed to begin with. + else if(signal.data["compression"]) + signal.data["compression"] = COMPRESSION_AMOUNT_DECOMPRESSING if(istype(machine_from, /obj/machinery/telecomms/bus)) relay_direct_information(signal, machine_from) // send the signal back to the machine @@ -31,7 +36,10 @@ signal.data["slow"] += rand(5, 10) // slow the signal down relay_information(signal, signal.server_type) -//Preset Processors +#undef COMPRESSION_AMOUNT_COMPRESSING +#undef COMPRESSION_AMOUNT_DECOMPRESSING + +// Preset Processors /obj/machinery/telecomms/processor/preset_one id = "Processor 1" diff --git a/code/game/machinery/telecomms/machines/receiver.dm b/code/game/machinery/telecomms/machines/receiver.dm index c9c183c35ff..0c4b6d2a02d 100644 --- a/code/game/machinery/telecomms/machines/receiver.dm +++ b/code/game/machinery/telecomms/machines/receiver.dm @@ -1,11 +1,10 @@ -/* - The receiver idles and receives messages from subspace-compatible radio equipment; - primarily headsets. Then they just relay this information to all linked devices, - which would probably be network hubs. - - Link to Processor Units in case receiver can't send to bus units. -*/ - +/** + * The receiver idles and receives messages from subspace-compatible radio equipment, + * primarily headsets. Then they just relay this information to all linked devices, + * which would usually be through the telecommunications hub. + * + * Link to Processor Units in case receiver can't send to a telecommunication hub. + */ /obj/machinery/telecomms/receiver name = "subspace receiver" icon_state = "broadcast receiver" @@ -27,21 +26,27 @@ use_power(idle_power_usage) +/** + * Checks whether the signal can be received by this receiver or not, based on + * if it's in the signal's `levels`, or if there's a liked hub with a linked + * relay that can receive the signal for it. + * + * Returns `TRUE` if it can receive the signal, `FALSE` if not. + */ /obj/machinery/telecomms/receiver/proc/check_receive_level(datum/signal/subspace/signal) if (z in signal.levels) return TRUE - for(var/obj/machinery/telecomms/hub/H in links) - for(var/obj/machinery/telecomms/relay/R in H.links) - if(R.can_receive(signal) && (R.z in signal.levels)) + for(var/obj/machinery/telecomms/hub/linked_hub in links) + for(var/obj/machinery/telecomms/relay/linked_relay in linked_hub.links) + if(linked_relay.can_receive(signal) && (linked_relay.z in signal.levels)) return TRUE return FALSE -//Preset Receivers +// Preset Receivers //--PRESET LEFT--// - /obj/machinery/telecomms/receiver/preset_left id = "Receiver A" network = "tcommsat" @@ -50,16 +55,16 @@ //--PRESET RIGHT--// - /obj/machinery/telecomms/receiver/preset_right id = "Receiver B" network = "tcommsat" autolinkers = list("receiverB") // link to relay freq_listening = list(FREQ_COMMAND, FREQ_ENGINEERING, FREQ_SECURITY) - //Common and other radio frequencies for people to freely use /obj/machinery/telecomms/receiver/preset_right/Initialize(mapload) . = ..() + // Also add common and other freely-available radio frequencies for people + // to have access to. for(var/i = MIN_FREQ, i <= MAX_FREQ, i += 2) freq_listening |= i diff --git a/code/game/machinery/telecomms/machines/relay.dm b/code/game/machinery/telecomms/machines/relay.dm index d3a6ac9ee90..2173a519be4 100644 --- a/code/game/machinery/telecomms/machines/relay.dm +++ b/code/game/machinery/telecomms/machines/relay.dm @@ -1,11 +1,11 @@ -/* - The relay idles until it receives information. It then passes on that information - depending on where it came from. - - The relay is needed in order to send information pass Z levels. It must be linked - with a HUB, the only other machine that can send/receive pass Z levels. -*/ - +/** + * The relay idles until it receives information. It then passes on that information + * depending on where it came from. + * + * The relay is needed in order to send information to different Z levels. It + * must be linked with a hub, the only other machine that can send to/receive + * from other Z levels. + */ /obj/machinery/telecomms/relay name = "telecommunication relay" icon_state = "relay" @@ -14,10 +14,12 @@ density = TRUE idle_power_usage = BASE_MACHINE_IDLE_CONSUMPTION * 0.01 netspeed = 5 - long_range_link = 1 + long_range_link = TRUE circuit = /obj/item/circuitboard/machine/telecomms/relay - var/broadcasting = 1 - var/receiving = 1 + /// Can this relay broadcast signals to other Z levels? + var/broadcasting = TRUE + /// Can this relay receive signals from other Z levels? + var/receiving = TRUE /obj/machinery/telecomms/relay/receive_information(datum/signal/subspace/signal, obj/machinery/telecomms/machine_from) // Add our level and send it back @@ -25,33 +27,49 @@ if(can_send(signal) && relay_turf) // Relays send signals to all ZTRAIT_STATION z-levels if(SSmapping.level_trait(relay_turf.z, ZTRAIT_STATION)) - for(var/z in SSmapping.levels_by_trait(ZTRAIT_STATION)) - signal.levels |= SSmapping.get_connected_levels(z) + for(var/z_level in SSmapping.levels_by_trait(ZTRAIT_STATION)) + signal.levels |= SSmapping.get_connected_levels(z_level) else signal.levels |= SSmapping.get_connected_levels(relay_turf) use_power(idle_power_usage) -/// Checks to see if it can send/receive. -/obj/machinery/telecomms/relay/proc/can(datum/signal/signal) +/** + * Checks to see if the relay can send/receive the signal, by checking if it's + * on, and if it's listening to the frequency of the signal. + * + * Returns `TRUE` if it can listen to the signal, `FALSE` if not. + */ +/obj/machinery/telecomms/relay/proc/can_listen_to_signal(datum/signal/signal) if(!on) return FALSE if(!is_freq_listening(signal)) return FALSE return TRUE +/** + * Checks to see if the relay can send this signal, which requires it to have + * `broadcasting` set to `TRUE`. + * + * Returns `TRUE` if it can send the signal, `FALSE` if not. + */ /obj/machinery/telecomms/relay/proc/can_send(datum/signal/signal) - if(!can(signal)) + if(!can_listen_to_signal(signal)) return FALSE return broadcasting +/** + * Checks to see if the relay can receive this signal, which requires it to have + * `receiving` set to `TRUE`. + * + * Returns `TRUE` if it can receive the signal, `FALSE` if not. + */ /obj/machinery/telecomms/relay/proc/can_receive(datum/signal/signal) - if(!can(signal)) + if(!can_listen_to_signal(signal)) return FALSE return receiving -//Preset Relay - +// Preset Relays /obj/machinery/telecomms/relay/preset network = "tcommsat" @@ -78,7 +96,7 @@ toggled = FALSE autolinkers = list("r_relay") -//Generic preset relay +// Generic preset relay /obj/machinery/telecomms/relay/preset/auto hide = TRUE autolinkers = list("autorelay") diff --git a/code/game/machinery/telecomms/machines/server.dm b/code/game/machinery/telecomms/machines/server.dm index 4bcc2c70a73..fedcf519ff2 100644 --- a/code/game/machinery/telecomms/machines/server.dm +++ b/code/game/machinery/telecomms/machines/server.dm @@ -1,10 +1,11 @@ -/* - The server logs all traffic and signal data. Once it records the signal, it sends - it to the subspace broadcaster. - - Store a maximum of 100 logs and then deletes them. -*/ - +#define MAX_LOG_ENTRIES 400 + +/** + * The server logs all traffic and signal data. Once it records the signal, it + * sends it to the subspace broadcaster. + * + * Store a maximum of `MAX_LOG_ENTRIES` (400) log entries and then deletes them. + */ /obj/machinery/telecomms/server name = "telecommunication server" icon_state = "comm_server" @@ -13,8 +14,13 @@ density = TRUE idle_power_usage = BASE_MACHINE_IDLE_CONSUMPTION * 0.01 circuit = /obj/item/circuitboard/machine/telecomms/server + /// A list of previous entries on the network. It will not exceed + /// `MAX_LOG_ENTRIES` entries in length, flushing the oldest entries + /// automatically. var/list/log_entries = list() - var/totaltraffic = 0 // gigabytes (if > 1024, divide by 1024 -> terrabytes) + /// Total trafic, which is increased every time a signal is increased and + /// the current traffic is higher than 0. See `traffic` for more info. + var/total_traffic = 0 /obj/machinery/telecomms/server/receive_information(datum/signal/subspace/vocal/signal, obj/machinery/telecomms/machine_from) // can't log non-vocal signals @@ -22,10 +28,10 @@ return if(traffic > 0) - totaltraffic += traffic // add current traffic to total traffic + total_traffic += traffic // add current traffic to total traffic // Delete particularly old logs - if (log_entries.len >= 400) + if (log_entries.len >= MAX_LOG_ENTRIES) log_entries.Cut(1, 2) // Don't create a log if the frequency is banned from being logged @@ -39,7 +45,7 @@ // If the signal is still compressed, make the log entry gibberish var/compression = signal.data["compression"] - if(compression > 0) + if(compression > NONE) log.input_type = "Corrupt File" var/replace_characters = compression >= 20 ? TRUE : FALSE log.parameters["name"] = Gibberish(signal.data["name"], replace_characters) @@ -47,7 +53,7 @@ log.parameters["message"] = Gibberish(signal.data["message"], replace_characters) // Give the log a name and store it - var/identifier = num2text( rand(-1000,1000) + world.time ) + var/identifier = num2text(rand(-1000, 1000) + world.time) log.name = "data packet ([md5(identifier)])" log_entries.Add(log) @@ -57,11 +63,16 @@ use_power(idle_power_usage) -// Simple log entry datum +#undef MAX_LOG_ENTRIES + +/// Simple log entry datum for the telecommunication server /datum/comm_log_entry + /// Type of entry. var/input_type = "Speech File" + /// Name of the entry. var/name = "data packet (#)" - var/parameters = list() // copied from signal.data above + /// Parameters extracted from the signal. + var/parameters = list() // Preset Servers @@ -98,9 +109,9 @@ freq_listening = list() autolinkers = list("common") -//Common and other radio frequencies for people to freely use /obj/machinery/telecomms/server/presets/common/Initialize(mapload) . = ..() + // Common and other radio frequencies for people to freely use for(var/i = MIN_FREQ, i <= MAX_FREQ, i += 2) freq_listening |= i diff --git a/code/game/machinery/telecomms/telecomunications.dm b/code/game/machinery/telecomms/telecomunications.dm index 95d5ca581ca..b8d0414ad28 100644 --- a/code/game/machinery/telecomms/telecomunications.dm +++ b/code/game/machinery/telecomms/telecomunications.dm @@ -1,19 +1,11 @@ - -/* - Hello, friends, this is Doohl from sexylands. You may be wondering what this - monstrous code file is. Sit down, boys and girls, while I tell you the tale. - - - The telecom machines were designed to be compatible with any radio - signals, provided they use subspace transmission. Currently they are only used for - headsets, but they can eventually be outfitted for real COMPUTER networks. This - is just a skeleton, ladies and gentlemen. - - Look at radio.dm for the prequel to this code. -*/ - +/// A list of all of the `/obj/machinery/telecomms` (and subtypes) machines +/// that exist in the world currently. GLOBAL_LIST_EMPTY(telecomms_list) +/** + * The basic telecomms machinery type, implementing all of the logic that's + * shared between all of the telecomms machinery. + */ /obj/machinery/telecomms icon = 'icons/obj/machines/telecomms.dmi' critical_machine = TRUE @@ -40,15 +32,16 @@ GLOBAL_LIST_EMPTY(telecomms_list) // list of frequencies to tune into: if none, will listen to all var/list/freq_listening = list() + /// Is it actually active or not? var/on = TRUE - /// Is it toggled on + /// Is it toggled on, so is it /meant/ to be active? var/toggled = TRUE /// Can you link it across Z levels or on the otherside of the map? (Relay & Hub) var/long_range_link = FALSE /// Is it a hidden machine? var/hide = FALSE - ///Looping sounds for any servers + /// Looping sounds for any servers var/datum/looping_sound/server/soundloop /// relay signal to all linked machinery that are of type [filter]. If signal has been sent [amount] times, stop sending @@ -90,16 +83,20 @@ GLOBAL_LIST_EMPTY(telecomms_list) return send_count +/// Sends a signal directly to a machine. /obj/machinery/telecomms/proc/relay_direct_information(datum/signal/signal, obj/machinery/telecomms/machine) - // send signal directly to a machine machine.receive_information(signal, src) -///receive information from linked machinery +/// Receive information from linked machinery /obj/machinery/telecomms/proc/receive_information(datum/signal/signal, obj/machinery/telecomms/machine_from) return +/** + * Checks whether the machinery is listening to that signal. + * + * Returns `TRUE` if found, `FALSE` if not. + */ /obj/machinery/telecomms/proc/is_freq_listening(datum/signal/signal) - // return TRUE if found, FALSE if not found return signal && (!length(freq_listening) || (signal.frequency in freq_listening)) /obj/machinery/telecomms/Initialize(mapload) @@ -122,17 +119,17 @@ GLOBAL_LIST_EMPTY(telecomms_list) links = list() return ..() -/// Used in auto linking -/obj/machinery/telecomms/proc/add_automatic_link(obj/machinery/telecomms/T) +/// Handles the automatic linking of another machine to this one. +/obj/machinery/telecomms/proc/add_automatic_link(obj/machinery/telecomms/machine_to_link) var/turf/position = get_turf(src) - var/turf/T_position = get_turf(T) - if((position.z != T_position.z) && !(long_range_link && T.long_range_link)) + var/turf/T_position = get_turf(machine_to_link) + if((position.z != T_position.z) && !(long_range_link && machine_to_link.long_range_link)) return - if(src == T) + if(src == machine_to_link) return for(var/autolinker_id in autolinkers) - if(autolinker_id in T.autolinkers) - add_new_link(T) + if(autolinker_id in machine_to_link.autolinkers) + add_new_link(machine_to_link) return /obj/machinery/telecomms/update_icon_state() @@ -143,6 +140,11 @@ GLOBAL_LIST_EMPTY(telecomms_list) update_appearance() return ..() +/** + * Handles updating the power state of the machine, modifying its `on` + * variable based on if it's `toggled` and if it's either broken, has no power + * or it's EMP'd. Handles updating appearance based on that power change. + */ /obj/machinery/telecomms/proc/update_power() var/old_on = on if(toggled) @@ -167,8 +169,9 @@ GLOBAL_LIST_EMPTY(telecomms_list) return if(prob(100/severity) && !(machine_stat & EMPED)) set_machine_stat(machine_stat | EMPED) - var/duration = (300 * 10)/severity - addtimer(CALLBACK(src, PROC_REF(de_emp)), rand(duration - 20, duration + 20)) + var/duration = (300 SECONDS)/severity + addtimer(CALLBACK(src, PROC_REF(de_emp)), rand(duration - 2 SECONDS, duration + 2 SECONDS)) +/// Handles the machine stopping being affected by an EMP. /obj/machinery/telecomms/proc/de_emp() set_machine_stat(machine_stat & ~EMPED) diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm index c10c04a9fa1..a8aeab47614 100644 --- a/code/game/objects/items.dm +++ b/code/game/objects/items.dm @@ -520,7 +520,6 @@ return var/datum/fantasy_affix/affix = affixes[picked_affix_name] affixes.Remove(affix) - QDEL_LIST_ASSOC(affixes) //remove the rest, we didn't use them var/fantasy_quality = 0 if(affix.alignment & AFFIX_GOOD) fantasy_quality++ diff --git a/code/game/objects/items/devices/laserpointer.dm b/code/game/objects/items/devices/laserpointer.dm index f595d376c3b..fae8d3950fd 100644 --- a/code/game/objects/items/devices/laserpointer.dm +++ b/code/game/objects/items/devices/laserpointer.dm @@ -71,7 +71,7 @@ diode = null return TRUE -/obj/item/laser_pointer/tool_act(mob/living/user, obj/item/tool) +/obj/item/laser_pointer/tool_act(mob/living/user, obj/item/tool, tool_type, is_right_clicking) . = ..() if(isnull(crystal_lens) || !(tool.tool_behaviour == TOOL_WIRECUTTER || tool.tool_behaviour == TOOL_HEMOSTAT)) return diff --git a/code/game/objects/items/dna_probe.dm b/code/game/objects/items/dna_probe.dm index 4ea89d0a95e..6c9651a3142 100644 --- a/code/game/objects/items/dna_probe.dm +++ b/code/game/objects/items/dna_probe.dm @@ -135,7 +135,7 @@ to_chat(user, span_notice("You pull out the needle from [src] and flip the switch, and start injecting yourself with it.")) if(!do_after(user, CARP_MIX_DNA_TIMER)) return - var/mob/living/simple_animal/hostile/space_dragon/new_dragon = user.change_mob_type(/mob/living/simple_animal/hostile/space_dragon, location = loc, delete_old_mob = TRUE) + var/mob/living/basic/space_dragon/new_dragon = user.change_mob_type(/mob/living/basic/space_dragon, location = loc, delete_old_mob = TRUE) new_dragon.add_filter("anger_glow", 3, list("type" = "outline", "color" = "#ff330030", "size" = 5)) new_dragon.add_movespeed_modifier(/datum/movespeed_modifier/dragon_rage) priority_announce("A large organic energy flux has been recorded near of [station_name()], please stand-by.", "Lifesign Alert") diff --git a/code/game/objects/items/food/monkeycube.dm b/code/game/objects/items/food/monkeycube.dm index ffc9b63c62f..d61b05477de 100644 --- a/code/game/objects/items/food/monkeycube.dm +++ b/code/game/objects/items/food/monkeycube.dm @@ -8,7 +8,6 @@ foodtypes = MEAT | SUGAR food_flags = FOOD_FINGER_FOOD w_class = WEIGHT_CLASS_TINY - var/faction var/spawned_mob = /mob/living/carbon/human/species/monkey /obj/item/food/monkeycube/proc/Expand() 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 5ed7fcd4682..e52c5f8034c 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 @@ -343,7 +343,7 @@ if (!.) return FALSE var/mob/living/carbon/human/human_owner = owner - RegisterSignal(human_owner, COMSIG_HUMAN_MELEE_UNARMED_ATTACK, PROC_REF(on_punched)) + RegisterSignal(human_owner, COMSIG_LIVING_UNARMED_ATTACK, PROC_REF(on_punched)) human_owner.physiology.brute_mod *= brute_modifier for (var/obj/item/bodypart/arm/arm in human_owner.bodyparts) if (arm.limb_id != SPECIES_GOLEM) @@ -354,10 +354,10 @@ /datum/status_effect/golem/titanium/proc/on_punched(mob/living/puncher, atom/punchee, proximity) SIGNAL_HANDLER if (!proximity || !isliving(punchee)) - return + return NONE var/mob/living/victim = punchee if (victim.body_position == LYING_DOWN || (!(FACTION_MINING in victim.faction) && !(FACTION_BOSS in victim.faction))) - return + return NONE victim.apply_damage(mining_bonus, BRUTE) /// Make the targeted arm big and strong @@ -370,7 +370,7 @@ /datum/status_effect/golem/titanium/on_remove() var/mob/living/carbon/human/human_owner = owner - UnregisterSignal(human_owner, COMSIG_HUMAN_MELEE_UNARMED_ATTACK) + UnregisterSignal(human_owner, COMSIG_LIVING_UNARMED_ATTACK) human_owner.physiology.brute_mod /= brute_modifier for (var/obj/item/bodypart/arm/arm as anything in modified_arms) debuff_arm(arm) diff --git a/code/game/objects/items/storage/secure.dm b/code/game/objects/items/storage/secure.dm index ad4be8d6e40..0d845b5254e 100644 --- a/code/game/objects/items/storage/secure.dm +++ b/code/game/objects/items/storage/secure.dm @@ -40,7 +40,7 @@ . = ..() icon_state = "[initial(icon_state)][atom_storage?.locked ? "_locked" : null]" -/obj/item/storage/secure/tool_act(mob/living/user, obj/item/tool) +/obj/item/storage/secure/tool_act(mob/living/user, obj/item/tool, tool_type, is_right_clicking) if(can_hack_open && atom_storage.locked) return ..() else diff --git a/code/game/objects/items/tcg/tcg_machines.dm b/code/game/objects/items/tcg/tcg_machines.dm index a38bb8a9599..767592535f7 100644 --- a/code/game/objects/items/tcg/tcg_machines.dm +++ b/code/game/objects/items/tcg/tcg_machines.dm @@ -293,9 +293,9 @@ GLOBAL_LIST_EMPTY(tcgcard_machine_radial_choices) use_power = NO_POWER_USE ///Reference to the display panel generated by this button. - var/obj/effect/decal/trading_card_panel/display_panel_ref + var/obj/effect/trading_card_panel/display_panel_ref ///Typepath of the display panel generated. - var/display_panel_type = /obj/effect/decal/trading_card_panel + var/display_panel_type = /obj/effect/trading_card_panel ///Where the panel will be spawned in relation to the button on the X axis. var/panel_offset_x = 1 ///Where the panel will be spawned in relation to the button on the Y axis. @@ -306,10 +306,7 @@ GLOBAL_LIST_EMPTY(tcgcard_mana_bar_radial_choices) /obj/machinery/trading_card_button/Initialize(mapload) . = ..() - var/obj/effect/decal/trading_card_panel/new_panel = new display_panel_type(get_turf(src)) - new_panel.pixel_x = panel_offset_x - new_panel.pixel_y = panel_offset_y - display_panel_ref = new_panel + display_panel_ref = new display_panel_type(locate(x + panel_offset_x, y + panel_offset_y, z)) /obj/machinery/trading_card_button/Destroy() QDEL_NULL(display_panel_ref) @@ -367,8 +364,8 @@ GLOBAL_LIST_EMPTY(tcgcard_mana_bar_radial_choices) name = "life control panel" desc = "A set of buttons that lets you keep track of your life shards when playing Tactical Game Cards." icon_state = "health_buttons" - display_panel_type = /obj/effect/decal/trading_card_panel/health - panel_offset_x = -24 + display_panel_type = /obj/effect/trading_card_panel/health + panel_offset_x = -1 ///Global list containing all options used for the TGC health button. GLOBAL_LIST_EMPTY(tcgcard_health_bar_radial_choices) @@ -395,11 +392,12 @@ GLOBAL_LIST_EMPTY(tcgcard_health_bar_radial_choices) display_panel_ref.gems -= tgui_input_number(user, "Please input total damage", "Inflict damage", 1, display_panel_ref.gem_slots, 0) ///A display panel that renders a set of icons (in this case mana crystals), this is generated by /obj/machinery/trading_card_button and can be manipulated by the button which generates it. -/obj/effect/decal/trading_card_panel +/obj/effect/trading_card_panel name = "mana panel" icon = 'icons/obj/toys/tcgmisc_large.dmi' icon_state = "display_panel" pixel_x = -10 + anchored = TRUE ///How much "active" gems will appear var/gems = 1 @@ -428,11 +426,11 @@ GLOBAL_LIST_EMPTY(tcgcard_health_bar_radial_choices) ///The name of what this panel tracks, used in the description var/gem_title = "mana" -/obj/effect/decal/trading_card_panel/Initialize(mapload) +/obj/effect/trading_card_panel/Initialize(mapload) . = ..() update_icon(UPDATE_OVERLAYS) -/obj/effect/decal/trading_card_panel/update_overlays() +/obj/effect/trading_card_panel/update_overlays() . = ..() if(!gem_slots) return @@ -447,12 +445,12 @@ GLOBAL_LIST_EMPTY(tcgcard_health_bar_radial_choices) gem_overlay.pixel_w = (gem - 1) * individual_gem_offset_x + gem_bar_offset_w . += gem_overlay -/obj/effect/decal/trading_card_panel/examine(mob/user) +/obj/effect/trading_card_panel/examine(mob/user) . = ..() . += span_notice("It is currently showing [gems] out of [gem_slots] [gem_title].") ///A variant of the display panel for life shards, this one is set up to display two columns. -/obj/effect/decal/trading_card_panel/health +/obj/effect/trading_card_panel/health name = "life shard panel" pixel_x = 9 diff --git a/code/game/objects/structures/false_walls.dm b/code/game/objects/structures/false_walls.dm index 6ac17e1ae02..8cb4b487c67 100644 --- a/code/game/objects/structures/false_walls.dm +++ b/code/game/objects/structures/false_walls.dm @@ -84,7 +84,7 @@ qdel(src) return T -/obj/structure/falsewall/tool_act(mob/living/user, obj/item/tool) +/obj/structure/falsewall/tool_act(mob/living/user, obj/item/tool, tool_type, is_right_clicking) if(!opening) return ..() to_chat(user, span_warning("You must wait until the door has stopped moving!")) diff --git a/code/game/objects/structures/fluff.dm b/code/game/objects/structures/fluff.dm index 78085b37d55..15298367bc0 100644 --- a/code/game/objects/structures/fluff.dm +++ b/code/game/objects/structures/fluff.dm @@ -287,6 +287,7 @@ /obj/structure/fluff/broken_canister_frame name = "broken canister frame" + desc = "A torn apart canister. It looks like some metal can be salvaged with a wrench." icon_state = "broken_canister" anchored = FALSE density = TRUE diff --git a/code/game/objects/structures/spawner.dm b/code/game/objects/structures/spawner.dm index 2ad70bdbc84..b654e0d43f4 100644 --- a/code/game/objects/structures/spawner.dm +++ b/code/game/objects/structures/spawner.dm @@ -8,11 +8,12 @@ anchored = TRUE density = TRUE + faction = list(FACTION_HOSTILE) + var/max_mobs = 5 var/spawn_time = 30 SECONDS var/mob_types = list(/mob/living/basic/carp) var/spawn_text = "emerges from" - var/faction = list(FACTION_HOSTILE) var/spawner_type = /datum/component/spawner /// Is this spawner taggable with something? var/scanner_taggable = FALSE diff --git a/code/game/turfs/closed/walls.dm b/code/game/turfs/closed/walls.dm index f28c6b41f80..f8d411acee4 100644 --- a/code/game/turfs/closed/walls.dm +++ b/code/game/turfs/closed/walls.dm @@ -34,48 +34,63 @@ var/list/dent_decals -/turf/closed/wall/MouseDrop_T(mob/living/carbon/carbon_mob, mob/user) +/turf/closed/wall/MouseDrop_T(atom/dropping, mob/user, params) ..() - if(carbon_mob != user) + if(dropping != user) return - if(carbon_mob.is_leaning == TRUE) + if(!iscarbon(dropping) && !iscyborg(dropping)) return - if(carbon_mob.pulledby) + var/mob/living/leaner = dropping + if(leaner.incapacitated(IGNORE_RESTRAINTS) || leaner.stat != CONSCIOUS || HAS_TRAIT(leaner, TRAIT_NO_TRANSFORM)) return - if(!carbon_mob.density) + if(!leaner.density || leaner.pulledby || leaner.buckled || !(leaner.mobility_flags & MOBILITY_STAND)) return - var/turf/checked_turf = get_step(carbon_mob, REVERSE_DIR(carbon_mob.dir)) - if(checked_turf == src) - carbon_mob.start_leaning(src) - -/mob/living/carbon/proc/start_leaning(obj/wall) + if(HAS_TRAIT_FROM(leaner, TRAIT_UNDENSE, LEANING_TRAIT)) + return + var/turf/checked_turf = get_step(leaner, REVERSE_DIR(leaner.dir)) + if(checked_turf != src) + return + leaner.start_leaning(src) +/mob/living/proc/start_leaning(turf/closed/wall/wall) + var/new_y = base_pixel_y + pixel_y + var/new_x = base_pixel_x + pixel_x switch(dir) if(SOUTH) - pixel_y += LEANING_OFFSET + new_y += LEANING_OFFSET if(NORTH) - pixel_y += -LEANING_OFFSET + new_y -= LEANING_OFFSET if(WEST) - pixel_x += LEANING_OFFSET + new_x += LEANING_OFFSET if(EAST) - pixel_x += -LEANING_OFFSET - - ADD_TRAIT(src, TRAIT_UNDENSE, LEANING_TRAIT) - ADD_TRAIT(src, TRAIT_EXPANDED_FOV, LEANING_TRAIT) - visible_message(span_notice("[src] leans against \the [wall]!"), \ - span_notice("You lean against \the [wall]!")) - RegisterSignals(src, list(COMSIG_MOB_CLIENT_PRE_MOVE, COMSIG_HUMAN_DISARM_HIT, COMSIG_LIVING_GET_PULLED, COMSIG_MOVABLE_TELEPORTING, COMSIG_ATOM_DIR_CHANGE), PROC_REF(stop_leaning)) + new_x -= LEANING_OFFSET + + animate(src, 0.2 SECONDS, pixel_x = new_x, pixel_y = new_y) + add_traits(list(TRAIT_UNDENSE, TRAIT_EXPANDED_FOV), LEANING_TRAIT) + visible_message( + span_notice("[src] leans against [wall]."), + span_notice("You lean against [wall]."), + ) + RegisterSignals(src, list( + COMSIG_MOB_CLIENT_PRE_MOVE, + COMSIG_HUMAN_DISARM_HIT, + COMSIG_LIVING_GET_PULLED, + COMSIG_MOVABLE_TELEPORTING, + COMSIG_ATOM_DIR_CHANGE, + ), PROC_REF(stop_leaning)) update_fov() - is_leaning = TRUE -/mob/living/carbon/proc/stop_leaning() +/mob/living/proc/stop_leaning() SIGNAL_HANDLER - UnregisterSignal(src, list(COMSIG_MOB_CLIENT_PRE_MOVE, COMSIG_HUMAN_DISARM_HIT, COMSIG_LIVING_GET_PULLED, COMSIG_MOVABLE_TELEPORTING, COMSIG_ATOM_DIR_CHANGE)) - is_leaning = FALSE - pixel_y = base_pixel_y + body_position_pixel_x_offset - pixel_x = base_pixel_y + body_position_pixel_y_offset - REMOVE_TRAIT(src, TRAIT_UNDENSE, LEANING_TRAIT) - REMOVE_TRAIT(src, TRAIT_EXPANDED_FOV, LEANING_TRAIT) + UnregisterSignal(src, list( + COMSIG_MOB_CLIENT_PRE_MOVE, + COMSIG_HUMAN_DISARM_HIT, + COMSIG_LIVING_GET_PULLED, + COMSIG_MOVABLE_TELEPORTING, + COMSIG_ATOM_DIR_CHANGE, + )) + animate(src, 0.2 SECONDS, pixel_x = base_pixel_x, pixel_y = base_pixel_y) + remove_traits(list(TRAIT_UNDENSE, TRAIT_EXPANDED_FOV), LEANING_TRAIT) update_fov() /turf/closed/wall/Initialize(mapload) diff --git a/code/game/turfs/open/floor/plating.dm b/code/game/turfs/open/floor/plating.dm index eee4797887b..a38338010d4 100644 --- a/code/game/turfs/open/floor/plating.dm +++ b/code/game/turfs/open/floor/plating.dm @@ -177,7 +177,7 @@ ScrapeAway(flags = CHANGETURF_INHERIT_AIR) return TRUE -/turf/open/floor/plating/foam/tool_act(mob/living/user, obj/item/I, tool_type) +/turf/open/floor/plating/foam/tool_act(mob/living/user, obj/item/tool, tool_type, is_right_clicking) return //reinforced plating deconstruction states diff --git a/code/modules/antagonists/heretic/heretic_knowledge.dm b/code/modules/antagonists/heretic/heretic_knowledge.dm index 1f408698f3c..a885c24a6a4 100644 --- a/code/modules/antagonists/heretic/heretic_knowledge.dm +++ b/code/modules/antagonists/heretic/heretic_knowledge.dm @@ -177,9 +177,11 @@ var/obj/item/stack/sac_stack = sacrificed var/how_much_to_use = 0 for(var/requirement in required_atoms) - if(islist(requirement) && !is_type_in_list(sacrificed, requirement)) + // If it's not requirement type and type is not a list, skip over this check + if(!istype(sacrificed, requirement) && !islist(requirement)) continue - if(!istype(sacrificed, requirement)) + // If requirement *is* a list and the stack *is* in the list, skip over this check + if(islist(requirement) && !is_type_in_list(sacrificed, requirement)) continue how_much_to_use = min(required_atoms[requirement], sac_stack.amount) break diff --git a/code/modules/antagonists/heretic/knowledge/blade_lore.dm b/code/modules/antagonists/heretic/knowledge/blade_lore.dm index f2f3b156a2f..55102c12c79 100644 --- a/code/modules/antagonists/heretic/knowledge/blade_lore.dm +++ b/code/modules/antagonists/heretic/knowledge/blade_lore.dm @@ -32,13 +32,13 @@ /datum/heretic_knowledge/limited_amount/starting/base_blade name = "The Cutting Edge" desc = "Opens up the Path of Blades to you. \ - Allows you to transmute a knife with two bars of silver to create a Sundered Blade. \ + Allows you to transmute a knife with two bars of silver or titanium to create a Sundered Blade. \ You can create up to five at a time." gain_text = "Our great ancestors forged swords and practiced sparring on the eve of great battles." next_knowledge = list(/datum/heretic_knowledge/blade_grasp) required_atoms = list( /obj/item/knife = 1, - /obj/item/stack/sheet/mineral/silver = 2, + list(/obj/item/stack/sheet/mineral/silver, /obj/item/stack/sheet/mineral/titanium) = 2, ) result_atoms = list(/obj/item/melee/sickly_blade/dark) limit = 5 // It's the blade path, it's a given diff --git a/code/modules/antagonists/space_dragon/space_dragon.dm b/code/modules/antagonists/space_dragon/space_dragon.dm index 7c49bed6b95..574e458faca 100644 --- a/code/modules/antagonists/space_dragon/space_dragon.dm +++ b/code/modules/antagonists/space_dragon/space_dragon.dm @@ -157,6 +157,7 @@ if(objective_complete) return rifts_charged = 0 + ADD_TRAIT(owner.current, TRAIT_RIFT_FAILURE, REF(src)) owner.current.add_movespeed_modifier(/datum/movespeed_modifier/dragon_depression) riftTimer = -1 SEND_SOUND(owner.current, sound('sound/vehicles/rocketlaunch.ogg')) diff --git a/code/modules/antagonists/traitor/objectives/hack_comm_console.dm b/code/modules/antagonists/traitor/objectives/hack_comm_console.dm index 52e0397cc60..93323e4e15f 100644 --- a/code/modules/antagonists/traitor/objectives/hack_comm_console.dm +++ b/code/modules/antagonists/traitor/objectives/hack_comm_console.dm @@ -23,7 +23,7 @@ /datum/traitor_objective/hack_comm_console/generate_objective(datum/mind/generating_for, list/possible_duplicates) AddComponent(/datum/component/traitor_objective_mind_tracker, generating_for, \ - signals = list(COMSIG_HUMAN_EARLY_UNARMED_ATTACK = PROC_REF(on_unarmed_attack))) + signals = list(COMSIG_LIVING_UNARMED_ATTACK = PROC_REF(on_unarmed_attack))) RegisterSignal(SSdcs, COMSIG_GLOB_TRAITOR_OBJECTIVE_COMPLETED, PROC_REF(on_global_obj_completed)) return TRUE diff --git a/code/modules/atmospherics/machinery/air_alarm/_air_alarm.dm b/code/modules/atmospherics/machinery/air_alarm/_air_alarm.dm index e629c14e0fe..24d1e63e42a 100644 --- a/code/modules/atmospherics/machinery/air_alarm/_air_alarm.dm +++ b/code/modules/atmospherics/machinery/air_alarm/_air_alarm.dm @@ -287,6 +287,8 @@ GLOBAL_LIST_EMPTY_TYPED(air_alarms, /obj/machinery/airalarm) "refID" = REF(vent), "long_name" = sanitize(vent.name), "power" = vent.on, + "overclock" = vent.fan_overclocked, + "integrity" = vent.get_integrity_percentage(), "checks" = vent.pressure_checks, "excheck" = vent.pressure_checks & ATMOS_EXTERNAL_BOUND, "incheck" = vent.pressure_checks & ATMOS_INTERNAL_BOUND, @@ -356,6 +358,14 @@ GLOBAL_LIST_EMPTY_TYPED(air_alarms, /obj/machinery/airalarm) powering.on = !!params["val"] powering.atmos_conditions_changed() powering.update_appearance(UPDATE_ICON) + + if("overclock") + if(isnull(vent)) + return TRUE + vent.toggle_overclock() + vent.update_appearance(UPDATE_ICON) + return TRUE + if ("direction") if (isnull(vent)) return TRUE diff --git a/code/modules/atmospherics/machinery/components/unary_devices/vent_pump.dm b/code/modules/atmospherics/machinery/components/unary_devices/vent_pump.dm index 3422f3e3adf..25713e55e37 100644 --- a/code/modules/atmospherics/machinery/components/unary_devices/vent_pump.dm +++ b/code/modules/atmospherics/machinery/components/unary_devices/vent_pump.dm @@ -15,6 +15,8 @@ shift_underlay_only = FALSE pipe_state = "uvent" vent_movement = VENTCRAWL_ALLOWED | VENTCRAWL_CAN_SEE | VENTCRAWL_ENTRANCE_ALLOWED + // vents are more complex machinery and so are less resistant to damage + max_integrity = 100 ///Direction of pumping the gas (ATMOS_DIRECTION_RELEASING or ATMOS_DIRECTION_SIPHONING) var/pump_direction = ATMOS_DIRECTION_RELEASING @@ -34,6 +36,18 @@ ///area this vent is assigned to var/area/assigned_area + /// Is this vent currently overclocked, removing pressure limits but damaging the fan? + var/fan_overclocked = FALSE + + /// Rate of damage per atmos process to the fan when overclocked. Set to 0 to disable damage. + var/fan_damage_rate = 0.5 + + /// The cached string we show for examine that lets you know how fucked up the fan is. + var/examine_condition + + /// Datum for managing the overclock sound loop + var/datum/looping_sound/vent_pump_overclock/sound_loop + /obj/machinery/atmospherics/components/unary/vent_pump/Initialize(mapload) if(!id_tag) id_tag = assign_random_name() @@ -42,16 +56,44 @@ tool_screentips = string_assoc_nested_list(list( TOOL_MULTITOOL = list( SCREENTIP_CONTEXT_LMB = "Log to link later with air sensor", - ) + ), + TOOL_SCREWDRIVER = list( + SCREENTIP_CONTEXT_LMB = "Repair", + ), )) AddElement(/datum/element/contextual_screentip_tools, tool_screentips) . = ..() + sound_loop = new(src) assign_to_area() +/obj/machinery/atmospherics/components/unary/vent_pump/on_update_integrity(old_value, new_value) + . = ..() + var/condition_string + switch(get_integrity_percentage()) + if(1) + condition_string = "perfect" + if(0.75 to 0.99) + condition_string = "good" + if(0.50 to 0.74) + condition_string = "okay" + if(0.25 to 0.49) + condition_string = "bad" + else + condition_string = "terrible" + examine_condition = "The fan is in [condition_string] condition." + /obj/machinery/atmospherics/components/unary/vent_pump/examine(mob/user) . = ..() . += span_notice("You can link it with an air sensor using a multitool.") + if(fan_overclocked) + . += span_warning("It is currently overclocked causing it to take damage over time.") + + if(get_integrity() > 0) + . += span_notice(examine_condition) + else + . += span_warning("The fan is broken.") + /obj/machinery/atmospherics/components/unary/vent_pump/multitool_act(mob/living/user, obj/item/multitool/multi_tool) if(istype(multi_tool.buffer, /obj/machinery/air_sensor)) var/obj/machinery/air_sensor/sensor = multi_tool.buffer @@ -63,8 +105,33 @@ multi_tool.set_buffer(src) return TOOL_ACT_TOOLTYPE_SUCCESS +/obj/machinery/atmospherics/components/unary/vent_pump/screwdriver_act(mob/living/user, obj/item/tool) + var/time_to_repair = (10 SECONDS) * (1 - get_integrity_percentage()) + if(!time_to_repair) + return FALSE + + balloon_alert(user, "repairing vent...") + if(do_after(user, time_to_repair, src)) + balloon_alert(user, "vent repaired") + repair_damage(max_integrity) + + else + balloon_alert(user, "interrupted!") + return TOOL_ACT_TOOLTYPE_SUCCESS + +/obj/machinery/atmospherics/components/unary/vent_pump/atom_fix() + set_is_operational(TRUE) + update_appearance() + return ..() + +/obj/machinery/atmospherics/components/unary/vent_pump/atom_break(damage_flag) + set_is_operational(FALSE) + update_appearance() + return ..() + /obj/machinery/atmospherics/components/unary/vent_pump/Destroy() disconnect_from_area() + QDEL_NULL(sound_loop) var/area/vent_area = get_area(src) if(vent_area) @@ -107,6 +174,17 @@ . = ..() disconnect_from_area(area_to_unregister) +/obj/machinery/atmospherics/components/unary/vent_pump/update_overlays() + . = ..() + if(!powered()) + return + + if(get_integrity() <= 0) + . += mutable_appearance(icon, "broken") + + else if(fan_overclocked) + . += mutable_appearance(icon, "overclocked") + /obj/machinery/atmospherics/components/unary/vent_pump/update_icon_nopipes() cut_overlays() if(showpipe) @@ -144,6 +222,20 @@ else // pump_direction == SIPHONING icon_state = "vent_in" +/obj/machinery/atmospherics/components/unary/vent_pump/proc/toggle_overclock(from_break = FALSE) + fan_overclocked = !fan_overclocked + + if(from_break) + playsound(src, 'sound/machines/fan_break.ogg', 100) + fan_overclocked = FALSE + + if(fan_overclocked) + sound_loop.start() + else + sound_loop.stop() + + update_appearance() + /obj/machinery/atmospherics/components/unary/vent_pump/process_atmos() if(!is_operational) return @@ -154,6 +246,17 @@ var/turf/open/us = loc if(!istype(us)) return + + var/current_integrity = get_integrity() + if(fan_overclocked) + take_damage(fan_damage_rate, sound_effect=FALSE) + if(current_integrity == 0) + on = FALSE + set_is_operational(FALSE) + toggle_overclock(from_break = TRUE) + return + + var/percent_integrity = get_integrity_percentage() var/datum/gas_mixture/air_contents = airs[1] var/datum/gas_mixture/environment = us.return_air() var/environment_pressure = environment.return_pressure() @@ -168,9 +271,13 @@ if(pressure_delta > 0) if(air_contents.temperature > 0) - if(environment_pressure >= 50 * ONE_ATMOSPHERE) + if(!fan_overclocked && (environment_pressure >= 50 * ONE_ATMOSPHERE)) return FALSE + var/transfer_moles = (pressure_delta * environment.volume) / (air_contents.temperature * R_IDEAL_GAS_EQUATION) + if(!fan_overclocked && (percent_integrity < 1)) + transfer_moles *= percent_integrity + var/datum/gas_mixture/removed = air_contents.remove(transfer_moles) if(!removed || !removed.total_moles()) @@ -187,9 +294,12 @@ pressure_delta = min(pressure_delta, (internal_pressure_bound - air_contents.return_pressure())) if(pressure_delta > 0 && environment.temperature > 0) - if(air_contents.return_pressure() >= 50 * ONE_ATMOSPHERE) + if(!fan_overclocked && (air_contents.return_pressure() >= 50 * ONE_ATMOSPHERE)) return FALSE + var/transfer_moles = (pressure_delta * air_contents.volume) / (environment.temperature * R_IDEAL_GAS_EQUATION) + if(!fan_overclocked && (percent_integrity < 1)) + transfer_moles *= percent_integrity var/datum/gas_mixture/removed = loc.remove_air(transfer_moles) diff --git a/code/modules/capture_the_flag/ctf_equipment.dm b/code/modules/capture_the_flag/ctf_equipment.dm index 5ec412f9017..e822ae2dbb1 100644 --- a/code/modules/capture_the_flag/ctf_equipment.dm +++ b/code/modules/capture_the_flag/ctf_equipment.dm @@ -165,7 +165,7 @@ /obj/item/ammo_casing/energy/instakill projectile_type = /obj/projectile/beam/instakill - e_cost = 0 + e_cost = 0 // Not possible to use the macro select_name = "DESTROY" /obj/projectile/beam/instakill diff --git a/code/modules/capture_the_flag/ctf_game.dm b/code/modules/capture_the_flag/ctf_game.dm index 1f6c44c293a..bfebcc706ca 100644 --- a/code/modules/capture_the_flag/ctf_game.dm +++ b/code/modules/capture_the_flag/ctf_game.dm @@ -152,11 +152,13 @@ if(player_mob.dna.species.outfit_important_for_life) player_mob.set_species(/datum/species/human) - player_mob.AddComponent( \ - /datum/component/temporary_body, \ - old_mind = new_team_member.mob.mind, \ - old_body = new_team_member.mob.mind.current, \ - ) + var/datum/mind/new_member_mind = new_team_member.mob.mind + if(new_member_mind?.current) + player_mob.AddComponent( \ + /datum/component/temporary_body, \ + old_mind = new_member_mind, \ + old_body = new_member_mind.current, \ + ) player_mob.ckey = new_team_member.ckey if(isnull(ctf_player_component)) diff --git a/code/modules/cards/cardhand.dm b/code/modules/cards/cardhand.dm index 9dab4e65b58..ac14e17fea6 100644 --- a/code/modules/cards/cardhand.dm +++ b/code/modules/cards/cardhand.dm @@ -110,7 +110,7 @@ icon_state = null // we want an error icon to appear if this doesn't get qdel return - var/starting_card_pos = max(1, cards.len - CARDS_MAX_DISPLAY_LIMIT) // only display the top cards in the cardhand + var/starting_card_pos = max(0, cards.len - CARDS_MAX_DISPLAY_LIMIT) + 1 // only display the top cards in the cardhand, +1 because list indexes start at 1 var/cards_to_display = min(CARDS_MAX_DISPLAY_LIMIT, cards.len) // 90 degrees from the 1st card to the last, so split the divider by total cards displayed var/angle_divider = round(90/(cards_to_display - 1)) diff --git a/code/modules/cargo/universal_scanner.dm b/code/modules/cargo/universal_scanner.dm index 880a75783d8..b9a2d01e14e 100644 --- a/code/modules/cargo/universal_scanner.dm +++ b/code/modules/cargo/universal_scanner.dm @@ -175,6 +175,7 @@ price += report.total_value[exported_datum] if(price) to_chat(user, span_notice("Scanned [target], value: [price] credits[target.contents.len ? " (contents included)" : ""].")) + playsound(src, 'sound/machines/terminal_select.ogg', 50, vary = TRUE) else to_chat(user, span_warning("Scanned [target], no export value.")) diff --git a/code/modules/client/client_procs.dm b/code/modules/client/client_procs.dm index 56406139379..44591686aef 100644 --- a/code/modules/client/client_procs.dm +++ b/code/modules/client/client_procs.dm @@ -275,6 +275,7 @@ GLOBAL_LIST_INIT(blacklisted_builds, list( prefs = GLOB.preferences_datums[ckey] if(prefs) prefs.parent = src + prefs.load_savefile() // just to make sure we have the latest data prefs.apply_all_client_preferences() else prefs = new /datum/preferences(src) diff --git a/code/modules/client/preferences/species_features/basic.dm b/code/modules/client/preferences/species_features/basic.dm index 6e34a234e7d..abf4ea0e44e 100644 --- a/code/modules/client/preferences/species_features/basic.dm +++ b/code/modules/client/preferences/species_features/basic.dm @@ -1,4 +1,4 @@ -/proc/generate_icon_with_head_accessory(datum/sprite_accessory/sprite_accessory) +/proc/generate_icon_with_head_accessory(datum/sprite_accessory/sprite_accessory, y_offset = 0) var/static/icon/head_icon if (isnull(head_icon)) head_icon = icon('icons/mob/human/bodyparts_greyscale.dmi', "human_head_m") @@ -7,8 +7,10 @@ var/icon/final_icon = new(head_icon) if (!isnull(sprite_accessory)) ASSERT(istype(sprite_accessory)) - + var/icon/head_accessory_icon = icon(sprite_accessory.icon, sprite_accessory.icon_state) + if(y_offset) + head_accessory_icon.Shift(NORTH, y_offset) head_accessory_icon.Blend(COLOR_DARK_BROWN, ICON_MULTIPLY) final_icon.Blend(head_accessory_icon, ICON_OVERLAY) @@ -138,7 +140,8 @@ return assoc_to_keys_features(GLOB.hairstyles_list) /datum/preference/choiced/hairstyle/icon_for(value) - return generate_icon_with_head_accessory(GLOB.hairstyles_list[value]) + var/datum/sprite_accessory/hair/hairstyle = GLOB.hairstyles_list[value] + return generate_icon_with_head_accessory(hairstyle, hairstyle?.y_offset) /datum/preference/choiced/hairstyle/apply_to_human(mob/living/carbon/human/target, value) target.set_hairstyle(value, update = FALSE) diff --git a/code/modules/clothing/head/helmet.dm b/code/modules/clothing/head/helmet.dm index f8cd88923ec..2960260255f 100644 --- a/code/modules/clothing/head/helmet.dm +++ b/code/modules/clothing/head/helmet.dm @@ -178,7 +178,7 @@ toggle_message = "You pull the visor down on" alt_toggle_message = "You push the visor up on" armor_type = /datum/armor/toggleable_riot - flags_inv = HIDEEARS|HIDEFACE|HIDESNOUT + flags_inv = HIDEHAIR|HIDEEARS|HIDEFACE|HIDESNOUT strip_delay = 80 actions_types = list(/datum/action/item_action/toggle) visor_flags_inv = HIDEFACE|HIDESNOUT diff --git a/code/modules/clothing/head/wig.dm b/code/modules/clothing/head/wig.dm index b692c1383c5..4d3165f827c 100644 --- a/code/modules/clothing/head/wig.dm +++ b/code/modules/clothing/head/wig.dm @@ -25,7 +25,7 @@ item_flags &= ~EXAMINE_SKIP /obj/item/clothing/head/wig/update_icon_state() - var/datum/sprite_accessory/hair_style = GLOB.hairstyles_list[hairstyle] + var/datum/sprite_accessory/hair/hair_style = GLOB.hairstyles_list[hairstyle] if(hair_style) icon = hair_style.icon icon_state = hair_style.icon_state @@ -37,12 +37,13 @@ if(isinhands) return - var/datum/sprite_accessory/hair = GLOB.hairstyles_list[hairstyle] + var/datum/sprite_accessory/hair/hair = GLOB.hairstyles_list[hairstyle] if(!hair) return var/mutable_appearance/hair_overlay = mutable_appearance(hair.icon, hair.icon_state, layer = -HAIR_LAYER, appearance_flags = RESET_COLOR) hair_overlay.color = color + hair_overlay.pixel_y = hair.y_offset . += hair_overlay // So that the wig actually blocks emissives. diff --git a/code/modules/clothing/shoes/gunboots.dm b/code/modules/clothing/shoes/gunboots.dm index db24b2338cf..d8335b5fcb0 100644 --- a/code/modules/clothing/shoes/gunboots.dm +++ b/code/modules/clothing/shoes/gunboots.dm @@ -18,13 +18,13 @@ /obj/item/clothing/shoes/gunboots/equipped(mob/user, slot) . = ..() if(slot & ITEM_SLOT_FEET) - RegisterSignal(user, COMSIG_HUMAN_MELEE_UNARMED_ATTACK, PROC_REF(check_kick)) + RegisterSignal(user, COMSIG_LIVING_UNARMED_ATTACK, PROC_REF(check_kick)) else - UnregisterSignal(user, COMSIG_HUMAN_MELEE_UNARMED_ATTACK) + UnregisterSignal(user, COMSIG_LIVING_UNARMED_ATTACK) /obj/item/clothing/shoes/gunboots/dropped(mob/user) if(user) - UnregisterSignal(user, COMSIG_HUMAN_MELEE_UNARMED_ATTACK) + UnregisterSignal(user, COMSIG_LIVING_UNARMED_ATTACK) return ..() /// After each step, check if we randomly fire a shot @@ -38,8 +38,8 @@ /// Stomping on someone while wearing gunboots shoots them point blank /obj/item/clothing/shoes/gunboots/proc/check_kick(mob/living/carbon/human/kicking_person, atom/attacked_atom, proximity) SIGNAL_HANDLER - if(!isliving(attacked_atom)) - return + if(!proximity || !isliving(attacked_atom)) + return NONE var/mob/living/attacked_living = attacked_atom if(attacked_living.body_position == LYING_DOWN) INVOKE_ASYNC(src, PROC_REF(fire_shot), attacked_living) diff --git a/code/modules/clothing/suits/ghostsheet.dm b/code/modules/clothing/suits/ghostsheet.dm index e99d838dc50..268cca46199 100644 --- a/code/modules/clothing/suits/ghostsheet.dm +++ b/code/modules/clothing/suits/ghostsheet.dm @@ -10,6 +10,7 @@ flags_inv = HIDEGLOVES|HIDEEARS|HIDEFACE|HIDEHAIR|HIDEFACIALHAIR|HIDESNOUT alternate_worn_layer = UNDER_HEAD_LAYER species_exception = list(/datum/species/golem) + supports_variations_flags = CLOTHING_DIGITIGRADE_VARIATION_NO_NEW_ICON /obj/item/clothing/suit/costume/ghost_sheet/Initialize(mapload) . = ..() diff --git a/code/modules/events/ghost_role/space_dragon.dm b/code/modules/events/ghost_role/space_dragon.dm index 379b5d7e07b..dd75a97a869 100644 --- a/code/modules/events/ghost_role/space_dragon.dm +++ b/code/modules/events/ghost_role/space_dragon.dm @@ -31,7 +31,7 @@ if(isnull(spawn_location)) return MAP_ERROR - var/mob/living/simple_animal/hostile/space_dragon/dragon = new (spawn_location) + var/mob/living/basic/space_dragon/dragon = new (spawn_location) dragon.key = key dragon.mind.add_antag_datum(/datum/antagonist/space_dragon) playsound(dragon, 'sound/magic/ethereal_exit.ogg', 50, TRUE, -1) diff --git a/code/modules/food_and_drinks/machinery/microwave.dm b/code/modules/food_and_drinks/machinery/microwave.dm index d52e2213a5b..8488025149a 100644 --- a/code/modules/food_and_drinks/machinery/microwave.dm +++ b/code/modules/food_and_drinks/machinery/microwave.dm @@ -35,6 +35,8 @@ var/wire_disabled = FALSE /// Wire cut to run mode backwards var/wire_mode_swap = FALSE + /// Fail due to inserted PDA + var/pda_failure = FALSE var/operating = FALSE /// How dirty is it? var/dirty = 0 @@ -123,8 +125,8 @@ else if(held_item && istype(held_item, /obj/item/stock_parts/cell)) context[SCREENTIP_CONTEXT_CTRL_LMB] = "Insert cell" - if(!anchored && held_item?.tool_behaviour == TOOL_WRENCH) - context[SCREENTIP_CONTEXT_LMB] = "Install/Secure" + if(held_item?.tool_behaviour == TOOL_WRENCH) + context[SCREENTIP_CONTEXT_LMB] = "[anchored ? "Unsecure" : "Install/Secure"]" return CONTEXTUAL_SCREENTIP_SET if(broken > NOT_BROKEN) @@ -469,6 +471,9 @@ vampire_charging_enabled = !vampire_charging_enabled balloon_alert(user, "set to [vampire_charging_enabled ? "charge" : "cook"]") + playsound(src, 'sound/machines/twobeep_high.ogg', 50, FALSE) + if(issilicon(user)) + visible_message(span_notice("[user] sets \the [src] to [vampire_charging_enabled ? "charge" : "cook"]."), blind_message = span_notice("You hear \the [src] make an informative beep!")) /obj/machinery/microwave/CtrlClick(mob/user) . = ..() @@ -571,6 +576,9 @@ for(var/atom/movable/potential_fooditem as anything in ingredients) if(IS_EDIBLE(potential_fooditem)) non_food_ingedients-- + if(istype(potential_fooditem, /obj/item/modular_computer/pda) && prob(75)) + pda_failure = TRUE + notify_ghosts("[cooker] has overheated their PDA!", source = src, action = NOTIFY_JUMP, flashwindow = FALSE, header = "Hunger Games: Catching Fire") // If we're cooking non-food items we can fail randomly if(length(non_food_ingedients) && prob(min(dirty * 5, 100))) @@ -662,15 +670,15 @@ */ /obj/machinery/microwave/proc/loop_finish(mob/cooker) operating = FALSE + if(pda_failure) + spark() + pda_failure = FALSE // in case they repair it after this, reset + broken = REALLY_BROKEN + explosion(src, heavy_impact_range = 1, light_impact_range = 2, flame_range = 1) var/cursed_chef = cooker && HAS_TRAIT(cooker, TRAIT_CURSED) var/metal_amount = 0 for(var/obj/item/cooked_item in ingredients) - if(istype(cooked_item, /obj/item/modular_computer/pda) && prob(75)) - spark() - broken = REALLY_BROKEN - explosion(src, heavy_impact_range = 1, light_impact_range = 2, flame_range = 1) - var/sigreturn = cooked_item.microwave_act(src, cooker, randomize_pixel_offset = ingredients.len) if(sigreturn & COMPONENT_MICROWAVE_SUCCESS) if(isstack(cooked_item)) @@ -734,7 +742,6 @@ * * cooker - The mob that initiated the cook cycle, can be null if no apparent mob triggered it (such as via emp) */ /obj/machinery/microwave/proc/vampire(mob/cooker) - wzhzhzh() var/obj/item/modular_computer/pda/vampire_pda = LAZYACCESS(ingredients, 1) if(isnull(vampire_pda)) playsound(src, 'sound/machines/buzz-sigh.ogg', 50, FALSE) @@ -742,11 +749,12 @@ return vampire_cell = vampire_pda.internal_cell - if(isnull(vampire_pda)) + if(isnull(vampire_cell)) playsound(src, 'sound/machines/buzz-sigh.ogg', 50, FALSE) after_finish_loop() return + wzhzhzh() var/vampire_charge_amount = vampire_cell.maxcharge - vampire_cell.charge charge_loop(vampire_charge_amount, cooker = cooker) diff --git a/code/modules/food_and_drinks/recipes/soup_mixtures.dm b/code/modules/food_and_drinks/recipes/soup_mixtures.dm index ad2caa84ca6..b35bc128d32 100644 --- a/code/modules/food_and_drinks/recipes/soup_mixtures.dm +++ b/code/modules/food_and_drinks/recipes/soup_mixtures.dm @@ -85,7 +85,7 @@ if(!length(required_ingredients)) return - // If a food item is supposed to be made, remove relevant ingredients from the pot, then make the item + // If a food item is supposed to be made, remove relevant ingredients from the pot, then make the item if(!isnull(resulting_food_path)) var/list/tracked_ingredients LAZYINITLIST(tracked_ingredients) @@ -112,7 +112,7 @@ for(var/reagent_path as anything in required_reagents) holder.add_reagent(reagent_path,(required_reagents[reagent_path])*(created_volume-ingredient_max_multiplier)) - + // This only happens if we're being instant reacted so let's just skip to what we really want if(isnull(reaction)) testing("Soup reaction of type [type] instant reacted, cleaning up.") @@ -851,9 +851,9 @@ /datum/chemical_reaction/food/soup/monkey required_reagents = list( - /datum/reagent/water = 25, + /datum/reagent/water = 20, /datum/reagent/consumable/flour = 5, - /datum/reagent/consumable/salt = 5, + /datum/reagent/water/salt = 10, /datum/reagent/consumable/blackpepper = 5, ) required_ingredients = list( @@ -2103,7 +2103,7 @@ name = "\improper Hong Kong macaroni soup" icon = 'icons/obj/food/martian.dmi' icon_state = "hong_kong_macaroni" - drink_type = MEAT | VEGETABLES | GRAIN + drink_type = MEAT | VEGETABLES | GRAIN /datum/chemical_reaction/food/soup/hong_kong_macaroni required_reagents = list( diff --git a/code/modules/hallucination/mother.dm b/code/modules/hallucination/mother.dm new file mode 100644 index 00000000000..4e2a389260c --- /dev/null +++ b/code/modules/hallucination/mother.dm @@ -0,0 +1,81 @@ +/// Your mother appears to scold you. +/datum/hallucination/your_mother + random_hallucination_weight = 2 + var/obj/effect/client_image_holder/hallucination/your_mother/mother + +/datum/hallucination/your_mother/start() + var/list/spawn_locs = list() + for(var/turf/open/floor in view(hallucinator, 4)) + if(floor.is_blocked_turf(exclude_mobs = TRUE)) + continue + spawn_locs += floor + + if(!length(spawn_locs)) + return FALSE + var/turf/spawn_loc = pick(spawn_locs) + mother = new(spawn_loc, hallucinator, src) + mother.AddComponent(/datum/component/leash, owner = hallucinator, distance = get_dist(hallucinator, mother)) //basically makes mother follow them + point_at(hallucinator) + talk("[hallucinator]!!!!") + var/list/scold_lines = list( + pick(list("CLEAN YOUR ROOM THIS INSTANT!", "IT'S TIME TO WAKE UP FOR SCHOOL!!")), + pick(list("YOU INSULT YOUR GRANDPARENTS!", "USELESS!")), + pick(list("I BROUGHT YOU INTO THIS WORLD, I CAN TAKE YOU OUT!!!", "YOU'RE GROUNDED!!")), + ) + var/delay = 2 SECONDS + for(var/line in scold_lines) + addtimer(CALLBACK(src, PROC_REF(talk), line), delay) + delay += 2 SECONDS + addtimer(CALLBACK(src, PROC_REF(exit)), delay + 4 SECONDS) + return TRUE + +/datum/hallucination/your_mother/proc/point_at(atom/target) + var/turf/tile = get_turf(target) + if(!tile) + return + + var/obj/visual = image('icons/hud/screen_gen.dmi', mother.loc, "arrow", FLY_LAYER) + + INVOKE_ASYNC(GLOBAL_PROC, GLOBAL_PROC_REF(flick_overlay_global), visual, list(hallucinator.client), 2.5 SECONDS) + animate(visual, pixel_x = (tile.x - mother.x) * world.icon_size, pixel_y = (tile.y - mother.y) * world.icon_size, time = 1.7, easing = EASE_OUT) + +/datum/hallucination/your_mother/proc/talk(text) + var/plus_runechat = hallucinator.client?.prefs.read_preference(/datum/preference/toggle/enable_runechat) + var/datum/language/understood_language = hallucinator.get_random_understood_language() + var/spans = list(mother.speech_span) + + if(!plus_runechat) + var/image/speech_overlay = image('icons/mob/effects/talk.dmi', mother, "default0", layer = ABOVE_MOB_LAYER) + INVOKE_ASYNC(GLOBAL_PROC, GLOBAL_PROC_REF(flick_overlay_global), speech_overlay, list(hallucinator.client), 30) + else + hallucinator.create_chat_message(mother, understood_language, text, spans) + + var/message = hallucinator.compose_message(mother, understood_language, text, null, spans, visible_name = TRUE) + to_chat(hallucinator, message) + +/datum/hallucination/your_mother/proc/exit() + qdel(src) + +/datum/outfit/yourmother + name = "Your Mother" + + uniform = /obj/item/clothing/under/color/jumpskirt/red + neck = /obj/item/clothing/neck/beads + shoes = /obj/item/clothing/shoes/sandal + +/datum/outfit/yourmother/post_equip(mob/living/carbon/human/user, visualsOnly = FALSE) + . = ..() + user.set_hairstyle("Braided", update = TRUE) //get_dynamic_human_appearance uses bald dummies + +/obj/effect/client_image_holder/hallucination/your_mother + gender = FEMALE + image_icon = 'icons/mob/simple/simple_human.dmi' + name = "Your mother" + desc = "She is not happy." + image_state = "" + +/obj/effect/client_image_holder/hallucination/your_mother/Initialize(mapload, list/mobs_which_see_us, datum/hallucination/parent) + . = ..() + var/mob/living/carbon/hallucinator = parent.hallucinator + image_icon = getFlatIcon(get_dynamic_human_appearance(/datum/outfit/yourmother, hallucinator.dna.species)) + regenerate_image() diff --git a/code/modules/hallucination/station_message.dm b/code/modules/hallucination/station_message.dm index fa51e103cca..02488d2016e 100644 --- a/code/modules/hallucination/station_message.dm +++ b/code/modules/hallucination/station_message.dm @@ -1,6 +1,3 @@ -#define ALERT_TITLE(text) ("

" + text + "

") -#define ALERT_BODY(text) ("

" + span_alert(text) + "

") - /datum/hallucination/station_message abstract_hallucination_parent = /datum/hallucination/station_message random_hallucination_weight = 1 @@ -12,16 +9,16 @@ /datum/hallucination/station_message/blob_alert /datum/hallucination/station_message/blob_alert/start() - to_chat(hallucinator, ALERT_TITLE("Biohazard Alert")) - to_chat(hallucinator, ALERT_BODY("Confirmed outbreak of level 5 biohazard aboard [station_name()]. All personnel must contain the outbreak.")) + to_chat(hallucinator, span_priorityannounce("Biohazard Alert")) + to_chat(hallucinator, span_priorityalert("Confirmed outbreak of level 5 biohazard aboard [station_name()]. All personnel must contain the outbreak.")) SEND_SOUND(hallucinator, sound(SSstation.announcer.event_sounds[ANNOUNCER_OUTBREAK5])) return ..() /datum/hallucination/station_message/shuttle_dock /datum/hallucination/station_message/shuttle_dock/start() - to_chat(hallucinator, ALERT_TITLE("Priority Announcement")) - to_chat(hallucinator, ALERT_BODY("[SSshuttle.emergency || "The Emergency Shuttle"] has docked with the station. You have 3 minutes to board the Emergency Shuttle.")) + to_chat(hallucinator, span_priorityannounce("Priority Announcement")) + to_chat(hallucinator, span_priorityalert("[SSshuttle.emergency || "The Emergency Shuttle"] has docked with the station. You have 3 minutes to board the Emergency Shuttle.")) SEND_SOUND(hallucinator, sound(SSstation.announcer.event_sounds[ANNOUNCER_SHUTTLEDOCK])) return ..() @@ -31,8 +28,8 @@ if(!(locate(/mob/living/silicon/ai) in GLOB.silicon_mobs)) return FALSE - to_chat(hallucinator, ALERT_TITLE("Anomaly Alert")) - to_chat(hallucinator, ALERT_BODY("Hostile runtimes detected in all station systems, please deactivate your AI to prevent possible damage to its morality core.")) + to_chat(hallucinator, span_priorityannounce("Anomaly Alert")) + to_chat(hallucinator, span_priorityalert("Hostile runtimes detected in all station systems, please deactivate your AI to prevent possible damage to its morality core.")) SEND_SOUND(hallucinator, sound(SSstation.announcer.event_sounds[ANNOUNCER_AIMALF])) return ..() @@ -56,8 +53,8 @@ var/message_with_name = pick(ascension_bodies) message_with_name = replacetext(message_with_name, "%FAKENAME%", totally_real_heretic.real_name) - to_chat(hallucinator, ALERT_TITLE(generate_heretic_text())) - to_chat(hallucinator, ALERT_BODY("[generate_heretic_text()] [message_with_name] [generate_heretic_text()]")) + to_chat(hallucinator, span_priorityannounce("[generate_heretic_text()]")) + to_chat(hallucinator, span_priorityalert("[generate_heretic_text()] [message_with_name] [generate_heretic_text()]")) SEND_SOUND(hallucinator, sound(SSstation.announcer.event_sounds[ANNOUNCER_SPANOMALIES])) return ..() @@ -74,8 +71,8 @@ var/area/fake_summon_area_type = pick(GLOB.the_station_areas - hallucinator_area.type) var/area/fake_summon_area = GLOB.areas_by_type[fake_summon_area_type] - to_chat(hallucinator, ALERT_TITLE("Central Command Higher Dimensional Affairs")) - to_chat(hallucinator, ALERT_BODY("Figments from an eldritch god are being summoned by [totally_real_cult_leader.real_name] \ + to_chat(hallucinator, span_priorityannounce("Central Command Higher Dimensional Affairs")) + to_chat(hallucinator, span_priorityalert("Figments from an eldritch god are being summoned by [totally_real_cult_leader.real_name] \ into [fake_summon_area] from an unknown dimension. Disrupt the ritual at all costs!")) SEND_SOUND(hallucinator, 'sound/ambience/antag/bloodcult/bloodcult_scribe.ogg') @@ -85,8 +82,8 @@ random_hallucination_weight = 2 /datum/hallucination/station_message/meteors/start() - to_chat(hallucinator, ALERT_TITLE("Meteor Alert")) - to_chat(hallucinator, ALERT_BODY("Meteors have been detected on collision course with the station.")) + to_chat(hallucinator, span_priorityannounce("Meteor Alert")) + to_chat(hallucinator, span_priorityalert("Meteors have been detected on collision course with the station.")) SEND_SOUND(hallucinator, sound(SSstation.announcer.event_sounds[ANNOUNCER_METEORS])) return ..() @@ -113,6 +110,3 @@ hallucinator.playsound_local(get_turf(hallucinator), 'sound/effects/explosion_distant.ogg', 50, FALSE, pressure_affected = FALSE) qdel(src) - -#undef ALERT_TITLE -#undef ALERT_BODY diff --git a/code/modules/holodeck/turfs.dm b/code/modules/holodeck/turfs.dm index 28482873aeb..1e89052af59 100644 --- a/code/modules/holodeck/turfs.dm +++ b/code/modules/holodeck/turfs.dm @@ -8,7 +8,7 @@ /turf/open/floor/holofloor/attackby(obj/item/I, mob/living/user) return // HOLOFLOOR DOES NOT GIVE A FUCK -/turf/open/floor/holofloor/tool_act(mob/living/user, obj/item/I, tool_type) +/turf/open/floor/holofloor/tool_act(mob/living/user, obj/item/tool, tool_type, is_right_clicking) return /turf/open/floor/holofloor/burn_tile() 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 5775f0a20f2..6f08be00e5d 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 @@ -13,8 +13,8 @@ resistance_flags = FIRE_PROOF | LAVA_PROOF max_integrity = 200 + faction = list(FACTION_ASHWALKER) - var/faction = list(FACTION_ASHWALKER) var/meat_counter = 6 var/datum/team/ashwalkers/ashies var/datum/linked_objective diff --git a/code/modules/mining/lavaland/megafauna_loot.dm b/code/modules/mining/lavaland/megafauna_loot.dm index 65d3a1ad3b3..20cbec1444b 100644 --- a/code/modules/mining/lavaland/megafauna_loot.dm +++ b/code/modules/mining/lavaland/megafauna_loot.dm @@ -401,7 +401,7 @@ give_blood(10) /obj/item/soulscythe/attack_hand(mob/user, list/modifiers) - if(soul.ckey && !soul.faction_check_mob(user)) + if(soul.ckey && !soul.faction_check_atom(user)) to_chat(user, span_warning("You can't pick up [src]!")) return return ..() diff --git a/code/modules/mining/lavaland/tendril_loot.dm b/code/modules/mining/lavaland/tendril_loot.dm index 96e330825f1..a6684a221ae 100644 --- a/code/modules/mining/lavaland/tendril_loot.dm +++ b/code/modules/mining/lavaland/tendril_loot.dm @@ -632,7 +632,7 @@ . = ..() if(slot & ITEM_SLOT_GLOVES) tool_behaviour = TOOL_MINING - RegisterSignal(user, COMSIG_HUMAN_EARLY_UNARMED_ATTACK, PROC_REF(rocksmash)) + RegisterSignal(user, COMSIG_LIVING_UNARMED_ATTACK, PROC_REF(rocksmash)) RegisterSignal(user, COMSIG_MOVABLE_BUMP, PROC_REF(rocksmash)) else stopmining(user) @@ -643,13 +643,15 @@ /obj/item/clothing/gloves/gauntlets/proc/stopmining(mob/user) tool_behaviour = initial(tool_behaviour) - UnregisterSignal(user, COMSIG_HUMAN_EARLY_UNARMED_ATTACK) + UnregisterSignal(user, COMSIG_LIVING_UNARMED_ATTACK) UnregisterSignal(user, COMSIG_MOVABLE_BUMP) /obj/item/clothing/gloves/gauntlets/proc/rocksmash(mob/living/carbon/human/user, atom/rocks, proximity) SIGNAL_HANDLER + if(!proximity) + return NONE if(!ismineralturf(rocks) && !isasteroidturf(rocks)) - return + return NONE rocks.attackby(src, user) return COMPONENT_CANCEL_ATTACK_CHAIN diff --git a/code/modules/mob/dead/observer/observer.dm b/code/modules/mob/dead/observer/observer.dm index a28153a2196..8033d465a90 100644 --- a/code/modules/mob/dead/observer/observer.dm +++ b/code/modules/mob/dead/observer/observer.dm @@ -219,9 +219,8 @@ GLOBAL_VAR_INIT(observer_default_invisibility, INVISIBILITY_OBSERVER) setDir(2 )//reset the dir to its default so the sprites all properly align up if(ghost_accs == GHOST_ACCS_FULL && (icon_state in GLOB.ghost_forms_with_accessories_list)) //check if this form supports accessories and if the client wants to show them - var/datum/sprite_accessory/S if(facial_hairstyle) - S = GLOB.facial_hairstyles_list[facial_hairstyle] + var/datum/sprite_accessory/S = GLOB.facial_hairstyles_list[facial_hairstyle] if(S) facial_hair_overlay = mutable_appearance(S.icon, "[S.icon_state]", -HAIR_LAYER) if(facial_hair_color) @@ -229,12 +228,13 @@ GLOBAL_VAR_INIT(observer_default_invisibility, INVISIBILITY_OBSERVER) facial_hair_overlay.alpha = 200 add_overlay(facial_hair_overlay) if(hairstyle) - S = GLOB.hairstyles_list[hairstyle] + var/datum/sprite_accessory/hair/S = GLOB.hairstyles_list[hairstyle] if(S) hair_overlay = mutable_appearance(S.icon, "[S.icon_state]", -HAIR_LAYER) if(hair_color) hair_overlay.color = hair_color hair_overlay.alpha = 200 + hair_overlay.pixel_y = S.y_offset add_overlay(hair_overlay) /* diff --git a/code/modules/mob/living/basic/icemoon/ice_whelp/ice_whelp.dm b/code/modules/mob/living/basic/icemoon/ice_whelp/ice_whelp.dm index f89009cc2d9..8fb02ec83df 100644 --- a/code/modules/mob/living/basic/icemoon/ice_whelp/ice_whelp.dm +++ b/code/modules/mob/living/basic/icemoon/ice_whelp/ice_whelp.dm @@ -43,12 +43,12 @@ AddElement(/datum/element/footstep, FOOTSTEP_MOB_HEAVY) AddComponent(/datum/component/basic_mob_ability_telegraph) AddComponent(/datum/component/basic_mob_attack_telegraph, telegraph_duration = 0.6 SECONDS) - var/datum/action/cooldown/mob_cooldown/ice_breath/flamethrower = new(src) - var/datum/action/cooldown/mob_cooldown/ice_breathe_all_directions/wide_flames = new(src) + var/datum/action/cooldown/mob_cooldown/fire_breath/ice/flamethrower = new(src) flamethrower.Grant(src) + ai_controller.set_blackboard_key(BB_WHELP_STRAIGHTLINE_FIRE, flamethrower) + var/datum/action/cooldown/mob_cooldown/fire_breath/ice/cross/wide_flames = new(src) wide_flames.Grant(src) ai_controller.set_blackboard_key(BB_WHELP_WIDESPREAD_FIRE, wide_flames) - ai_controller.set_blackboard_key(BB_WHELP_STRAIGHTLINE_FIRE, flamethrower) RegisterSignal(src, COMSIG_HOSTILE_PRE_ATTACKINGTARGET, PROC_REF(pre_attack)) diff --git a/code/modules/mob/living/basic/icemoon/ice_whelp/ice_whelp_abilities.dm b/code/modules/mob/living/basic/icemoon/ice_whelp/ice_whelp_abilities.dm index d5dc50d0a69..026106516fb 100644 --- a/code/modules/mob/living/basic/icemoon/ice_whelp/ice_whelp_abilities.dm +++ b/code/modules/mob/living/basic/icemoon/ice_whelp/ice_whelp_abilities.dm @@ -1,23 +1,26 @@ -/datum/action/cooldown/mob_cooldown/ice_breath +/// Breathe "fire" in a line (it's freezing cold) +/datum/action/cooldown/mob_cooldown/fire_breath/ice name = "Ice Breath" desc = "Fire a cold line of fire towards the enemy!" button_icon = 'icons/effects/magic.dmi' button_icon_state = "fireball" cooldown_time = 3 SECONDS melee_cooldown_time = 0 SECONDS - click_to_activate = TRUE - ///the range of fire - var/fire_range = 4 + fire_range = 4 + fire_damage = 10 -/datum/action/cooldown/mob_cooldown/ice_breath/Activate(atom/target_atom) - var/turf/target_fire_turf = get_ranged_target_turf_direct(owner, target_atom, fire_range) - var/list/burn_turfs = get_line(owner, target_fire_turf) - get_turf(owner) - // This proc sleeps - INVOKE_ASYNC(GLOBAL_PROC, GLOBAL_PROC_REF(dragon_fire_line), owner, /* burn_turfs = */ burn_turfs, /* frozen = */ TRUE) - StartCooldown() - return TRUE +/datum/action/cooldown/mob_cooldown/fire_breath/ice/burn_turf(turf/fire_turf, list/hit_list, atom/source) + var/obj/effect/hotspot/fire_hotspot = ..() + fire_hotspot.add_atom_colour(COLOR_BLUE_LIGHT, FIXED_COLOUR_PRIORITY) // You're blue now, that's my attack + return fire_hotspot -/datum/action/cooldown/mob_cooldown/ice_breathe_all_directions +/datum/action/cooldown/mob_cooldown/fire_breath/ice/on_burn_mob(mob/living/barbecued, mob/living/source) + barbecued.apply_status_effect(/datum/status_effect/ice_block_talisman, 2 SECONDS) + to_chat(barbecued, span_userdanger("You're frozen solid by [source]'s icy breath!")) + barbecued.adjustFireLoss(fire_damage) + +/// Breathe really cold fire in a plus shape, like bomberman +/datum/action/cooldown/mob_cooldown/fire_breath/ice/cross name = "Fire all directions" desc = "Unleash lines of cold fire in all directions" button_icon = 'icons/effects/fire.dmi' @@ -25,13 +28,10 @@ cooldown_time = 4 SECONDS melee_cooldown_time = 0 SECONDS click_to_activate = FALSE - ///the range of fire - var/fire_range = 6 + fire_range = 6 -/datum/action/cooldown/mob_cooldown/ice_breathe_all_directions/Activate(atom/target_atom) +/datum/action/cooldown/mob_cooldown/fire_breath/ice/cross/attack_sequence(atom/target) + playsound(owner.loc, fire_sound, 200, TRUE) for(var/direction in GLOB.cardinals) var/turf/target_fire_turf = get_ranged_target_turf(owner, direction, fire_range) - var/list/burn_turfs = get_line(owner, target_fire_turf) - get_turf(owner) - INVOKE_ASYNC(GLOBAL_PROC, GLOBAL_PROC_REF(dragon_fire_line), owner, burn_turfs, frozen = TRUE) - StartCooldown() - return TRUE + fire_line(target_fire_turf) diff --git a/code/modules/mob/living/basic/lavaland/brimdemon/brimbeam.dm b/code/modules/mob/living/basic/lavaland/brimdemon/brimbeam.dm index 29a3de60029..b8e2bb68c69 100644 --- a/code/modules/mob/living/basic/lavaland/brimdemon/brimbeam.dm +++ b/code/modules/mob/living/basic/lavaland/brimdemon/brimbeam.dm @@ -9,7 +9,6 @@ click_to_activate = TRUE cooldown_time = 5 SECONDS melee_cooldown_time = 0 - check_flags = AB_CHECK_CONSCIOUS | AB_CHECK_INCAPACITATED /// How far does our beam go? var/beam_range = 10 /// How long does our beam last? diff --git a/code/modules/mob/living/basic/lavaland/goliath/goliath_actions.dm b/code/modules/mob/living/basic/lavaland/goliath/goliath_actions.dm index bb8adaf61c3..b484afa0cea 100644 --- a/code/modules/mob/living/basic/lavaland/goliath/goliath_actions.dm +++ b/code/modules/mob/living/basic/lavaland/goliath/goliath_actions.dm @@ -9,7 +9,6 @@ click_to_activate = TRUE cooldown_time = 12 SECONDS melee_cooldown_time = 0 - check_flags = AB_CHECK_CONSCIOUS | AB_CHECK_INCAPACITATED shared_cooldown = NONE /// Furthest range we can activate ability at var/max_range = 7 @@ -44,7 +43,6 @@ overlay_icon_state = "bg_demon_border" cooldown_time = 24 SECONDS melee_cooldown_time = 0 - check_flags = AB_CHECK_CONSCIOUS | AB_CHECK_INCAPACITATED shared_cooldown = NONE click_to_activate = FALSE @@ -69,7 +67,6 @@ click_to_activate = TRUE cooldown_time = 12 SECONDS melee_cooldown_time = 0 - check_flags = AB_CHECK_CONSCIOUS | AB_CHECK_INCAPACITATED shared_cooldown = NONE /datum/action/cooldown/mob_cooldown/tentacle_grasp/Activate(atom/target) diff --git a/code/modules/mob/living/basic/lavaland/hivelord/spawn_hivelord_brood.dm b/code/modules/mob/living/basic/lavaland/hivelord/spawn_hivelord_brood.dm index 3fee2a003f3..63a66d4c4e3 100644 --- a/code/modules/mob/living/basic/lavaland/hivelord/spawn_hivelord_brood.dm +++ b/code/modules/mob/living/basic/lavaland/hivelord/spawn_hivelord_brood.dm @@ -9,7 +9,6 @@ click_to_activate = TRUE cooldown_time = 2 SECONDS melee_cooldown_time = 0 - check_flags = AB_CHECK_CONSCIOUS | AB_CHECK_INCAPACITATED shared_cooldown = NONE /// If a mob is not clicked directly, inherit targetting data from this blackboard key and setting it upon this target key var/ai_target_key = BB_BASIC_MOB_CURRENT_TARGET diff --git a/code/modules/mob/living/basic/lavaland/legion/legion_ai.dm b/code/modules/mob/living/basic/lavaland/legion/legion_ai.dm index 310bbeb708e..ff29ea3c240 100644 --- a/code/modules/mob/living/basic/lavaland/legion/legion_ai.dm +++ b/code/modules/mob/living/basic/lavaland/legion/legion_ai.dm @@ -32,7 +32,7 @@ /datum/targetting_datum/basic/attack_until_dead/legion /datum/targetting_datum/basic/attack_until_dead/legion/faction_check(datum/ai_controller/controller, mob/living/living_mob, mob/living/the_target) - if (!living_mob.faction_check_mob(the_target, exact_match = check_factions_exactly)) + if (!living_mob.faction_check_atom(the_target, exact_match = check_factions_exactly)) return FALSE if (istype(the_target, living_mob.type)) return TRUE @@ -46,7 +46,7 @@ /datum/ai_planning_subtree/flee_target/legion/SelectBehaviors(datum/ai_controller/controller, seconds_per_tick) var/mob/living/target = controller.blackboard[target_key] - if (QDELETED(target) || target.faction_check_mob(controller.pawn)) + if (QDELETED(target) || target.faction_check_atom(controller.pawn)) return // Only flee if we have a hostile target return ..() diff --git a/code/modules/mob/living/basic/lavaland/legion/legion_brood.dm b/code/modules/mob/living/basic/lavaland/legion/legion_brood.dm index 962d232c5ef..7ce568d5760 100644 --- a/code/modules/mob/living/basic/lavaland/legion/legion_brood.dm +++ b/code/modules/mob/living/basic/lavaland/legion/legion_brood.dm @@ -49,7 +49,7 @@ if (ishuman(target) && target.stat > SOFT_CRIT) infest(target) return - if (isliving(target) && faction_check_mob(target) && !istype(target, created_by?.type)) + if (isliving(target) && faction_check_atom(target) && !istype(target, created_by?.type)) visible_message(span_warning("[src] melds with [target]'s flesh!")) target.apply_status_effect(/datum/status_effect/regenerative_core) new /obj/effect/temp_visual/heal(get_turf(target), COLOR_HEALING_CYAN) diff --git a/code/modules/mob/living/basic/lavaland/legion/spawn_legions.dm b/code/modules/mob/living/basic/lavaland/legion/spawn_legions.dm index 1ffcafecd56..f68c5f7fafe 100644 --- a/code/modules/mob/living/basic/lavaland/legion/spawn_legions.dm +++ b/code/modules/mob/living/basic/lavaland/legion/spawn_legions.dm @@ -9,7 +9,6 @@ click_to_activate = TRUE cooldown_time = 2 SECONDS melee_cooldown_time = 0 - check_flags = AB_CHECK_CONSCIOUS | AB_CHECK_INCAPACITATED shared_cooldown = NONE /// If a mob is not clicked directly, inherit targetting data from this blackboard key and setting it upon this target key var/ai_target_key = BB_BASIC_MOB_CURRENT_TARGET diff --git a/code/modules/mob/living/basic/lavaland/watcher/watcher_gaze.dm b/code/modules/mob/living/basic/lavaland/watcher/watcher_gaze.dm index 4b322c220ed..06a221db2dc 100644 --- a/code/modules/mob/living/basic/lavaland/watcher/watcher_gaze.dm +++ b/code/modules/mob/living/basic/lavaland/watcher/watcher_gaze.dm @@ -9,7 +9,6 @@ background_icon_state = "bg_demon" overlay_icon_state = "bg_demon_border" cooldown_time = 20 SECONDS - check_flags = AB_CHECK_CONSCIOUS | AB_CHECK_INCAPACITATED click_to_activate = FALSE shared_cooldown = NONE melee_cooldown_time = 0 SECONDS diff --git a/code/modules/mob/living/basic/lavaland/watcher/watcher_overwatch.dm b/code/modules/mob/living/basic/lavaland/watcher/watcher_overwatch.dm index 0c8194c524a..541a4ed9e1c 100644 --- a/code/modules/mob/living/basic/lavaland/watcher/watcher_overwatch.dm +++ b/code/modules/mob/living/basic/lavaland/watcher/watcher_overwatch.dm @@ -10,7 +10,6 @@ background_icon_state = "bg_demon" overlay_icon_state = "bg_demon_border" cooldown_time = 20 SECONDS - check_flags = AB_CHECK_CONSCIOUS | AB_CHECK_INCAPACITATED click_to_activate = TRUE shared_cooldown = NONE /// Furthest range we can activate ability at diff --git a/code/modules/mob/living/basic/space_fauna/demon/demon_subtypes.dm b/code/modules/mob/living/basic/space_fauna/demon/demon_subtypes.dm index e52eb09ac0b..ed3c131949d 100644 --- a/code/modules/mob/living/basic/space_fauna/demon/demon_subtypes.dm +++ b/code/modules/mob/living/basic/space_fauna/demon/demon_subtypes.dm @@ -99,16 +99,19 @@ /mob/living/basic/demon/slaughter/proc/on_attack(mob/living/source, atom/attack_target, proximity_flag, list/modifiers) SIGNAL_HANDLER + if(!proximity_flag) + return NONE + if(LAZYACCESS(modifiers, RIGHT_CLICK)) bodyslam(attack_target) return COMPONENT_CANCEL_ATTACK_CHAIN if(!iscarbon(attack_target)) - return + return NONE var/mob/living/carbon/target = attack_target if(target.stat == DEAD || isnull(target.mind) || (current_hitstreak > wound_bonus_hitstreak_max)) - return + return NONE current_hitstreak++ wound_bonus += wound_bonus_per_hit diff --git a/code/modules/mob/living/basic/space_fauna/faithless.dm b/code/modules/mob/living/basic/space_fauna/faithless.dm index c1dc297ea46..88696b3a3c7 100644 --- a/code/modules/mob/living/basic/space_fauna/faithless.dm +++ b/code/modules/mob/living/basic/space_fauna/faithless.dm @@ -38,9 +38,9 @@ /mob/living/basic/faithless/Initialize(mapload) . = ..() ADD_TRAIT(src, TRAIT_SPACEWALK, INNATE_TRAIT) + AddElement(/datum/element/door_pryer) AddElement(/datum/element/footstep, FOOTSTEP_MOB_SHOE) AddElement(/datum/element/mob_grabber, steal_from_others = FALSE) - AddComponent(/datum/component/pry_open_door) /mob/living/basic/faithless/melee_attack(atom/target, list/modifiers, ignore_cooldown) . = ..() diff --git a/code/modules/mob/living/basic/space_fauna/ghost.dm b/code/modules/mob/living/basic/space_fauna/ghost.dm index 35afaade990..ad79fefc3e6 100644 --- a/code/modules/mob/living/basic/space_fauna/ghost.dm +++ b/code/modules/mob/living/basic/space_fauna/ghost.dm @@ -71,10 +71,11 @@ ghost_facial_hair_color = ghost_hair_color if(!isnull(ghost_hairstyle) && ghost_hairstyle != "Bald") //Bald hairstyle and the Shaved facial hairstyle lack an associated sprite and will not properly generate hair, and just cause runtimes. - var/datum/sprite_accessory/hair_style = GLOB.hairstyles_list[ghost_hairstyle] //We use the hairstyle name to get the sprite accessory, which we copy the icon_state from. + var/datum/sprite_accessory/hair/hair_style = GLOB.hairstyles_list[ghost_hairstyle] //We use the hairstyle name to get the sprite accessory, which we copy the icon_state from. ghost_hair = mutable_appearance('icons/mob/human/human_face.dmi', "[hair_style.icon_state]", -HAIR_LAYER) ghost_hair.alpha = 200 ghost_hair.color = ghost_hair_color + ghost_hair.pixel_y = hair_style.y_offset add_overlay(ghost_hair) if(!isnull(ghost_facial_hairstyle) && ghost_facial_hairstyle != "Shaved") diff --git a/code/modules/mob/living/basic/space_fauna/mushroom.dm b/code/modules/mob/living/basic/space_fauna/mushroom.dm index 96280db2923..6f900b08abf 100644 --- a/code/modules/mob/living/basic/space_fauna/mushroom.dm +++ b/code/modules/mob/living/basic/space_fauna/mushroom.dm @@ -74,7 +74,7 @@ ///we only attacked another mushrooms /datum/targetting_datum/basic/mushroom/faction_check(datum/ai_controller/controller, mob/living/living_mob, mob/living/the_target) - return !living_mob.faction_check_mob(the_target, exact_match = check_factions_exactly) + return !living_mob.faction_check_atom(the_target, exact_match = check_factions_exactly) /datum/ai_planning_subtree/find_and_hunt_target/mushroom_food target_key = BB_LOW_PRIORITY_HUNTING_TARGET diff --git a/code/modules/mob/living/basic/space_fauna/regal_rat/regal_rat.dm b/code/modules/mob/living/basic/space_fauna/regal_rat/regal_rat.dm index 164c25fb896..24e53b3bf44 100644 --- a/code/modules/mob/living/basic/space_fauna/regal_rat/regal_rat.dm +++ b/code/modules/mob/living/basic/space_fauna/regal_rat/regal_rat.dm @@ -54,6 +54,7 @@ AddElement(/datum/element/waddling) AddElement(/datum/element/ai_retaliate) + AddElement(/datum/element/door_pryer, pry_time = 5 SECONDS, interaction_key = REGALRAT_INTERACTION) AddComponent(\ /datum/component/ghost_direct_control,\ poll_candidates = poll_ghosts,\ @@ -81,7 +82,7 @@ return if(ismouse(user)) - if(user.faction_check_mob(src, exact_match = TRUE)) + if(user.faction_check_atom(src, exact_match = TRUE)) . += span_notice("This is your king. Long live [p_their()] majesty!") else . += span_warning("This is a false king! Strike [p_them()] down!") @@ -174,10 +175,6 @@ if(isnull(mind)) return - if(istype(target, /obj/machinery/door/airlock)) - INVOKE_ASYNC(src, PROC_REF(pry_door), target) - return COMPONENT_HOSTILE_NO_ATTACK - if(!combat_mode) INVOKE_ASYNC(src, PROC_REF(poison_target), target) return COMPONENT_HOSTILE_NO_ATTACK @@ -195,7 +192,7 @@ balloon_alert(src, "already dead!") return FALSE - if(living_target.faction_check_mob(src, exact_match = TRUE)) + if(living_target.faction_check_atom(src, exact_match = TRUE)) balloon_alert(src, "one of your soldiers!") return FALSE @@ -235,43 +232,7 @@ heal_bodypart_damage(amount) qdel(target) -/** - * Allows rat king to pry open an airlock if it isn't locked. - * - * A proc used for letting the rat king pry open airlocks instead of just attacking them. - * This allows the rat king to traverse the station when there is a lack of vents or - * accessible doors, something which is common in certain rat king spawn points. - * - * Returns TRUE if the door opens, FALSE otherwise. - */ -/mob/living/basic/regal_rat/proc/pry_door(target) - if(DOING_INTERACTION(src, REGALRAT_INTERACTION)) - return FALSE - - var/obj/machinery/door/airlock/prying_door = target - if(!prying_door.density || prying_door.locked || prying_door.welded || prying_door.seal) - return FALSE - - visible_message( - span_warning("[src] begins prying open the airlock..."), - span_notice("You begin digging your claws into the airlock..."), - span_warning("You hear groaning metal..."), - ) - var/time_to_open = 0.5 SECONDS - - if(prying_door.hasPower()) - time_to_open = 5 SECONDS - playsound(src, 'sound/machines/airlock_alien_prying.ogg', 100, vary = TRUE) - - if(!do_after(src, time_to_open, prying_door, interaction_key = REGALRAT_INTERACTION)) - return FALSE - - if(!prying_door.open(BYPASS_DOOR_CHECKS)) - balloon_alert(src, "failed to open!") - return FALSE - - return TRUE - +/// Regal rat subtype which can be possessed by ghosts /mob/living/basic/regal_rat/controlled poll_ghosts = TRUE diff --git a/code/modules/mob/living/basic/space_fauna/space_dragon/dragon_breath.dm b/code/modules/mob/living/basic/space_fauna/space_dragon/dragon_breath.dm new file mode 100644 index 00000000000..5be5038b3a4 --- /dev/null +++ b/code/modules/mob/living/basic/space_fauna/space_dragon/dragon_breath.dm @@ -0,0 +1,32 @@ +/// A space dragon's fire breath, toasts lunch AND buffs your friends +/datum/action/cooldown/mob_cooldown/fire_breath/carp + desc = "A Space Dragon's burning breath not only chars its foes, but invigorates Space Carp as well." + fire_damage = 30 + mech_damage = 50 + fire_range = 20 + fire_temperature = 700 // Even hotter than a megafauna for some reason + shared_cooldown = NONE + melee_cooldown_time = 0 SECONDS + +/datum/action/cooldown/mob_cooldown/fire_breath/carp/on_burn_mob(mob/living/barbecued, mob/living/source) + if (!source.faction_check_atom(barbecued)) + return ..() + to_chat(barbecued, span_notice("[source]'s fiery breath fills you with energy!")) + barbecued.apply_status_effect(/datum/status_effect/carp_invigoration) + +/// Makes you run faster for the duration +/datum/status_effect/carp_invigoration + id = "carp_invigorated" + alert_type = null + duration = 8 SECONDS + +/datum/status_effect/carp_invigoration/on_apply() + . = ..() + if (!.) + return + owner.add_filter("anger_glow", 3, list("type" = "outline", "color" = COLOR_CARP_RIFT_RED, "size" = 2)) + owner.add_movespeed_modifier(/datum/movespeed_modifier/dragon_rage) + +/datum/status_effect/carp_invigoration/on_remove() + owner.remove_filter("anger_glow") + owner.remove_movespeed_modifier(/datum/movespeed_modifier/dragon_rage) diff --git a/code/modules/mob/living/basic/space_fauna/space_dragon/dragon_gust.dm b/code/modules/mob/living/basic/space_fauna/space_dragon/dragon_gust.dm new file mode 100644 index 00000000000..074804de86c --- /dev/null +++ b/code/modules/mob/living/basic/space_fauna/space_dragon/dragon_gust.dm @@ -0,0 +1,94 @@ +/// Default additional time to spend stunned per usage of ability +#define DEFAULT_ACTIVATED_ENDLAG 3 DECISECONDS + +/// Rise into the air and slam down, knocking people away. No real cooldown but has escalating endlag if used in quick succession. +/datum/action/cooldown/mob_cooldown/wing_buffet + name = "Wing Buffet" + desc = "Rise into the air and release a powerful gust from your wings, blowing attackers away. Becomes more tiring if used in quick succession." + button_icon = 'icons/effects/magic.dmi' + button_icon_state = "tornado" + cooldown_time = 1 SECONDS + melee_cooldown_time = 0 + click_to_activate = FALSE + shared_cooldown = NONE + /// Timer we use to track our current action + var/active_timer + /// How far away can we reach people? + var/gust_distance = 4 + /// How long to animate for before we start? + var/windup_time = 1.2 SECONDS + /// Minimum amount of stun time following use of wing buffet + var/minimum_endlag = 4 DECISECONDS + /// Amount of extra time to stay stunned after the end of the ability + var/additional_endlag = 0 DECISECONDS + /// Amount of time to add to endlag after each successful use of the ability + var/endlag_per_activation = DEFAULT_ACTIVATED_ENDLAG + /// How much accumulated stun time do we subtract every second? Takes a full minute to regen off a single use :( + var/endlag_decay_per_second = DEFAULT_ACTIVATED_ENDLAG / 60 + /// Increase the effect of our accumulated additional stun time by this much if space dragon has lost some rifts + var/exhaustion_multiplier = 5 + /// List of traits we apply while the ability is ongoing, stops us from moving around and such + var/static/list/applied_traits = list( + TRAIT_IMMOBILIZED, + TRAIT_INCAPACITATED, + TRAIT_NO_FLOATING_ANIM, + TRAIT_WING_BUFFET, + ) + +/datum/action/cooldown/mob_cooldown/wing_buffet/Grant(mob/granted_to) + . = ..() + RegisterSignal(granted_to, COMSIG_LIVING_LIFE, PROC_REF(on_life)) + +/datum/action/cooldown/mob_cooldown/wing_buffet/Remove(mob/removed_from) + . = ..() + deltimer(active_timer) + UnregisterSignal(removed_from, COMSIG_LIVING_LIFE) + removed_from.remove_traits(applied_traits + TRAIT_WING_BUFFET_TIRED, REF(src)) + +/// Decay our accumulated additional tiredness +/datum/action/cooldown/mob_cooldown/wing_buffet/proc/on_life(mob/living/liver, seconds_per_tick, times_fired) + SIGNAL_HANDLER + if (liver.stat == DEAD) + return // not so life now buddy + additional_endlag = max(0, additional_endlag - (endlag_decay_per_second * seconds_per_tick)) + +/datum/action/cooldown/mob_cooldown/wing_buffet/Activate(atom/target) + begin_sequence() + StartCooldown() + return TRUE + +/// Rise up into the air +/datum/action/cooldown/mob_cooldown/wing_buffet/proc/begin_sequence() + owner.add_traits(applied_traits, REF(src)) // No moving till we're done + owner.update_appearance(UPDATE_ICON) + animate(owner, pixel_y = 20, time = windup_time) + active_timer = addtimer(CALLBACK(src, PROC_REF(ground_pound)), windup_time, TIMER_DELETE_ME | TIMER_STOPPABLE) + +/// Slam into the ground +/datum/action/cooldown/mob_cooldown/wing_buffet/proc/ground_pound() + if (QDELETED(owner)) + return + owner.pixel_y = 0 + playsound(owner, 'sound/effects/gravhit.ogg', 100, TRUE) + for (var/mob/living/candidate in view(gust_distance, owner)) + if(candidate == owner || candidate.faction_check_atom(owner)) + continue + owner.visible_message(span_boldwarning("[candidate] is knocked back by the gust!")) + to_chat(candidate, span_userdanger("You're knocked back by the gust!")) + var/dir_to_target = get_dir(get_turf(owner), get_turf(candidate)) + var/throwtarget = get_edge_target_turf(target, dir_to_target) + candidate.safe_throw_at(throwtarget, range = 10, speed = 1, thrower = owner) + candidate.Paralyze(5 SECONDS) + + var/endlag_multiplier = HAS_TRAIT(owner, TRAIT_RIFT_FAILURE) ? exhaustion_multiplier : 1 + var/stun_time = minimum_endlag + (additional_endlag * endlag_multiplier) + additional_endlag += endlag_per_activation * endlag_multiplier // double dips, rough + ADD_TRAIT(owner, TRAIT_WING_BUFFET_TIRED, REF(src)) + owner.update_appearance(UPDATE_ICON) + active_timer = addtimer(CALLBACK(src, PROC_REF(complete_ability)), stun_time, TIMER_DELETE_ME | TIMER_STOPPABLE) + +/datum/action/cooldown/mob_cooldown/wing_buffet/proc/complete_ability() + owner.remove_traits(applied_traits + TRAIT_WING_BUFFET_TIRED, REF(src)) + owner.update_appearance(UPDATE_ICON) + +#undef DEFAULT_ACTIVATED_ENDLAG diff --git a/code/modules/mob/living/basic/space_fauna/space_dragon/space_dragon.dm b/code/modules/mob/living/basic/space_fauna/space_dragon/space_dragon.dm new file mode 100644 index 00000000000..50c54da6c9b --- /dev/null +++ b/code/modules/mob/living/basic/space_fauna/space_dragon/space_dragon.dm @@ -0,0 +1,230 @@ +/// You can't make a dragon darker than this, it'd be hard to see +#define REJECT_DARK_COLOUR_THRESHOLD 50 +/// Any interactions executed by the space dragon +#define DOAFTER_SOURCE_SPACE_DRAGON_INTERACTION "space dragon interaction" + +/** + * Advanced stage of the space carp life cycle, spawned as a midround antagonist or via traitor transformation. + * Can eat corpses to heal, blow people back with its wings, and obviously as a dragon it breathes fire. It can even tear through walls. + * The midround even version also creates rifts which summon carp, and heals when near them. + */ +/mob/living/basic/space_dragon + name = "Space Dragon" + desc = "A serpentine leviathan whose flight defies all modern understanding of physics. Said to be the ultimate stage in the life cycle of the Space Carp." + icon = 'icons/mob/nonhuman-player/spacedragon.dmi' + icon_state = "spacedragon" + icon_living = "spacedragon" + icon_dead = "spacedragon_dead" + health_doll_icon = "spacedragon" + faction = list(FACTION_CARP) + flags_1 = PREVENT_CONTENTS_EXPLOSION_1 + gender = NEUTER + maxHealth = 400 + health = 400 + unsuitable_cold_damage = 0 + unsuitable_heat_damage = 0 + unsuitable_atmos_damage = 0 + damage_coeff = list(BRUTE = 1, BURN = 1, TOX = 1, CLONE = 1, STAMINA = 0.5, OXY = 1) + combat_mode = TRUE + speed = 0 + movement_type = FLYING + attack_verb_continuous = "chomps" + attack_verb_simple = "chomp" + attack_sound = 'sound/magic/demon_attack1.ogg' + attack_vis_effect = ATTACK_EFFECT_BITE + obj_damage = 50 + melee_damage_upper = 35 + melee_damage_lower = 35 + melee_attack_cooldown = CLICK_CD_MELEE + mob_size = MOB_SIZE_LARGE + armour_penetration = 30 + pixel_x = -16 + base_pixel_x = -16 + maptext_height = 64 + maptext_width = 64 + mouse_opacity = MOUSE_OPACITY_ICON + death_sound = 'sound/creatures/space_dragon_roar.ogg' + death_message = "screeches in agony as it collapses to the floor, its life extinguished." + butcher_results = list(/obj/item/stack/ore/diamond = 5, /obj/item/stack/sheet/sinew = 5, /obj/item/stack/sheet/bone = 30) + + /// The colour of the space dragon + var/chosen_colour + /// Minimum devastation damage dealt coefficient based on max health + var/devastation_damage_min_percentage = 0.4 + /// Maximum devastation damage dealt coefficient based on max health + var/devastation_damage_max_percentage = 0.75 + /// Our fire breath action + var/datum/action/cooldown/mob_cooldown/fire_breath/carp/fire_breath + /// Our wing flap action + var/datum/action/cooldown/mob_cooldown/wing_buffet/buffet + +/mob/living/basic/space_dragon/Initialize(mapload) + . = ..() + add_traits(list(TRAIT_SPACEWALK, TRAIT_FREE_HYPERSPACE_MOVEMENT, TRAIT_NO_FLOATING_ANIM, TRAIT_HEALS_FROM_CARP_RIFTS), INNATE_TRAIT) + AddElement(/datum/element/simple_flying) + AddElement(/datum/element/content_barfer) + AddElement(/datum/element/wall_tearer, do_after_key = DOAFTER_SOURCE_SPACE_DRAGON_INTERACTION) + AddElement(/datum/element/door_pryer, pry_time = 4 SECONDS, interaction_key = DOAFTER_SOURCE_SPACE_DRAGON_INTERACTION) + AddComponent(/datum/component/seethrough_mob) + RegisterSignal(src, COMSIG_HOSTILE_PRE_ATTACKINGTARGET, PROC_REF(pre_attack)) + RegisterSignal(src, COMSIG_MOB_STATCHANGE, PROC_REF(on_stat_changed)) + RegisterSignal(src, COMSIG_ATOM_PRE_EX_ACT, PROC_REF(on_exploded)) + + fire_breath = new(src) + fire_breath.Grant(src) + + buffet = new(src) + buffet.Grant(src) + +/mob/living/basic/space_dragon/Destroy() + QDEL_NULL(fire_breath) + QDEL_NULL(buffet) + return ..() + +/mob/living/basic/space_dragon/Login() + . = ..() + if(!isnull(chosen_colour)) + return + rename_dragon() + select_colour() + +/// Allows the space dragon to pick a funny name +/mob/living/basic/space_dragon/proc/rename_dragon() + var/chosen_name = sanitize_name(reject_bad_text(tgui_input_text(src, "What would you like your name to be?", "Choose Your Name", real_name, MAX_NAME_LEN))) + if(!chosen_name) // Null or empty or rejected + to_chat(src, span_warning("Not a valid name, please try again.")) + rename_dragon() + return + to_chat(src, span_notice("Your name is now [span_name("[chosen_name]")], the feared Space Dragon.")) + fully_replace_character_name(null, chosen_name) + +/// Select scale colour with the colour picker +/mob/living/basic/space_dragon/proc/select_colour() + chosen_colour = input(src, "What colour would you like to be?" ,"Colour Selection", COLOR_WHITE) as color|null + if(!chosen_colour) // Redo proc until we get a color + to_chat(src, span_warning("Not a valid colour, please try again.")) + select_colour() + return + var/temp_hsv = RGBtoHSV(chosen_colour) + if(ReadHSV(temp_hsv)[3] < REJECT_DARK_COLOUR_THRESHOLD) + to_chat(src, span_danger("Invalid colour. Your colour is not bright enough.")) + select_colour() + return + add_atom_colour(chosen_colour, FIXED_COLOUR_PRIORITY) + update_appearance(UPDATE_OVERLAYS) + +/mob/living/basic/space_dragon/update_icon_state() + . = ..() + if (stat == DEAD) + return + if (!HAS_TRAIT(src, TRAIT_WING_BUFFET)) + icon_state = icon_living + return + if (HAS_TRAIT(src, TRAIT_WING_BUFFET_TIRED)) + icon_state = "spacedragon_gust_2" + return + icon_state = "spacedragon_gust" + +/mob/living/basic/space_dragon/update_overlays() + . = ..() + var/overlay_state = "overlay_base" + if (stat == DEAD) + overlay_state = "overlay_dead" + else if (HAS_TRAIT(src, TRAIT_WING_BUFFET_TIRED)) + overlay_state = "overlay_gust_2" + else if (HAS_TRAIT(src, TRAIT_WING_BUFFET)) + overlay_state = "overlay_gust" + + var/mutable_appearance/overlay = mutable_appearance(icon, overlay_state) + overlay.appearance_flags = RESET_COLOR + . += overlay + +/mob/living/basic/space_dragon/melee_attack(obj/vehicle/sealed/mecha/target, list/modifiers, ignore_cooldown) + . = ..() + if (!. || !ismecha(target)) + return + target.take_damage(obj_damage, BRUTE, MELEE) + +/// Before we attack something, check if we want to do something else instead +/mob/living/basic/space_dragon/proc/pre_attack(mob/living/source, atom/target) + SIGNAL_HANDLER + if (target == src) + return COMPONENT_HOSTILE_NO_ATTACK // Easy to misclick yourself, let's not + if (DOING_INTERACTION(source, DOAFTER_SOURCE_SPACE_DRAGON_INTERACTION)) + balloon_alert(source, "busy!") + return COMPONENT_HOSTILE_NO_ATTACK + if (!isliving(target)) + return + var/mob/living/living_target = target + if (living_target.stat != DEAD) + return + INVOKE_ASYNC(src, PROC_REF(try_eat), living_target) + return COMPONENT_HOSTILE_NO_ATTACK + +/// Try putting something inside us +/mob/living/basic/space_dragon/proc/try_eat(mob/living/food) + balloon_alert(src, "swallowing...") + if (do_after(src, 3 SECONDS, target = food)) + eat(food) + +/// Succeed in putting something inside us +/mob/living/basic/space_dragon/proc/eat(mob/living/food) + adjust_health(-food.maxHealth * 0.25) + if (QDELETED(food) || food.loc == src) + return FALSE + playsound(src, 'sound/magic/demon_attack1.ogg', 60, TRUE) + visible_message(span_boldwarning("[src] swallows [food] whole!")) + food.extinguish_mob() // It's wet in there, and our food is likely to be on fire. Let's be decent and not husk them. + food.forceMove(src) + return TRUE + +/mob/living/basic/space_dragon/Entered(atom/movable/arrived, atom/old_loc, list/atom/old_locs) + . = ..() + if (isliving(arrived)) + RegisterSignal(arrived, COMSIG_MOB_STATCHANGE, PROC_REF(eaten_stat_changed)) + +/mob/living/basic/space_dragon/Exited(atom/movable/gone, direction) + . = ..() + if (isliving(gone)) + UnregisterSignal(gone, COMSIG_MOB_STATCHANGE) + +/// Release consumed mobs if they transition from dead to alive +/mob/living/basic/space_dragon/proc/eaten_stat_changed(mob/living/eaten) + SIGNAL_HANDLER + if (eaten.stat == DEAD) + return + new /obj/effect/decal/cleanable/vomit(loc) + playsound(src, 'sound/effects/splat.ogg', vol = 50, vary = TRUE) + visible_message(span_danger("[src] vomits up [eaten]!")) + eaten.forceMove(loc) + eaten.Paralyze(5 SECONDS) + +/mob/living/basic/space_dragon/RangedAttack(atom/target, modifiers) + fire_breath.Trigger(target = target) + +/mob/living/basic/space_dragon/ranged_secondary_attack(atom/target, modifiers) + buffet.Trigger() + +/// When our stat changes, make sure we are using the correct overlay +/mob/living/basic/space_dragon/proc/on_stat_changed() + SIGNAL_HANDLER + update_appearance(UPDATE_OVERLAYS) + +/// We take devastating bomb damage as a random percentage of our maximum health instead of being gibbed +/mob/living/basic/space_dragon/proc/on_exploded(mob/living/source, severity, target, origin) + SIGNAL_HANDLER + if (severity != EXPLODE_DEVASTATE) + return + var/damage_coefficient = rand(devastation_damage_min_percentage, devastation_damage_max_percentage) + adjustBruteLoss(initial(maxHealth)*damage_coefficient) + return COMPONENT_CANCEL_EX_ACT // we handled it + +/// Subtype used by the midround/event +/mob/living/basic/space_dragon/spawn_with_antag + +/mob/living/basic/space_dragon/spawn_with_antag/mind_initialize() + . = ..() + mind.add_antag_datum(/datum/antagonist/space_dragon) + +#undef REJECT_DARK_COLOUR_THRESHOLD +#undef DOAFTER_SOURCE_SPACE_DRAGON_INTERACTION diff --git a/code/modules/mob/living/basic/space_fauna/spider/spider_abilities/lay_eggs.dm b/code/modules/mob/living/basic/space_fauna/spider/spider_abilities/lay_eggs.dm index 28a543be3ac..01477cd8435 100644 --- a/code/modules/mob/living/basic/space_fauna/spider/spider_abilities/lay_eggs.dm +++ b/code/modules/mob/living/basic/space_fauna/spider/spider_abilities/lay_eggs.dm @@ -5,7 +5,6 @@ button_icon_state = "lay_eggs" background_icon_state = "bg_alien" overlay_icon_state = "bg_alien_border" - check_flags = AB_CHECK_CONSCIOUS | AB_CHECK_INCAPACITATED cooldown_time = 0 melee_cooldown_time = 0 shared_cooldown = NONE diff --git a/code/modules/mob/living/basic/space_fauna/spider/spider_abilities/web.dm b/code/modules/mob/living/basic/space_fauna/spider/spider_abilities/web.dm index b7062a2dc17..d4f587c9386 100644 --- a/code/modules/mob/living/basic/space_fauna/spider/spider_abilities/web.dm +++ b/code/modules/mob/living/basic/space_fauna/spider/spider_abilities/web.dm @@ -6,7 +6,6 @@ button_icon_state = "lay_web" background_icon_state = "bg_alien" overlay_icon_state = "bg_alien_border" - check_flags = AB_CHECK_CONSCIOUS | AB_CHECK_INCAPACITATED cooldown_time = 0 SECONDS melee_cooldown_time = 0 shared_cooldown = NONE diff --git a/code/modules/mob/living/basic/space_fauna/spider/spider_abilities/wrap.dm b/code/modules/mob/living/basic/space_fauna/spider/spider_abilities/wrap.dm index 536f09cef8d..e7771f075a8 100644 --- a/code/modules/mob/living/basic/space_fauna/spider/spider_abilities/wrap.dm +++ b/code/modules/mob/living/basic/space_fauna/spider/spider_abilities/wrap.dm @@ -8,7 +8,6 @@ overlay_icon_state = "bg_alien_border" button_icon = 'icons/mob/actions/actions_animal.dmi' button_icon_state = "wrap_0" - check_flags = AB_CHECK_CONSCIOUS | AB_CHECK_INCAPACITATED click_to_activate = TRUE ranged_mousepointer = 'icons/effects/mouse_pointers/wrap_target.dmi' shared_cooldown = NONE diff --git a/code/modules/mob/living/basic/vermin/mouse.dm b/code/modules/mob/living/basic/vermin/mouse.dm index 87d549ac523..6043cceb4b1 100644 --- a/code/modules/mob/living/basic/vermin/mouse.dm +++ b/code/modules/mob/living/basic/vermin/mouse.dm @@ -72,7 +72,7 @@ /mob/living/basic/mouse/examine(mob/user) . = ..() - var/sameside = user.faction_check_mob(src, exact_match = TRUE) + var/sameside = user.faction_check_atom(src, exact_match = TRUE) if(isregalrat(user)) if(sameside) . += span_notice("This rat serves under you.") diff --git a/code/modules/mob/living/carbon/carbon_defines.dm b/code/modules/mob/living/carbon/carbon_defines.dm index c467cd2f001..0cfb9d08c83 100644 --- a/code/modules/mob/living/carbon/carbon_defines.dm +++ b/code/modules/mob/living/carbon/carbon_defines.dm @@ -122,8 +122,6 @@ /// A bitfield of "bodytypes", updated by /obj/item/bodypart/proc/synchronize_bodytypes() var/bodytype = BODYTYPE_HUMANOID | BODYTYPE_ORGANIC - var/is_leaning = FALSE - COOLDOWN_DECLARE(bleeding_message_cd) diff --git a/code/modules/mob/living/carbon/human/_species.dm b/code/modules/mob/living/carbon/human/_species.dm index 22589f09440..6bd93d364d3 100644 --- a/code/modules/mob/living/carbon/human/_species.dm +++ b/code/modules/mob/living/carbon/human/_species.dm @@ -1218,7 +1218,6 @@ GLOBAL_LIST_EMPTY(features_by_species) target.lastattacker = user.real_name target.lastattackerckey = user.ckey - user.dna.species.spec_unarmedattacked(user, target) if(user.limb_destroyer) target.dismembering_strike(user, affecting.body_zone) @@ -1250,9 +1249,6 @@ GLOBAL_LIST_EMPTY(features_by_species) target.StaminaKnockdown(20) //SKYRAT EDIT ADDITION log_combat(user, target, "got a stun punch with their previous punch") -/datum/species/proc/spec_unarmedattacked(mob/living/carbon/human/user, mob/living/carbon/human/target) - return - /datum/species/proc/disarm(mob/living/carbon/human/user, mob/living/carbon/human/target, datum/martial_art/attacker_style) if(target.check_block()) target.visible_message(span_warning("[user]'s shove is blocked by [target]!"), \ @@ -1829,11 +1825,8 @@ GLOBAL_LIST_EMPTY(features_by_species) former_tail_owner.clear_mood_event("tail_balance_lost") former_tail_owner.clear_mood_event("wrong_tail_regained") -///Species override for unarmed attacks because the attack_hand proc was made by a mouth-breathing troglodyte on a tricycle. Also to whoever thought it would be a good idea to make it so the original spec_unarmedattack was not actually linked to unarmed attack needs to be checked by a doctor because they clearly have a vast empty space in their head. -/datum/species/proc/spec_unarmedattack(mob/living/carbon/human/user, atom/target, modifiers) - return FALSE - /* SKYRAT EDIT REMOVAL - MOVED TO MODULAR + /// Returns a list of strings representing features this species has. /// Used by the preferences UI to know what buttons to show. /datum/species/proc/get_features() diff --git a/code/modules/mob/living/carbon/human/species_types/android.dm b/code/modules/mob/living/carbon/human/species_types/android.dm index ed8163a1538..a6f6a484afc 100644 --- a/code/modules/mob/living/carbon/human/species_types/android.dm +++ b/code/modules/mob/living/carbon/human/species_types/android.dm @@ -22,6 +22,7 @@ TRAIT_NOBLOOD, TRAIT_NO_DNA_COPY, TRAIT_NO_TRANSFORMATION_STING, + TRAIT_NOCRITDAMAGE, ) inherent_biotypes = MOB_ROBOTIC|MOB_HUMANOID diff --git a/code/modules/mob/living/carbon/human/species_types/monkeys.dm b/code/modules/mob/living/carbon/human/species_types/monkeys.dm index 2d054c67c71..bcb0a831182 100644 --- a/code/modules/mob/living/carbon/human/species_types/monkeys.dm +++ b/code/modules/mob/living/carbon/human/species_types/monkeys.dm @@ -52,70 +52,13 @@ passtable_on(H, SPECIES_TRAIT) H.dna.add_mutation(/datum/mutation/human/race, MUT_NORMAL) H.dna.activate_mutation(/datum/mutation/human/race) + H.AddElement(/datum/element/human_biter) /datum/species/monkey/on_species_loss(mob/living/carbon/C) . = ..() passtable_off(C, SPECIES_TRAIT) C.dna.remove_mutation(/datum/mutation/human/race) - -/datum/species/monkey/spec_unarmedattack(mob/living/carbon/human/user, atom/target, modifiers) - // If our hands are not blocked, dont try to bite them - if(!HAS_TRAIT(user, TRAIT_HANDS_BLOCKED)) - // if we aren't an advanced tool user, we call attack_paw and cancel the preceeding attack chain - if(!ISADVANCEDTOOLUSER(user)) - target.attack_paw(user, modifiers) - return TRUE - return ..() - - // this shouldn't even be possible, but I'm sure the check was here for a reason - if(!iscarbon(target)) - stack_trace("HEY LISTEN! We are performing a species spec_unarmed attack with a non-carbon user. How did you fuck this up?") - return TRUE - var/mob/living/carbon/victim = target - if(user.is_muzzled()) - return TRUE // cannot bite them if we're muzzled - - var/obj/item/bodypart/affecting - if(ishuman(victim)) - var/mob/living/carbon/human/human_victim = victim - affecting = human_victim.get_bodypart(human_victim.get_random_valid_zone(even_weights = TRUE)) - var/armor = victim.run_armor_check(affecting, MELEE) - - if(prob(MONKEY_SPEC_ATTACK_BITE_MISS_CHANCE)) - victim.visible_message( - span_danger("[user]'s bite misses [victim]!"), - span_danger("You avoid [user]'s bite!"), - span_hear("You hear jaws snapping shut!"), - COMBAT_MESSAGE_RANGE, - user, - ) - to_chat(user, span_danger("Your bite misses [victim]!")) - return TRUE - - var/obj/item/bodypart/head/mouth = user.get_bodypart(BODY_ZONE_HEAD) - if(!mouth) // check for them having a head, ala HARS - return TRUE - - var/damage_roll = rand(mouth.unarmed_damage_low, mouth.unarmed_damage_high) - victim.apply_damage(damage_roll, BRUTE, affecting, armor) - - victim.visible_message( - span_danger("[name] bites [victim]!"), - span_userdanger("[name] bites you!"), - span_hear("You hear a chomp!"), - COMBAT_MESSAGE_RANGE, - name, - ) - to_chat(user, span_danger("You bite [victim]!")) - - if(armor >= 2) // if they have basic armor on the limb we bit, don't spread diseases - return TRUE - for(var/datum/disease/bite_infection as anything in user.diseases) - if(bite_infection.spread_flags & (DISEASE_SPREAD_SPECIAL | DISEASE_SPREAD_NON_CONTAGIOUS)) - continue // ignore diseases that have special spread logic, or are not contagious - victim.ForceContractDisease(bite_infection) - - return TRUE + C.RemoveElement(/datum/element/human_biter) /datum/species/monkey/check_roundstart_eligible() if(check_holidays(MONKEYDAY)) diff --git a/code/modules/mob/living/living_defense.dm b/code/modules/mob/living/living_defense.dm index 01362dfb1ba..454742c3313 100644 --- a/code/modules/mob/living/living_defense.dm +++ b/code/modules/mob/living/living_defense.dm @@ -321,10 +321,6 @@ return martial_result /mob/living/attack_paw(mob/living/carbon/human/user, list/modifiers) - if(isturf(loc) && istype(loc.loc, /area/misc/start)) - to_chat(user, "No attacking people at spawn, you jackass.") - return FALSE - var/martial_result = user.apply_martial_art(src, modifiers) if (martial_result != MARTIAL_ATTACK_INVALID) return martial_result @@ -339,6 +335,8 @@ to_chat(user, span_warning("You don't want to hurt anyone!")) return FALSE + if(!user.get_bodypart(BODY_ZONE_HEAD)) + return FALSE if(user.is_muzzled() || user.is_mouth_covered(ITEM_SLOT_MASK)) to_chat(user, span_warning("You can't bite with your mouth covered!")) return FALSE diff --git a/code/modules/mob/living/simple_animal/friendly/drone/drone_say.dm b/code/modules/mob/living/simple_animal/friendly/drone/drone_say.dm index 88fc3b5cd85..0a89b0f956b 100644 --- a/code/modules/mob/living/simple_animal/friendly/drone/drone_say.dm +++ b/code/modules/mob/living/simple_animal/friendly/drone/drone_say.dm @@ -6,7 +6,7 @@ * * dead_can_hear - Boolean that determines if ghosts can hear the message (`FALSE` by default) * * source - [/atom] source that created the message * * faction_checked_mob - [/mob/living] to determine faction matches from - * * exact_faction_match - Passed to [/mob/proc/faction_check_mob] + * * exact_faction_match - Passed to [/mob/proc/faction_check_atom] */ /proc/_alert_drones(msg, dead_can_hear = FALSE, atom/source, mob/living/faction_checked_mob, exact_faction_match) if (dead_can_hear && source) @@ -17,7 +17,7 @@ var/mob/living/simple_animal/drone/D = i if(istype(D) && D.stat != DEAD) if(faction_checked_mob) - if(D.faction_check_mob(faction_checked_mob, exact_faction_match)) + if(D.faction_check_atom(faction_checked_mob, exact_faction_match)) to_chat(D, msg) else to_chat(D, msg) @@ -28,7 +28,7 @@ * Wraps [/proc/_alert_drones] with defaults * * * source - `src` - * * faction_check_mob - `src` + * * faction_check_atom - `src` * * dead_can_hear - `TRUE` */ /mob/living/simple_animal/drone/proc/alert_drones(msg, dead_can_hear = FALSE) diff --git a/code/modules/mob/living/simple_animal/hostile/hostile.dm b/code/modules/mob/living/simple_animal/hostile/hostile.dm index 305853adb96..96ae60c3e07 100644 --- a/code/modules/mob/living/simple_animal/hostile/hostile.dm +++ b/code/modules/mob/living/simple_animal/hostile/hostile.dm @@ -263,7 +263,7 @@ if(search_objects < 2) if(isliving(the_target)) var/mob/living/L = the_target - var/faction_check = faction_check_mob(L) + var/faction_check = faction_check_atom(L) if(robust_searching) if(faction_check && !attack_same) return FALSE @@ -433,7 +433,7 @@ playsound(loc, 'sound/machines/chime.ogg', 50, TRUE, -1) var/atom/target_from = GET_TARGETS_FROM(src) for(var/mob/living/simple_animal/hostile/M in oview(distance, target_from)) - if(faction_check_mob(M, TRUE)) + if(faction_check_atom(M, TRUE)) if(M.AIStatus == AI_OFF) return else @@ -445,7 +445,7 @@ for(var/mob/living/L in T) if(L == src || L == A) continue - if(faction_check_mob(L) && !attack_same) + if(faction_check_atom(L) && !attack_same) return TRUE /mob/living/simple_animal/hostile/proc/OpenFire(atom/A) diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/bubblegum.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/bubblegum.dm index 02d9e582b1a..ec90fa9fa7b 100644 --- a/code/modules/mob/living/simple_animal/hostile/megafauna/bubblegum.dm +++ b/code/modules/mob/living/simple_animal/hostile/megafauna/bubblegum.dm @@ -137,7 +137,7 @@ Difficulty: Hard . = list() for(var/mob/living/L in targets) var/list/bloodpool = get_bloodcrawlable_pools(get_turf(L), 0) - if(bloodpool.len && (!faction_check_mob(L) || L.stat == DEAD)) + if(bloodpool.len && (!faction_check_atom(L) || L.stat == DEAD)) . += L /** @@ -201,7 +201,7 @@ Difficulty: Hard new /obj/effect/temp_visual/bubblegum_hands/leftsmack(T) SLEEP_CHECK_DEATH(4, src) for(var/mob/living/L in T) - if(!faction_check_mob(L)) + if(!faction_check_atom(L)) to_chat(L, span_userdanger("[src] rends you!")) playsound(T, attack_sound, 100, TRUE, -1) var/limb_to_hit = L.get_bodypart(L.get_random_valid_zone(even_weights = TRUE)) @@ -217,7 +217,7 @@ Difficulty: Hard new /obj/effect/temp_visual/bubblegum_hands/leftthumb(T) SLEEP_CHECK_DEATH(6, src) for(var/mob/living/L in T) - if(!faction_check_mob(L)) + if(!faction_check_atom(L)) if(L.stat != CONSCIOUS) to_chat(L, span_userdanger("[src] drags you through the blood!")) playsound(T, 'sound/magic/enter_blood.ogg', 100, TRUE, -1) diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/drake.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/drake.dm index 84e2d9c049b..5aef5c9029b 100644 --- a/code/modules/mob/living/simple_animal/hostile/megafauna/drake.dm +++ b/code/modules/mob/living/simple_animal/hostile/megafauna/drake.dm @@ -1,7 +1,3 @@ -///used whenever the drake generates a hotspot -#define DRAKE_FIRE_TEMP 500 -///used whenever the drake generates a hotspot -#define DRAKE_FIRE_EXPOSURE 50 ///used to see if the drake is enraged or not #define DRAKE_ENRAGED (health < maxHealth*0.5) @@ -175,36 +171,6 @@ remove_atom_colour(TEMPORARY_COLOUR_PRIORITY) set_light_range(initial(light_range)) -//fire line keeps going even if dragon is deleted -/proc/dragon_fire_line(atom/source, list/turfs, frozen = FALSE) - var/list/hit_list = list() - for(var/turf/T in turfs) - if(isclosedturf(T)) - break - var/obj/effect/hotspot/drake_fire_hotspot = new /obj/effect/hotspot(T) - if(frozen) - drake_fire_hotspot.add_atom_colour(COLOR_BLUE_LIGHT, FIXED_COLOUR_PRIORITY) - T.hotspot_expose(DRAKE_FIRE_TEMP,DRAKE_FIRE_EXPOSURE,1) - for(var/mob/living/L in T.contents) - if(L in hit_list || istype(L, source.type)) - continue - hit_list += L - if(!frozen) - L.adjustFireLoss(20) - to_chat(L, span_userdanger("You're hit by [source]'s fire breath!")) - continue - L.adjustFireLoss(10) - L.apply_status_effect(/datum/status_effect/ice_block_talisman, 20) - to_chat(L, span_userdanger("You're hit by [source]'s freezing breath!")) - - // deals damage to mechs - for(var/obj/vehicle/sealed/mecha/M in T.contents) - if(M in hit_list) - continue - hit_list += M - M.take_damage(45, BRUTE, MELEE, 1) - sleep(0.15 SECONDS) - /mob/living/simple_animal/hostile/megafauna/dragon/ex_act(severity, target) if(severity <= EXPLODE_LIGHT) return FALSE @@ -371,8 +337,5 @@ return #undef DRAKE_ENRAGED -#undef DRAKE_FIRE_EXPOSURE -#undef DRAKE_FIRE_TEMP - #undef SWOOP_DAMAGEABLE #undef SWOOP_INVULNERABLE diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/hierophant.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/hierophant.dm index 828a78ccfb1..e20724227f1 100644 --- a/code/modules/mob/living/simple_animal/hostile/megafauna/hierophant.dm +++ b/code/modules/mob/living/simple_animal/hostile/megafauna/hierophant.dm @@ -694,7 +694,7 @@ Difficulty: Hard return for(var/mob/living/L in T.contents - hit_things) //find and damage mobs... hit_things += L - if((friendly_fire_check && caster?.faction_check_mob(L)) || L.stat == DEAD) + if((friendly_fire_check && caster?.faction_check_atom(L)) || L.stat == DEAD) continue if(L.client) flash_color(L.client, "#660099", 1) @@ -719,7 +719,7 @@ Difficulty: Hard hit_things += M for(var/O in M.occupants) var/mob/living/occupant = O - if(friendly_fire_check && caster?.faction_check_mob(occupant)) + if(friendly_fire_check && caster?.faction_check_atom(occupant)) continue to_chat(occupant, span_userdanger("Your [M.name] is struck by a [name]!")) playsound(M,'sound/weapons/sear.ogg', 50, TRUE, -4) diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/legion.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/legion.dm index 777cb3b878f..de693bde9ea 100644 --- a/code/modules/mob/living/simple_animal/hostile/megafauna/legion.dm +++ b/code/modules/mob/living/simple_animal/hostile/megafauna/legion.dm @@ -269,14 +269,14 @@ density = TRUE layer = ABOVE_OBJ_LAYER armor_type = /datum/armor/structure_legionturret + //Compared with the targeted mobs. If they have the faction, turret won't shoot. + faction = list(FACTION_MINING) ///What kind of projectile the actual damaging part should be. var/projectile_type = /obj/projectile/beam/legion ///Time until the tracer gets shot var/initial_firing_time = 18 ///How long it takes between shooting the tracer and the projectile. var/shot_delay = 8 - ///Compared with the targeted mobs. If they have the faction, turret won't shoot. - var/faction = list(FACTION_MINING) /datum/armor/structure_legionturret laser = 100 diff --git a/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/elite.dm b/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/elite.dm index 6fe1fa1ecfc..fcfa4560611 100644 --- a/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/elite.dm +++ b/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/elite.dm @@ -37,7 +37,7 @@ /mob/living/simple_animal/hostile/asteroid/elite/AttackingTarget() if(ishostile(target)) var/mob/living/simple_animal/hostile/M = target - if(faction_check_mob(M)) + if(faction_check_atom(M)) return FALSE if(istype(target, /obj/structure/elite_tumor)) var/obj/structure/elite_tumor/T = target diff --git a/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/herald.dm b/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/herald.dm index bf4d33a10ed..aa61c128e3f 100644 --- a/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/herald.dm +++ b/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/herald.dm @@ -234,7 +234,7 @@ /obj/projectile/herald/on_hit(atom/target, blocked = FALSE) if(ismob(target) && ismob(firer)) var/mob/living/mob_target = target - if(mob_target.faction_check_mob(firer)) + if(mob_target.faction_check_atom(firer)) damage = 0 . = ..() diff --git a/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/legionnaire.dm b/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/legionnaire.dm index ec6c843080c..926f4e96baa 100644 --- a/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/legionnaire.dm +++ b/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/legionnaire.dm @@ -149,7 +149,7 @@ var/throwtarget = get_edge_target_turf(src, move_dir) for(var/mob/living/trample_target in T.contents - hit_things - src) hit_things += trample_target - if(faction_check_mob(trample_target)) + if(faction_check_atom(trample_target)) continue visible_message(span_boldwarning("[src] tramples and kicks [trample_target]!")) to_chat(trample_target, span_userdanger("[src] tramples you and kicks you away!")) diff --git a/code/modules/mob/living/simple_animal/hostile/mining_mobs/gutlunch.dm b/code/modules/mob/living/simple_animal/hostile/mining_mobs/gutlunch.dm index 92ad5f35927..7a3451e4ef8 100644 --- a/code/modules/mob/living/simple_animal/hostile/mining_mobs/gutlunch.dm +++ b/code/modules/mob/living/simple_animal/hostile/mining_mobs/gutlunch.dm @@ -60,7 +60,7 @@ if(isliving(the_target)) var/mob/living/L = the_target - if(faction_check_mob(L) && !attack_same) + if(faction_check_atom(L) && !attack_same) return FALSE if(L.stat > stat_attack || L.stat != stat_attack && stat_exclusive) return FALSE diff --git a/code/modules/mob/living/simple_animal/hostile/retaliate/retaliate.dm b/code/modules/mob/living/simple_animal/hostile/retaliate/retaliate.dm index 237360468f8..bf1c12d5da1 100644 --- a/code/modules/mob/living/simple_animal/hostile/retaliate/retaliate.dm +++ b/code/modules/mob/living/simple_animal/hostile/retaliate/retaliate.dm @@ -37,7 +37,7 @@ continue if(isliving(A)) var/mob/living/M = A - if(faction_check_mob(M) && attack_same || !faction_check_mob(M)) + if(faction_check_atom(M) && attack_same || !faction_check_atom(M)) enemies |= WEAKREF(M) else if(ismecha(A)) var/obj/vehicle/sealed/mecha/M = A @@ -46,7 +46,7 @@ add_enemies(M.occupants) for(var/mob/living/simple_animal/hostile/retaliate/H in around) - if(faction_check_mob(H) && !attack_same && !H.attack_same) + if(faction_check_atom(H) && !attack_same && !H.attack_same) H.enemies |= enemies /mob/living/simple_animal/hostile/retaliate/adjustHealth(amount, updating_health = TRUE, forced = FALSE) diff --git a/code/modules/mob/living/simple_animal/hostile/space_dragon.dm b/code/modules/mob/living/simple_animal/hostile/space_dragon.dm deleted file mode 100644 index c536da22cd1..00000000000 --- a/code/modules/mob/living/simple_animal/hostile/space_dragon.dm +++ /dev/null @@ -1,444 +0,0 @@ -/// The darkness threshold for space dragon when choosing a color -#define DARKNESS_THRESHOLD 50 -/// Any interactions executed by the space dragon -#define DOAFTER_SOURCE_SPACE_DRAGON_INTERACTION "space dragon interaction" - -/** - * # Space Dragon - * - * A space-faring leviathan-esque monster which breathes fire and summons carp. Spawned during its respective midround antagonist event. - * - * A space-faring monstrosity who has the ability to breathe dangerous fire breath and uses its powerful wings to knock foes away. - * Normally spawned as an antagonist during the Space Dragon event, Space Dragon's main goal is to open three rifts from which to pull a great tide of carp onto the station. - * Space Dragon can summon only one rift at a time, and can do so anywhere a blob is allowed to spawn. In order to trigger his victory condition, Space Dragon must summon and defend three rifts while they charge. - * Space Dragon, when spawned, has five minutes to summon the first rift. Failing to do so will cause Space Dragon to return from whence he came. - * When the rift spawns, ghosts can interact with it to spawn in as space carp to help complete the mission. One carp is granted when the rift is first summoned, with an extra one every 30 seconds. - * Once the victory condition is met, all current rifts become invulnerable to damage, are allowed to spawn infinite sentient space carp, and Space Dragon gets unlimited rage. - * Alternatively, if the shuttle arrives while Space Dragon is still active, their victory condition will automatically be met and all the rifts will immediately become fully charged. - * If a charging rift is destroyed, Space Dragon will be incredibly slowed, and the endlag on his gust attack is greatly increased on each use. - * Space Dragon has the following abilities to assist him with his objective: - * - Can shoot fire in straight line, dealing 30 burn damage and setting those suseptible on fire. - * - Can use his wings to temporarily stun and knock back any nearby mobs. This attack has no cooldown, but instead has endlag after the attack where Space Dragon cannot act. This endlag's time decreases over time, but is added to every time he uses the move. - * - Can swallow mob corpses to heal for half their max health. Any corpses swallowed are stored within him, and will be regurgitated on death. - * - Can tear through any type of wall. This takes 4 seconds for most walls, and 12 seconds for reinforced walls. - */ -/mob/living/simple_animal/hostile/space_dragon - name = "Space Dragon" - desc = "A vile, leviathan-esque creature that flies in the most unnatural way. Looks slightly similar to a space carp." - gender = NEUTER - maxHealth = 400 - health = 400 - damage_coeff = list(BRUTE = 1, BURN = 1, TOX = 1, CLONE = 1, STAMINA = 0.5, OXY = 1) - combat_mode = TRUE - speed = 0 - movement_type = FLYING - attack_verb_continuous = "chomps" - attack_verb_simple = "chomp" - attack_sound = 'sound/magic/demon_attack1.ogg' - attack_vis_effect = ATTACK_EFFECT_BITE - death_sound = 'sound/creatures/space_dragon_roar.ogg' - icon = 'icons/mob/nonhuman-player/spacedragon.dmi' - icon_state = "spacedragon" - icon_living = "spacedragon" - icon_dead = "spacedragon_dead" - health_doll_icon = "spacedragon" - obj_damage = 50 - environment_smash = ENVIRONMENT_SMASH_NONE - flags_1 = PREVENT_CONTENTS_EXPLOSION_1 - melee_damage_upper = 35 - melee_damage_lower = 35 - mob_size = MOB_SIZE_LARGE - armour_penetration = 30 - pixel_x = -16 - base_pixel_x = -16 - maptext_height = 64 - maptext_width = 64 - turns_per_move = 5 - ranged = TRUE - mouse_opacity = MOUSE_OPACITY_ICON - butcher_results = list(/obj/item/stack/ore/diamond = 5, /obj/item/stack/sheet/sinew = 5, /obj/item/stack/sheet/bone = 30) - death_message = "screeches as its wings turn to dust and it collapses on the floor, its life extinguished." - atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_plas" = 0, "max_plas" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0) - minbodytemp = 0 - maxbodytemp = 1500 - faction = list(FACTION_CARP) - pressure_resistance = 200 - /// How much endlag using Wing Gust should apply. Each use of wing gust increments this, and it decreases over time. - var/tiredness = 0 - /// A multiplier to how much each use of wing gust should add to the tiredness variable. Set to 5 if the current rift is destroyed. - var/tiredness_mult = 1 - /// The distance Space Dragon's gust reaches - var/gust_distance = 4 - /// The amount of tiredness to add to Space Dragon per use of gust - var/gust_tiredness = 30 - /// Determines whether or not Space Dragon is in the middle of using wing gust. If set to true, prevents him from moving and doing certain actions. - var/using_special = FALSE - /// The color of the space dragon. - var/chosen_color - /// Minimum devastation damage dealt coefficient based on max health - var/devastation_damage_min_percentage = 0.4 - /// Maximum devastation damage dealt coefficient based on max health - var/devastation_damage_max_percentage = 0.75 - -/mob/living/simple_animal/hostile/space_dragon/Initialize(mapload) - . = ..() - AddComponent(/datum/component/seethrough_mob) - AddElement(/datum/element/simple_flying) - add_traits(list(TRAIT_SPACEWALK, TRAIT_FREE_HYPERSPACE_MOVEMENT, TRAIT_NO_FLOATING_ANIM, TRAIT_HEALS_FROM_CARP_RIFTS), INNATE_TRAIT) - AddElement(/datum/element/content_barfer) - RegisterSignal(src, COMSIG_LIVING_UNARMED_ATTACK, PROC_REF(before_attack)) - -/mob/living/simple_animal/hostile/space_dragon/Login() - . = ..() - if(!chosen_color) - dragon_name() - color_selection() - -/mob/living/simple_animal/hostile/space_dragon/ex_act_devastate() - var/damage_coefficient = rand(devastation_damage_min_percentage, devastation_damage_max_percentage) - adjustBruteLoss(initial(maxHealth)*damage_coefficient) - -/mob/living/simple_animal/hostile/space_dragon/Life(seconds_per_tick = SSMOBS_DT, times_fired) - . = ..() - tiredness = max(tiredness - (0.5 * seconds_per_tick), 0) - -/mob/living/simple_animal/hostile/space_dragon/Entered(atom/movable/arrived, atom/old_loc, list/atom/old_locs) - . = ..() - if (isliving(arrived)) - RegisterSignal(arrived, COMSIG_MOB_STATCHANGE, PROC_REF(eaten_stat_changed)) - -/mob/living/simple_animal/hostile/space_dragon/Exited(atom/movable/gone, direction) - . = ..() - if (isliving(gone)) - UnregisterSignal(gone, COMSIG_MOB_STATCHANGE) - -/// Release consumed mobs if they transition from dead to alive -/mob/living/simple_animal/hostile/space_dragon/proc/eaten_stat_changed(mob/living/eaten) - SIGNAL_HANDLER - if (eaten.stat == DEAD) - return - playsound(src, 'sound/effects/splat.ogg', vol = 50, vary = TRUE) - visible_message(span_danger("[src] vomits up [eaten]!")) - eaten.forceMove(loc) - eaten.Paralyze(5 SECONDS) - -/mob/living/simple_animal/hostile/space_dragon/proc/before_attack(datum/source, atom/target) - SIGNAL_HANDLER - if(using_special) - return COMPONENT_CANCEL_ATTACK_CHAIN - - if(target == src) - to_chat(src, span_warning("You almost bite yourself, but then decide against it.")) - return COMPONENT_CANCEL_ATTACK_CHAIN - - if(DOING_INTERACTION(src, DOAFTER_SOURCE_SPACE_DRAGON_INTERACTION)) // patience grasshopper - target.balloon_alert(src, "finish current action first!") - return COMPONENT_CANCEL_ATTACK_CHAIN - - if(ismecha(target)) - target.take_damage(50, BRUTE, MELEE, 1) - return // don't block the rest of the attack chain - - if(iswallturf(target)) - INVOKE_ASYNC(src, PROC_REF(tear_down_wall), target) - return COMPONENT_CANCEL_ATTACK_CHAIN - - if(isliving(target)) //Swallows corpses like a snake to regain health. - var/mob/living/living_target = target - if(living_target.stat != DEAD) - return // go ham on slapping the shit out of them buddy - - INVOKE_ASYNC(src, PROC_REF(eat_this_corpse), living_target) - return COMPONENT_CANCEL_ATTACK_CHAIN - -/// Handles tearing down a wall. Returns TRUE if successful, FALSE otherwise. -/mob/living/simple_animal/hostile/space_dragon/proc/tear_down_wall(turf/closed/wall/wall_target) - to_chat(src, span_warning("You begin tearing through the wall...")) - playsound(src, 'sound/machines/airlock_alien_prying.ogg', 100, TRUE) - - var/time_to_tear = 4 SECONDS - if(istype(wall_target, /turf/closed/wall/r_wall)) - time_to_tear = 12 SECONDS - - if(!do_after(src, time_to_tear, target = wall_target, interaction_key = DOAFTER_SOURCE_SPACE_DRAGON_INTERACTION)) - return FALSE - - if(isopenturf(wall_target)) - return FALSE // well the thing was destroyed while we were sleeping so that's nice, but we didn't successfully tear it down. whatever - - wall_target.dismantle_wall(devastated = TRUE) - playsound(src, 'sound/effects/meteorimpact.ogg', 100, TRUE) - return TRUE - -/// Handles eating a corpse, giving us a bit of health back. Returns TRUE if we were sucessful in eating, FALSE otherwise. -/mob/living/simple_animal/hostile/space_dragon/proc/eat_this_corpse(mob/living/corpse) - to_chat(src, span_warning("You begin to swallow the body of [corpse] whole...")) - - if(!do_after(src, 3 SECONDS, target = corpse, interaction_key = DOAFTER_SOURCE_SPACE_DRAGON_INTERACTION)) - return FALSE - if(!eat(corpse)) - return FALSE - - adjustHealth(-(corpse.maxHealth * 0.25)) - return TRUE - -/mob/living/simple_animal/hostile/space_dragon/ranged_secondary_attack(atom/target, modifiers) - if(using_special) - return - using_special = TRUE - icon_state = "spacedragon_gust" - add_dragon_overlay() - useGust(0) - -/mob/living/simple_animal/hostile/space_dragon/Move() - if(!using_special) - ..() - -/mob/living/simple_animal/hostile/space_dragon/OpenFire() - if(using_special) - return - ranged_cooldown = world.time + ranged_cooldown_time - fire_stream() - -/mob/living/simple_animal/hostile/space_dragon/death(gibbed) - . = ..() - add_dragon_overlay() - -/mob/living/simple_animal/hostile/space_dragon/revive(full_heal_flags = NONE, excess_healing = 0, force_grab_ghost = FALSE) - . = ..() - add_dragon_overlay() - -/** - * Allows space dragon to choose its own name. - * - * Prompts the space dragon to choose a name, which it will then apply to itself. - * If the name is invalid, will re-prompt the dragon until a proper name is chosen. - */ -/mob/living/simple_animal/hostile/space_dragon/proc/dragon_name() - var/chosen_name = sanitize_name(reject_bad_text(tgui_input_text(src, "What would you like your name to be?", "Choose Your Name", real_name, MAX_NAME_LEN))) - if(!chosen_name) - to_chat(src, span_warning("Not a valid name, please try again.")) - dragon_name() - return - to_chat(src, span_notice("Your name is now [span_name("[chosen_name]")], the feared Space Dragon.")) - fully_replace_character_name(null, chosen_name) - -/** - * Allows space dragon to choose a color for itself. - * - * Prompts the space dragon to choose a color, from which it will then apply to itself. - * If an invalid color is given, will re-prompt the dragon until a proper color is chosen. - */ -/mob/living/simple_animal/hostile/space_dragon/proc/color_selection() - chosen_color = input(src,"What would you like your color to be?","Choose Your Color", COLOR_WHITE) as color|null - if(!chosen_color) //redo proc until we get a color - to_chat(src, span_warning("Not a valid color, please try again.")) - color_selection() - return - var/temp_hsv = RGBtoHSV(chosen_color) - if(ReadHSV(temp_hsv)[3] < DARKNESS_THRESHOLD) - to_chat(src, span_danger("Invalid color. Your color is not bright enough.")) - color_selection() - return - add_atom_colour(chosen_color, FIXED_COLOUR_PRIORITY) - add_dragon_overlay() - -/** - * Adds the proper overlay to the space dragon. - * - * Clears the current overlay on space dragon and adds a proper one for whatever animation he's in. - */ -/mob/living/simple_animal/hostile/space_dragon/proc/add_dragon_overlay() - cut_overlays() - if(stat == DEAD) - var/mutable_appearance/overlay = mutable_appearance(icon, "overlay_dead") - overlay.appearance_flags = RESET_COLOR - add_overlay(overlay) - return - if(!using_special) - var/mutable_appearance/overlay = mutable_appearance(icon, "overlay_base") - overlay.appearance_flags = RESET_COLOR - add_overlay(overlay) - return - if(using_special) - var/mutable_appearance/overlay = mutable_appearance(icon, "overlay_gust") - overlay.appearance_flags = RESET_COLOR - add_overlay(overlay) - -/** - * Determines a line of turfs from sources's position to the target with length range. - * - * Determines a line of turfs from the source's position to the target with length range. - * The line will extend on past the target if the range is large enough, and not reach the target if range is small enough. - * Arguments: - * * offset - whether or not to aim slightly to the left or right of the target - * * range - how many turfs should we go out for - * * atom/at - The target - */ -/mob/living/simple_animal/hostile/space_dragon/proc/line_target(offset, range, atom/at = target) - if(!at) - return - var/angle = ATAN2(at.x - src.x, at.y - src.y) + offset - var/turf/T = get_turf(src) - for(var/i in 1 to range) - var/turf/check = locate(src.x + cos(angle) * i, src.y + sin(angle) * i, src.z) - if(!check) - break - T = check - return (get_line(src, T) - get_turf(src)) - -/** - * Spawns fire at each position in a line from the source to the target. - * - * Spawns fire at each position in a line from the source to the target. - * Stops if it comes into contact with a solid wall, a window, or a door. - * Delays the spawning of each fire by 1.5 deciseconds. - * Arguments: - * * atom/at - The target - */ -/mob/living/simple_animal/hostile/space_dragon/proc/fire_stream(atom/at = target) - playsound(get_turf(src),'sound/magic/fireball.ogg', 200, TRUE) - var/range = 20 - var/list/turfs = list() - var/list/hit_list_parameter = list(src) - turfs = line_target(0, range, at) - var/delayFire = -1.0 - for(var/turf/T in turfs) - if(isclosedturf(T)) - return - for(var/obj/structure/window/W in T.contents) - return - for(var/obj/machinery/door/D in T.contents) - if(D.density) - return - delayFire += 1.0 - addtimer(CALLBACK(src, PROC_REF(dragon_fire_line), T, hit_list_parameter), delayFire) - -/** - * What occurs on each tile to actually create the fire. - * - * Creates a fire on the given turf. - * It creates a hotspot on the given turf, damages any living mob with 30 burn damage, and damages mechs by 50. - * It can only hit any given target once. - * Arguments: - * * turf/T - The turf to trigger the effects on. - * * list/hit_list - The list of targets that have already been hit in the fire_stream. - */ -/mob/living/simple_animal/hostile/space_dragon/proc/dragon_fire_line(turf/fire_turf, list/hit_list) - new /obj/effect/hotspot(fire_turf) - fire_turf.hotspot_expose(700,50,1) - for(var/mob/living/living_target in fire_turf.contents) - if(living_target.faction_check_mob(src) && living_target != src) - hit_list += living_target - start_carp_speedboost(living_target) - if(living_target in hit_list) - continue - if(living_target.mind?.has_antag_datum(/datum/antagonist/space_carp)) - continue - hit_list += living_target - living_target.adjustFireLoss(30) - to_chat(living_target, span_userdanger("You're hit by [src]'s fire breath!")) - // deals damage to mechs - for(var/obj/vehicle/sealed/mecha/mech_target in fire_turf.contents) - if(mech_target in hit_list) - continue - hit_list += mech_target - mech_target.take_damage(50, BRUTE, MELEE, 1) - -/** - * Applies the speed boost to carps when hit by space dragon's flame breath - * - * Applies the dragon rage effect to carps temporarily, giving them a glow and a speed boost. - * This lasts for 8 seconds. - * Arguments: - * * mob/living/target - The carp being affected. - */ -/mob/living/simple_animal/hostile/space_dragon/proc/start_carp_speedboost(mob/living/target) - target.add_filter("anger_glow", 3, list("type" = "outline", "color" = "#ff330030", "size" = 2)) - target.add_movespeed_modifier(/datum/movespeed_modifier/dragon_rage) - addtimer(CALLBACK(src, PROC_REF(end_carp_speedboost), target), 8 SECONDS) - -/** - * Remove the speed boost from carps when hit by space dragon's flame breath - * - * Removes the dragon rage effect from carps, removing their glow and speed boost. - * Arguments: - * * mob/living/target - The carp being affected. - */ -/mob/living/simple_animal/hostile/space_dragon/proc/end_carp_speedboost(mob/living/target) - target.remove_filter("anger_glow") - target.remove_movespeed_modifier(/datum/movespeed_modifier/dragon_rage) - -/** - * Handles consuming and storing consumed things inside Space Dragon - * - * Plays a sound and then stores the consumed thing inside Space Dragon. - * Used in AttackingTarget(), paired with a heal should it succeed. - * Arguments: - * * atom/movable/A - The thing being consumed - */ -/mob/living/simple_animal/hostile/space_dragon/proc/eat(atom/movable/A) - if(A && A.loc != src) - playsound(src, 'sound/magic/demon_attack1.ogg', 60, TRUE) - visible_message(span_warning("[src] swallows [A] whole!")) - to_chat(src, span_notice("Your acids cleanse the flames off [A] on the way down. Delicious!")) - A.extinguish() - A.forceMove(src) - return TRUE - return FALSE - -/** - * Resets Space Dragon's status after using wing gust. - * - * Resets Space Dragon's status after using wing gust. - * If it isn't dead by the time it calls this method, reset the sprite back to the normal living sprite. - * Also sets the using_special variable to FALSE, allowing Space Dragon to move and attack freely again. - */ -/mob/living/simple_animal/hostile/space_dragon/proc/reset_status() - if(stat != DEAD) - icon_state = "spacedragon" - using_special = FALSE - add_dragon_overlay() - -/** - * Handles wing gust from the windup all the way to the endlag at the end. - * - * Handles the wing gust attack from start to finish, based on the timer. - * When intially triggered, starts at 0. Until the timer reaches 10, increase Space Dragon's y position by 2 and call back to the function in 1.5 deciseconds. - * When the timer is at 10, trigger the attack. Change Space Dragon's sprite. reset his y position, and push all living creatures back in a 3 tile radius and stun them for 5 seconds. - * Stay in the ending state for how much our tiredness dictates and add to our tiredness. - * Arguments: - * * timer - The timer used for the windup. - */ -/mob/living/simple_animal/hostile/space_dragon/proc/useGust(timer) - if(timer != 10) - pixel_y = pixel_y + 2; - addtimer(CALLBACK(src, PROC_REF(useGust), timer + 1), 1.2) - return - pixel_y = 0 - icon_state = "spacedragon_gust_2" - cut_overlays() - var/mutable_appearance/overlay = mutable_appearance(icon, "overlay_gust_2") - overlay.appearance_flags = RESET_COLOR - add_overlay(overlay) - playsound(src, 'sound/effects/gravhit.ogg', 100, TRUE) - for (var/mob/living/candidate in view(gust_distance, src)) - if(candidate == src || candidate.faction_check_mob(src)) - continue - visible_message(span_boldwarning("[candidate] is knocked back by the gust!")) - to_chat(candidate, span_userdanger("You're knocked back by the gust!")) - var/dir_to_target = get_dir(get_turf(src), get_turf(candidate)) - var/throwtarget = get_edge_target_turf(target, dir_to_target) - candidate.safe_throw_at(throwtarget, 10, 1, src) - candidate.Paralyze(50) - addtimer(CALLBACK(src, PROC_REF(reset_status)), 4 + ((tiredness * tiredness_mult) / 10)) - tiredness = tiredness + (gust_tiredness * tiredness_mult) - -/mob/living/simple_animal/hostile/space_dragon/spawn_with_antag - -/mob/living/simple_animal/hostile/space_dragon/spawn_with_antag/mind_initialize() - . = ..() - mind.add_antag_datum(/datum/antagonist/space_dragon) - -#undef DARKNESS_THRESHOLD -#undef DOAFTER_SOURCE_SPACE_DRAGON_INTERACTION diff --git a/code/modules/mob/living/simple_animal/simple_animal.dm b/code/modules/mob/living/simple_animal/simple_animal.dm index 85c146b29c8..4c382a59b2f 100644 --- a/code/modules/mob/living/simple_animal/simple_animal.dm +++ b/code/modules/mob/living/simple_animal/simple_animal.dm @@ -509,7 +509,7 @@ else if(!is_child && M.gender == MALE && !(M.flags_1 & HOLOGRAM_1)) //Better safe than sorry ;_; partner = M - else if(isliving(M) && !faction_check_mob(M)) //shyness check. we're not shy in front of things that share a faction with us. + else if(isliving(M) && !faction_check_atom(M)) //shyness check. we're not shy in front of things that share a faction with us. return //we never mate when not alone, so just abort early if(alone && partner && children < 3) diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm index 9002033a13e..e5ddcf1f0ae 100644 --- a/code/modules/mob/mob.dm +++ b/code/modules/mob/mob.dm @@ -1202,21 +1202,7 @@ ///Can this mob use storage /mob/proc/canUseStorage() return FALSE -/** - * Check if the other mob has any factions the same as us - * - * If exact match is set, then all our factions must match exactly - */ -/mob/proc/faction_check_mob(mob/target, exact_match) - if(exact_match) //if we need an exact match, we need to do some bullfuckery. - var/list/faction_src = faction.Copy() - var/list/faction_target = target.faction.Copy() - if(!("[REF(src)]" in faction_target)) //if they don't have our ref faction, remove it from our factions list. - faction_src -= "[REF(src)]" //if we don't do this, we'll never have an exact match. - if(!("[REF(target)]" in faction_src)) - faction_target -= "[REF(target)]" //same thing here. - return faction_check(faction_src, faction_target, TRUE) - return faction_check(faction, target.faction, FALSE) + /* * Compare two lists of factions, returning true if any match * diff --git a/code/modules/mob/mob_defines.dm b/code/modules/mob/mob_defines.dm index 12905700318..c5aac5f526e 100644 --- a/code/modules/mob/mob_defines.dm +++ b/code/modules/mob/mob_defines.dm @@ -20,6 +20,8 @@ // we never want to hide a turf because it's not lit // We can rely on the lighting plane to handle that for us see_in_dark = 1e6 + // A list of factions that this mob is currently in, for hostile mob targetting, amongst other things + faction = list(FACTION_NEUTRAL) /// The current client inhabiting this mob. Managed by login/logout /// This exists so we can do cleanup in logout for occasions where a client was transfere rather then destroyed /// We need to do this because the mob on logout never actually has a reference to client @@ -144,9 +146,6 @@ /// What job does this mob have var/job = null//Living - /// A list of factions that this mob is currently in, for hostile mob targetting, amongst other things - var/list/faction = list(FACTION_NEUTRAL) - /// Can this mob enter shuttles var/move_on_shuttle = 1 diff --git a/code/modules/mob_spawn/mob_spawn.dm b/code/modules/mob_spawn/mob_spawn.dm index 02b3ea1866f..3f5dd81c184 100644 --- a/code/modules/mob_spawn/mob_spawn.dm +++ b/code/modules/mob_spawn/mob_spawn.dm @@ -11,8 +11,6 @@ var/mob_name ///the type of the mob, you best inherit this var/mob_type = /mob/living/basic/cockroach - ///Lazy string list of factions that the spawned mob will be in upon spawn - var/list/faction ////Human specific stuff. Don't set these if you aren't using a human, the unit tests will put a stop to your sinful hand. diff --git a/code/modules/mod/mod_core.dm b/code/modules/mod/mod_core.dm index 45fa61677b2..d5c43497982 100644 --- a/code/modules/mod/mod_core.dm +++ b/code/modules/mod/mod_core.dm @@ -399,7 +399,7 @@ SIGNAL_HANDLER if(mod.active) particle_effect = new(mod.wearer, /particles/pollen, PARTICLE_ATTACH_MOB) - mob_spawner = mod.wearer.AddComponent(/datum/component/spawner, spawn_types=list(spawned_mob_type), spawn_time=5 SECONDS, max_spawned=3) + mob_spawner = mod.wearer.AddComponent(/datum/component/spawner, spawn_types=list(spawned_mob_type), spawn_time=5 SECONDS, max_spawned=3, faction=mod.wearer.faction) RegisterSignal(mob_spawner, COMSIG_SPAWNER_SPAWNED, PROC_REF(new_mob)) RegisterSignal(mod.wearer, COMSIG_MOVABLE_MOVED, PROC_REF(spread_flowers)) diff --git a/code/modules/mod/modules/modules_ninja.dm b/code/modules/mod/modules/modules_ninja.dm index 7a38238594d..31db6017609 100644 --- a/code/modules/mod/modules/modules_ninja.dm +++ b/code/modules/mod/modules/modules_ninja.dm @@ -24,7 +24,7 @@ return if(bumpoff) RegisterSignal(mod.wearer, COMSIG_LIVING_MOB_BUMP, PROC_REF(unstealth)) - RegisterSignal(mod.wearer, COMSIG_HUMAN_MELEE_UNARMED_ATTACK, PROC_REF(on_unarmed_attack)) + RegisterSignal(mod.wearer, COMSIG_LIVING_UNARMED_ATTACK, PROC_REF(on_unarmed_attack)) RegisterSignal(mod.wearer, COMSIG_ATOM_BULLET_ACT, PROC_REF(on_bullet_act)) RegisterSignals(mod.wearer, list(COMSIG_MOB_ITEM_ATTACK, COMSIG_ATOM_ATTACKBY, COMSIG_ATOM_ATTACK_HAND, COMSIG_ATOM_HITBY, COMSIG_ATOM_HULK_ATTACK, COMSIG_ATOM_ATTACK_PAW, COMSIG_CARBON_CUFF_ATTEMPTED), PROC_REF(unstealth)) animate(mod.wearer, alpha = stealth_alpha, time = 1.5 SECONDS) @@ -36,7 +36,7 @@ return if(bumpoff) UnregisterSignal(mod.wearer, COMSIG_LIVING_MOB_BUMP) - UnregisterSignal(mod.wearer, list(COMSIG_HUMAN_MELEE_UNARMED_ATTACK, COMSIG_MOB_ITEM_ATTACK, COMSIG_ATOM_ATTACKBY, COMSIG_ATOM_ATTACK_HAND, COMSIG_ATOM_BULLET_ACT, COMSIG_ATOM_HITBY, COMSIG_ATOM_HULK_ATTACK, COMSIG_ATOM_ATTACK_PAW, COMSIG_CARBON_CUFF_ATTEMPTED)) + UnregisterSignal(mod.wearer, list(COMSIG_LIVING_UNARMED_ATTACK, COMSIG_MOB_ITEM_ATTACK, COMSIG_ATOM_ATTACKBY, COMSIG_ATOM_ATTACK_HAND, COMSIG_ATOM_BULLET_ACT, COMSIG_ATOM_HITBY, COMSIG_ATOM_HULK_ATTACK, COMSIG_ATOM_ATTACK_PAW, COMSIG_CARBON_CUFF_ATTEMPTED)) animate(mod.wearer, alpha = 255, time = 1.5 SECONDS) /obj/item/mod/module/stealth/proc/unstealth(datum/source) @@ -143,10 +143,10 @@ var/door_hack_counter = 0 /obj/item/mod/module/hacker/on_suit_activation() - RegisterSignal(mod.wearer, COMSIG_HUMAN_EARLY_UNARMED_ATTACK, PROC_REF(hack)) + RegisterSignal(mod.wearer, COMSIG_LIVING_UNARMED_ATTACK, PROC_REF(hack)) /obj/item/mod/module/hacker/on_suit_deactivation(deleting = FALSE) - UnregisterSignal(mod.wearer, COMSIG_HUMAN_EARLY_UNARMED_ATTACK) + UnregisterSignal(mod.wearer, COMSIG_LIVING_UNARMED_ATTACK) /obj/item/mod/module/hacker/proc/hack(mob/living/carbon/human/source, atom/target, proximity, modifiers) SIGNAL_HANDLER diff --git a/code/modules/mod/modules/modules_security.dm b/code/modules/mod/modules/modules_security.dm index 7e331433b4f..3ac431034b5 100644 --- a/code/modules/mod/modules/modules_security.dm +++ b/code/modules/mod/modules/modules_security.dm @@ -422,8 +422,10 @@ UnregisterSignal(creature, COMSIG_MOVABLE_MOVED) return - if(oldgroup != newgroup) - sorted_creatures[oldgroup] -= creature + if(oldgroup == newgroup) + return + + sorted_creatures[oldgroup] -= creature sorted_creatures[newgroup] += creature keyed_creatures[creature] = newgroup diff --git a/code/modules/plumbing/plumbers/acclimator.dm b/code/modules/plumbing/plumbers/acclimator.dm index 6b7a8caba4a..850ebaaa3ed 100644 --- a/code/modules/plumbing/plumbers/acclimator.dm +++ b/code/modules/plumbing/plumbers/acclimator.dm @@ -3,6 +3,9 @@ #define HEATING "Heating" #define NEUTRAL "Neutral" +///cool/heat power. converts temperature into joules +#define HEATER_COEFFICIENT 0.05 + ///this the plumbing version of a heater/freezer. /obj/machinery/plumbing/acclimator name = "chemical acclimator" @@ -17,8 +20,6 @@ var/target_temperature = 300 ///I cant find a good name for this. Basically if target is 300, and this is 10, it will still target 300 but will start emptying itself at 290 and 310. var/allowed_temperature_difference = 1 - ///cool/heat power - var/heater_coefficient = 0.05 ///Are we turned on or off? this is from the on and off button var/enabled = TRUE ///COOLING, HEATING or NEUTRAL. We track this for change, so we dont needlessly update our icon @@ -52,7 +53,7 @@ emptying = TRUE if(!emptying) //suspend heating/cooling during emptying phase - reagents.adjust_thermal_energy((target_temperature - reagents.chem_temp) * heater_coefficient * seconds_per_tick * SPECIFIC_HEAT_DEFAULT * reagents.total_volume) //keep constant with chem heater + reagents.adjust_thermal_energy((target_temperature - reagents.chem_temp) * HEATER_COEFFICIENT * seconds_per_tick * SPECIFIC_HEAT_DEFAULT * reagents.total_volume) //keep constant with chem heater reagents.handle_reactions() use_power(active_power_usage * seconds_per_tick) else if(acclimate_state != NEUTRAL) @@ -109,3 +110,4 @@ #undef COOLING #undef HEATING #undef NEUTRAL +#undef HEATER_COEFFICIENT diff --git a/code/modules/plumbing/plumbers/reaction_chamber.dm b/code/modules/plumbing/plumbers/reaction_chamber.dm index 36320f18184..d41c502ecf9 100644 --- a/code/modules/plumbing/plumbers/reaction_chamber.dm +++ b/code/modules/plumbing/plumbers/reaction_chamber.dm @@ -53,9 +53,6 @@ var/power_usage = active_power_usage * 0.5 if(!emptying || reagents.is_reacting) - //do reactions and stuff - reagents.handle_reactions() - //adjust temperature of final solution var/temp_diff = target_temperature - reagents.chem_temp if(abs(temp_diff) > 0.01) //if we are not close enough keep going @@ -174,9 +171,15 @@ /obj/machinery/plumbing/reaction_chamber/chem/handle_reagents(seconds_per_tick) while(reagents.ph < acidic_limit || reagents.ph > alkaline_limit) + //no power if(machine_stat & NOPOWER) return + //nothing to react with + var/num_of_reagents = length(reagents.reagent_list) + if(!num_of_reagents) + return + /** * figure out which buffer to transfer to restore balance * if solution is getting too basic(high ph) add some acid to lower it's value @@ -186,13 +189,14 @@ if(!buffer.total_volume) return - //transfer buffer and handle reactions, not a proven math but looks logical - var/transfer_amount = FLOOR((reagents.ph > alkaline_limit ? (reagents.ph - alkaline_limit) : (acidic_limit - reagents.ph)) * seconds_per_tick, CHEMICAL_QUANTISATION_LEVEL) - if(transfer_amount <= CHEMICAL_QUANTISATION_LEVEL || !buffer.trans_to(reagents, transfer_amount)) + //transfer buffer and handle reactions + var/ph_change = (reagents.ph > alkaline_limit ? (reagents.ph - alkaline_limit) : (acidic_limit - reagents.ph)) + var/buffer_amount = ((ph_change * reagents.total_volume) / (BUFFER_IONIZING_STRENGTH * num_of_reagents)) + if(!buffer.trans_to(reagents, buffer_amount * seconds_per_tick)) return //some power for accurate ph balancing - use_power(active_power_usage * 0.2 * seconds_per_tick) + use_power(active_power_usage * 0.03 * buffer_amount * seconds_per_tick) /obj/machinery/plumbing/reaction_chamber/chem/ui_interact(mob/user, datum/tgui/ui) ui = SStgui.try_update_ui(user, src, ui) diff --git a/code/modules/plumbing/plumbers/synthesizer.dm b/code/modules/plumbing/plumbers/synthesizer.dm index a4521dd9b2e..3dddd648e61 100644 --- a/code/modules/plumbing/plumbers/synthesizer.dm +++ b/code/modules/plumbing/plumbers/synthesizer.dm @@ -10,11 +10,11 @@ ///Amount we produce for every process. Ideally keep under 5 since thats currently the standard duct capacity var/amount = 1 ///I track them here because I have no idea how I'd make tgui loop like that - var/static/list/possible_amounts = list(0,1,2,3,4,5) + var/static/list/possible_amounts = list(0, 1, 2, 3, 4, 5) ///The reagent we are producing. We are a typepath, but are also typecast because there's several occations where we need to use initial. var/datum/reagent/reagent_id = null ///straight up copied from chem dispenser. Being a subtype would be extremely tedious and making it global would restrict potential subtypes using different dispensable_reagents - var/list/dispensable_reagents = list( + var/static/list/default_reagents = list( /datum/reagent/aluminium, /datum/reagent/bromine, /datum/reagent/carbon, @@ -41,10 +41,13 @@ /datum/reagent/water, /datum/reagent/fuel, ) + //reagents this synthesizer can dispense + var/list/dispensable_reagents /obj/machinery/plumbing/synthesizer/Initialize(mapload, bolt, layer) . = ..() AddComponent(/datum/component/plumbing/simple_supply, bolt, layer) + dispensable_reagents = default_reagents /obj/machinery/plumbing/synthesizer/process(seconds_per_tick) if(machine_stat & NOPOWER || !reagent_id || !amount) @@ -114,7 +117,7 @@ icon_state = "synthesizer_soda" //Copied from soda dispenser - dispensable_reagents = list( + var/static/list/soda_reagents = list( /datum/reagent/consumable/coffee, /datum/reagent/consumable/space_cola, /datum/reagent/consumable/cream, @@ -140,6 +143,11 @@ /datum/reagent/water, ) +/obj/machinery/plumbing/synthesizer/soda/Initialize(mapload, bolt, layer) + . = ..() + + dispensable_reagents = soda_reagents + /obj/machinery/plumbing/synthesizer/beer name = "beer synthesizer" desc = "Produces a single chemical at a given volume. Must be plumbed." @@ -147,7 +155,7 @@ icon_state = "synthesizer_booze" //Copied from beer dispenser - dispensable_reagents = list( + var/static/list/beer_reagents = list( /datum/reagent/consumable/ethanol/absinthe, /datum/reagent/consumable/ethanol/ale, /datum/reagent/consumable/ethanol/applejack, @@ -172,3 +180,7 @@ /datum/reagent/consumable/ethanol/wine, ) +/obj/machinery/plumbing/synthesizer/beer/Initialize(mapload, bolt, layer) + . = ..() + + dispensable_reagents = beer_reagents diff --git a/code/modules/power/cell.dm b/code/modules/power/cell.dm index dcc3369766f..eb2a5b4d1a2 100644 --- a/code/modules/power/cell.dm +++ b/code/modules/power/cell.dm @@ -23,7 +23,7 @@ ///Current charge in cell units var/charge = 0 ///Maximum charge in cell units - var/maxcharge = 1000 + var/maxcharge = STANDARD_CELL_CHARGE custom_materials = list(/datum/material/iron=SMALL_MATERIAL_AMOUNT*7, /datum/material/glass=SMALL_MATERIAL_AMOUNT*0.5) grind_results = list(/datum/reagent/lithium = 15, /datum/reagent/iron = 5, /datum/reagent/silicon = 5) ///If the cell has been booby-trapped by injecting it with plasma. Chance on use() to explode. @@ -31,7 +31,7 @@ ///If the power cell was damaged by an explosion, chance for it to become corrupted and function the same as rigged. var/corrupted = FALSE ///how much power is given every tick in a recharger - var/chargerate = 100 + var/chargerate = STANDARD_CELL_CHARGE * 0.1 ///If true, the cell will state it's maximum charge in it's description var/ratingdesc = TRUE ///If it's a grown that acts as a battery, add a wire overlay to it. @@ -51,7 +51,7 @@ create_reagents(5, INJECTABLE | DRAINABLE) if (override_maxcharge) maxcharge = override_maxcharge - rating = max(round(maxcharge / 10000, 1), 1) + rating = max(round(maxcharge / (STANDARD_CELL_CHARGE * 10), 1), 1) if(!charge) charge = maxcharge if(empty) @@ -82,7 +82,7 @@ . = COMPONENT_ITEM_CHARGED if(prob(80)) - maxcharge -= 200 + maxcharge -= STANDARD_CELL_CHARGE * 0.2 if(maxcharge <= 1) // Div by 0 protection maxcharge = 1 @@ -289,7 +289,7 @@ /obj/item/stock_parts/cell/crap name = "\improper Nanotrasen brand rechargeable AA battery" desc = "You can't top the plasma top." //TOTALLY TRADEMARK INFRINGEMENT - maxcharge = 500 + maxcharge = STANDARD_CELL_CHARGE * 0.5 custom_materials = list(/datum/material/glass=SMALL_MATERIAL_AMOUNT*0.4) /obj/item/stock_parts/cell/crap/empty @@ -298,18 +298,18 @@ /obj/item/stock_parts/cell/upgraded name = "upgraded power cell" desc = "A power cell with a slightly higher capacity than normal!" - maxcharge = 2500 + maxcharge = STANDARD_CELL_CHARGE * 2.5 custom_materials = list(/datum/material/glass=SMALL_MATERIAL_AMOUNT*0.5) - chargerate = 1000 + chargerate = STANDARD_CELL_CHARGE /obj/item/stock_parts/cell/upgraded/plus name = "upgraded power cell+" desc = "A power cell with an even higher capacity than the base model!" - maxcharge = 5000 + maxcharge = STANDARD_CELL_CHARGE * 5 /obj/item/stock_parts/cell/secborg name = "security borg rechargeable D battery" - maxcharge = 600 //600 max charge / 100 charge per shot = six shots + maxcharge = STANDARD_CELL_CHARGE * 0.6 custom_materials = list(/datum/material/glass=SMALL_MATERIAL_AMOUNT*0.4) /obj/item/stock_parts/cell/secborg/empty @@ -317,38 +317,38 @@ /obj/item/stock_parts/cell/mini_egun name = "miniature energy gun power cell" - maxcharge = 600 + maxcharge = STANDARD_CELL_CHARGE * 0.6 /obj/item/stock_parts/cell/hos_gun name = "X-01 multiphase energy gun power cell" - maxcharge = 1200 + maxcharge = STANDARD_CELL_CHARGE * 1.2 /obj/item/stock_parts/cell/pulse //200 pulse shots name = "pulse rifle power cell" - maxcharge = 40000 - chargerate = 1500 + maxcharge = STANDARD_CELL_CHARGE * 40 + chargerate = STANDARD_CELL_CHARGE * 1.5 /obj/item/stock_parts/cell/pulse/carbine //25 pulse shots name = "pulse carbine power cell" - maxcharge = 5000 + maxcharge = STANDARD_CELL_CHARGE * 5 /obj/item/stock_parts/cell/pulse/pistol //10 pulse shots name = "pulse pistol power cell" - maxcharge = 2000 + maxcharge = STANDARD_CELL_CHARGE * 2 /obj/item/stock_parts/cell/ninja name = "black power cell" icon_state = "bscell" - maxcharge = 10000 + maxcharge = STANDARD_CELL_CHARGE * 10 custom_materials = list(/datum/material/glass=SMALL_MATERIAL_AMOUNT*0.6) - chargerate = 2000 + chargerate = STANDARD_CELL_CHARGE * 2 /obj/item/stock_parts/cell/high name = "high-capacity power cell" icon_state = "hcell" - maxcharge = 10000 + maxcharge = STANDARD_CELL_CHARGE * 10 custom_materials = list(/datum/material/glass=SMALL_MATERIAL_AMOUNT*0.6) - chargerate = 1500 + chargerate = STANDARD_CELL_CHARGE * 1.5 /obj/item/stock_parts/cell/high/empty empty = TRUE @@ -356,9 +356,9 @@ /obj/item/stock_parts/cell/super name = "super-capacity power cell" icon_state = "scell" - maxcharge = 20000 + maxcharge = STANDARD_CELL_CHARGE * 20 custom_materials = list(/datum/material/glass=SMALL_MATERIAL_AMOUNT * 3) - chargerate = 2000 + chargerate = STANDARD_CELL_CHARGE * 2 /obj/item/stock_parts/cell/super/empty empty = TRUE @@ -366,9 +366,9 @@ /obj/item/stock_parts/cell/hyper name = "hyper-capacity power cell" icon_state = "hpcell" - maxcharge = 30000 + maxcharge = STANDARD_CELL_CHARGE * 30 custom_materials = list(/datum/material/glass=SMALL_MATERIAL_AMOUNT * 4) - chargerate = 3000 + chargerate = STANDARD_CELL_CHARGE * 3 /obj/item/stock_parts/cell/hyper/empty empty = TRUE @@ -377,9 +377,9 @@ name = "bluespace power cell" desc = "A rechargeable transdimensional power cell." icon_state = "bscell" - maxcharge = 40000 + maxcharge = STANDARD_CELL_CHARGE * 40 custom_materials = list(/datum/material/glass=SMALL_MATERIAL_AMOUNT*6) - chargerate = 4000 + chargerate = STANDARD_CELL_CHARGE * 4 /obj/item/stock_parts/cell/bluespace/empty empty = TRUE @@ -400,7 +400,7 @@ desc = "An alien power cell that produces energy seemingly out of nowhere." icon = 'icons/obj/antags/abductor.dmi' icon_state = "cell" - maxcharge = 50000 + maxcharge = STANDARD_CELL_CHARGE * 50 ratingdesc = FALSE /obj/item/stock_parts/cell/infinite/abductor/Initialize(mapload) @@ -413,7 +413,7 @@ icon = 'icons/obj/service/hydroponics/harvest.dmi' icon_state = "potato" charge = 100 - maxcharge = 300 + maxcharge = STANDARD_CELL_CHARGE * 0.3 charge_light_type = null connector_type = null custom_materials = null @@ -423,7 +423,7 @@ /obj/item/stock_parts/cell/emproof name = "\improper EMP-proof cell" desc = "An EMP-proof cell." - maxcharge = 500 + maxcharge = STANDARD_CELL_CHARGE * 0.5 /obj/item/stock_parts/cell/emproof/Initialize(mapload) AddElement(/datum/element/empprotection, EMP_PROTECT_SELF) @@ -441,15 +441,15 @@ icon = 'icons/mob/simple/slimes.dmi' icon_state = "yellow slime extract" custom_materials = null - maxcharge = 5000 + maxcharge = STANDARD_CELL_CHARGE * 5 charge_light_type = null connector_type = "slimecore" /obj/item/stock_parts/cell/beam_rifle name = "beam rifle capacitor" desc = "A high powered capacitor that can provide huge amounts of energy in an instant." - maxcharge = 50000 - chargerate = 5000 //Extremely energy intensive + maxcharge = STANDARD_CELL_CHARGE * 50 + chargerate = STANDARD_CELL_CHARGE * 5 //Extremely energy intensive /obj/item/stock_parts/cell/beam_rifle/corrupt() return @@ -463,7 +463,7 @@ /obj/item/stock_parts/cell/emergency_light name = "miniature power cell" desc = "A tiny power cell with a very low power capacity. Used in light fixtures to power them in the event of an outage." - maxcharge = 120 //Emergency lights use 0.2 W per tick, meaning ~10 minutes of emergency power from a cell + maxcharge = STANDARD_CELL_CHARGE * 0.12 //Emergency lights use 0.2 W per tick, meaning ~10 minutes of emergency power from a cell custom_materials = list(/datum/material/glass = SMALL_MATERIAL_AMOUNT*0.2) w_class = WEIGHT_CLASS_TINY @@ -478,7 +478,7 @@ name = "crystal power cell" desc = "A very high power cell made from crystallized plasma" icon_state = "crystal_cell" - maxcharge = 50000 + maxcharge = STANDARD_CELL_CHARGE * 50 chargerate = 0 charge_light_type = null connector_type = "crystal" @@ -486,7 +486,7 @@ grind_results = null /obj/item/stock_parts/cell/inducer_supply - maxcharge = 5000 + maxcharge = STANDARD_CELL_CHARGE * 5 #undef CELL_DRAIN_TIME #undef CELL_POWER_GAIN diff --git a/code/modules/projectiles/ammunition/energy/_energy.dm b/code/modules/projectiles/ammunition/energy/_energy.dm index 808cbdfbfe7..11c8707a5e7 100644 --- a/code/modules/projectiles/ammunition/energy/_energy.dm +++ b/code/modules/projectiles/ammunition/energy/_energy.dm @@ -4,7 +4,7 @@ caliber = ENERGY projectile_type = /obj/projectile/energy slot_flags = null - var/e_cost = 100 //The amount of energy a cell needs to expend to create this shot. + var/e_cost = LASER_SHOTS(10, STANDARD_CELL_CHARGE) //The amount of energy a cell needs to expend to create this shot. var/select_name = CALIBER_ENERGY fire_sound = 'sound/weapons/laser.ogg' firing_effect_type = /obj/effect/temp_visual/dir_setting/firing_effect/energy diff --git a/code/modules/projectiles/ammunition/energy/ebow.dm b/code/modules/projectiles/ammunition/energy/ebow.dm index 0eee10a58e5..535ea126576 100644 --- a/code/modules/projectiles/ammunition/energy/ebow.dm +++ b/code/modules/projectiles/ammunition/energy/ebow.dm @@ -1,7 +1,7 @@ /obj/item/ammo_casing/energy/bolt projectile_type = /obj/projectile/energy/bolt select_name = "bolt" - e_cost = 500 + e_cost = LASER_SHOTS(1, STANDARD_CELL_CHARGE * 0.5) fire_sound = 'sound/weapons/gun/general/heavy_shot_suppressed.ogg' // Even for non-suppressed crossbows, this is the most appropriate sound /obj/item/ammo_casing/energy/bolt/halloween diff --git a/code/modules/projectiles/ammunition/energy/gravity.dm b/code/modules/projectiles/ammunition/energy/gravity.dm index 5b781189c52..fe73ad26883 100644 --- a/code/modules/projectiles/ammunition/energy/gravity.dm +++ b/code/modules/projectiles/ammunition/energy/gravity.dm @@ -1,5 +1,5 @@ /obj/item/ammo_casing/energy/gravity - e_cost = 0 + e_cost = 0 // Not possible to use the macro fire_sound = 'sound/weapons/wave.ogg' select_name = "gravity" delay = 50 diff --git a/code/modules/projectiles/ammunition/energy/laser.dm b/code/modules/projectiles/ammunition/energy/laser.dm index e766f42be0f..c47181688a4 100644 --- a/code/modules/projectiles/ammunition/energy/laser.dm +++ b/code/modules/projectiles/ammunition/energy/laser.dm @@ -1,24 +1,21 @@ /obj/item/ammo_casing/energy/laser projectile_type = /obj/projectile/beam/laser - e_cost = 83 + e_cost = LASER_SHOTS(12, STANDARD_CELL_CHARGE) select_name = "kill" /obj/item/ammo_casing/energy/laser/hellfire projectile_type = /obj/projectile/beam/laser/hellfire - e_cost = 100 + e_cost = LASER_SHOTS(10, STANDARD_CELL_CHARGE) select_name = "maim" -/obj/item/ammo_casing/energy/laser/hellfire/antique - e_cost = 100 - /obj/item/ammo_casing/energy/lasergun projectile_type = /obj/projectile/beam/laser - e_cost = 62.5 + e_cost = LASER_SHOTS(16, STANDARD_CELL_CHARGE) select_name = "kill" /obj/item/ammo_casing/energy/lasergun/carbine projectile_type = /obj/projectile/beam/laser/carbine - e_cost = 25 // 40 shots + e_cost = LASER_SHOTS(40, STANDARD_CELL_CHARGE) select_name = "kill" fire_sound = 'sound/weapons/laser2.ogg' @@ -29,15 +26,15 @@ /obj/item/ammo_casing/energy/lasergun/old projectile_type = /obj/projectile/beam/laser - e_cost = 200 + e_cost = LASER_SHOTS(5, STANDARD_CELL_CHARGE) select_name = "kill" /obj/item/ammo_casing/energy/laser/hos - e_cost = 120 + e_cost = LASER_SHOTS(10, STANDARD_CELL_CHARGE * 1.2) /obj/item/ammo_casing/energy/laser/musket projectile_type = /obj/projectile/beam/laser/musket - e_cost = 1000 + e_cost = LASER_SHOTS(1, STANDARD_CELL_CHARGE) /obj/item/ammo_casing/energy/laser/musket/prime projectile_type = /obj/projectile/beam/laser/musket/prime @@ -49,7 +46,7 @@ /obj/item/ammo_casing/energy/chameleon projectile_type = /obj/projectile/energy/chameleon - e_cost = 0 + e_cost = 0 // Can't really use the macro here, unfortunately var/projectile_vars = list() /obj/item/ammo_casing/energy/chameleon/ready_proj() @@ -89,7 +86,7 @@ /obj/item/ammo_casing/energy/laser/pulse projectile_type = /obj/projectile/beam/pulse - e_cost = 200 + e_cost = LASER_SHOTS(200, STANDARD_CELL_CHARGE * 40) select_name = "DESTROY" fire_sound = 'sound/weapons/pulse.ogg' @@ -111,7 +108,7 @@ /obj/item/ammo_casing/energy/xray projectile_type = /obj/projectile/beam/xray - e_cost = 50 + e_cost = LASER_SHOTS(20, STANDARD_CELL_CHARGE) fire_sound = 'sound/weapons/laser3.ogg' /obj/item/ammo_casing/energy/mindflayer @@ -127,7 +124,7 @@ /obj/item/ammo_casing/energy/nanite projectile_type = /obj/projectile/bullet/c10mm //henk select_name = "bullet" - e_cost = 120 + e_cost = LASER_SHOTS(8, STANDARD_CELL_CHARGE) fire_sound = 'sound/weapons/thermalpistol.ogg' /obj/item/ammo_casing/energy/nanite/inferno diff --git a/code/modules/projectiles/ammunition/energy/lmg.dm b/code/modules/projectiles/ammunition/energy/lmg.dm index fbd5916613e..632044f0652 100644 --- a/code/modules/projectiles/ammunition/energy/lmg.dm +++ b/code/modules/projectiles/ammunition/energy/lmg.dm @@ -2,5 +2,5 @@ projectile_type = /obj/projectile/bullet/c3d select_name = "spraydown" fire_sound = 'sound/weapons/gun/smg/shot.ogg' - e_cost = 20 + e_cost = LASER_SHOTS(30, STANDARD_CELL_CHARGE * 0.6) firing_effect_type = /obj/effect/temp_visual/dir_setting/firing_effect diff --git a/code/modules/projectiles/ammunition/energy/plasma.dm b/code/modules/projectiles/ammunition/energy/plasma.dm index 00de4a90ffe..e660903bdc9 100644 --- a/code/modules/projectiles/ammunition/energy/plasma.dm +++ b/code/modules/projectiles/ammunition/energy/plasma.dm @@ -3,9 +3,9 @@ select_name = "plasma burst" fire_sound = 'sound/weapons/plasma_cutter.ogg' delay = 15 - e_cost = 25 + e_cost = LASER_SHOTS(40, STANDARD_CELL_CHARGE) /obj/item/ammo_casing/energy/plasma/adv projectile_type = /obj/projectile/plasma/adv delay = 10 - e_cost = 10 + e_cost = LASER_SHOTS(100, STANDARD_CELL_CHARGE) diff --git a/code/modules/projectiles/ammunition/energy/portal.dm b/code/modules/projectiles/ammunition/energy/portal.dm index 8bdd697f1bf..0ef63491f11 100644 --- a/code/modules/projectiles/ammunition/energy/portal.dm +++ b/code/modules/projectiles/ammunition/energy/portal.dm @@ -1,6 +1,6 @@ /obj/item/ammo_casing/energy/wormhole projectile_type = /obj/projectile/beam/wormhole - e_cost = 0 + e_cost = 0 // Can't use the macro harmful = FALSE fire_sound = 'sound/weapons/pulse3.ogg' select_name = "blue" diff --git a/code/modules/projectiles/ammunition/energy/special.dm b/code/modules/projectiles/ammunition/energy/special.dm index 24fba4b9ba4..f2fc274ee8a 100644 --- a/code/modules/projectiles/ammunition/energy/special.dm +++ b/code/modules/projectiles/ammunition/energy/special.dm @@ -5,7 +5,7 @@ /obj/item/ammo_casing/energy/ion/hos projectile_type = /obj/projectile/ion/weak - e_cost = 300 + e_cost = LASER_SHOTS(4, STANDARD_CELL_CHARGE * 1.2) /obj/item/ammo_casing/energy/declone projectile_type = /obj/projectile/energy/declone @@ -30,12 +30,12 @@ /obj/item/ammo_casing/energy/flora/revolution projectile_type = /obj/projectile/energy/florarevolution select_name = "revolution" - e_cost = 250 + e_cost = LASER_SHOTS(4, STANDARD_CELL_CHARGE) /obj/item/ammo_casing/energy/temp projectile_type = /obj/projectile/temp select_name = "freeze" - e_cost = 250 + e_cost = LASER_SHOTS(40, STANDARD_CELL_CHARGE * 10) fire_sound = 'sound/weapons/pulse3.ogg' /obj/item/ammo_casing/energy/temp/hot @@ -60,23 +60,23 @@ /obj/item/ammo_casing/energy/tesla_cannon fire_sound = 'sound/magic/lightningshock.ogg' - e_cost = 30 + e_cost = LASER_SHOTS(33, STANDARD_CELL_CHARGE) select_name = "shock" projectile_type = /obj/projectile/energy/tesla_cannon /obj/item/ammo_casing/energy/shrink projectile_type = /obj/projectile/beam/shrink select_name = "shrink ray" - e_cost = 200 + e_cost = LASER_SHOTS(5, STANDARD_CELL_CHARGE) /obj/item/ammo_casing/energy/marksman projectile_type = /obj/projectile/bullet/marksman select_name = "marksman nanoshot" - e_cost = 0 + e_cost = 0 // Can't use the macro fire_sound = 'sound/weapons/gun/revolver/shot_alt.ogg' /obj/item/ammo_casing/energy/fisher projectile_type = /obj/projectile/energy/fisher select_name = "light-buster" - e_cost = 250 + e_cost = LASER_SHOTS(2, STANDARD_CELL_CHARGE * 0.5) fire_sound = 'sound/weapons/gun/general/heavy_shot_suppressed.ogg' // fwip fwip fwip fwip diff --git a/code/modules/projectiles/ammunition/energy/stun.dm b/code/modules/projectiles/ammunition/energy/stun.dm index 630233e5d73..ee2f9fa17ee 100644 --- a/code/modules/projectiles/ammunition/energy/stun.dm +++ b/code/modules/projectiles/ammunition/energy/stun.dm @@ -2,38 +2,33 @@ projectile_type = /obj/projectile/energy/electrode select_name = "stun" fire_sound = 'sound/weapons/taser.ogg' - e_cost = 200 + e_cost = LASER_SHOTS(5, STANDARD_CELL_CHARGE) harmful = FALSE /obj/item/ammo_casing/energy/electrode/spec - e_cost = 100 + e_cost = LASER_SHOTS(10, STANDARD_CELL_CHARGE) /obj/item/ammo_casing/energy/electrode/gun fire_sound = 'sound/weapons/gun/pistol/shot.ogg' - e_cost = 100 + e_cost = LASER_SHOTS(10, STANDARD_CELL_CHARGE) /obj/item/ammo_casing/energy/electrode/old - e_cost = 1000 + e_cost = LASER_SHOTS(1, STANDARD_CELL_CHARGE) /obj/item/ammo_casing/energy/disabler projectile_type = /obj/projectile/beam/disabler select_name = "disable" - e_cost = 50 + e_cost = LASER_SHOTS(20, STANDARD_CELL_CHARGE) fire_sound = 'sound/weapons/taser2.ogg' harmful = FALSE /obj/item/ammo_casing/energy/disabler/hos - e_cost = 60 + e_cost = LASER_SHOTS(20, STANDARD_CELL_CHARGE * 1.2) /obj/item/ammo_casing/energy/disabler/smoothbore projectile_type = /obj/projectile/beam/disabler/smoothbore - e_cost = 1000 + e_cost = LASER_SHOTS(1, STANDARD_CELL_CHARGE) /obj/item/ammo_casing/energy/disabler/smoothbore/prime projectile_type = /obj/projectile/beam/disabler/smoothbore/prime - e_cost = 500 - -// SKYRAT ADDITION START -/obj/item/ammo_casing/energy/disabler/skyrat - e_cost = 1000 -// SKYRAT ADDITION END + e_cost = LASER_SHOTS(2, STANDARD_CELL_CHARGE) diff --git a/code/modules/projectiles/guns/energy/beam_rifle.dm b/code/modules/projectiles/guns/energy/beam_rifle.dm index 8869da14a59..a451b14de9a 100644 --- a/code/modules/projectiles/guns/energy/beam_rifle.dm +++ b/code/modules/projectiles/guns/energy/beam_rifle.dm @@ -433,7 +433,7 @@ /obj/item/ammo_casing/energy/beam_rifle/hitscan projectile_type = /obj/projectile/beam/beam_rifle/hitscan select_name = "beam" - e_cost = 10000 + e_cost = LASER_SHOTS(5, 50000) // Beam rifle has a custom cell fire_sound = 'sound/weapons/beam_sniper.ogg' /obj/projectile/beam/beam_rifle diff --git a/code/modules/projectiles/guns/energy/dueling.dm b/code/modules/projectiles/guns/energy/dueling.dm index a766ba5667f..7b3929d7574 100644 --- a/code/modules/projectiles/guns/energy/dueling.dm +++ b/code/modules/projectiles/guns/energy/dueling.dm @@ -292,7 +292,7 @@ //Casing /obj/item/ammo_casing/energy/duel - e_cost = 0 + e_cost = 0 // Can't use the macro projectile_type = /obj/projectile/energy/duel var/setting diff --git a/code/modules/projectiles/guns/energy/kinetic_accelerator.dm b/code/modules/projectiles/guns/energy/kinetic_accelerator.dm index 06e82a37aae..444b18ad274 100644 --- a/code/modules/projectiles/guns/energy/kinetic_accelerator.dm +++ b/code/modules/projectiles/guns/energy/kinetic_accelerator.dm @@ -165,7 +165,7 @@ /obj/item/ammo_casing/energy/kinetic projectile_type = /obj/projectile/kinetic select_name = "kinetic" - e_cost = 500 + e_cost = LASER_SHOTS(1, STANDARD_CELL_CHARGE * 0.5) fire_sound = 'sound/weapons/kenetic_accel.ogg' // fine spelling there chap /obj/item/ammo_casing/energy/kinetic/ready_proj(atom/target, mob/living/user, quiet, zone_override = "") diff --git a/code/modules/projectiles/guns/energy/laser.dm b/code/modules/projectiles/guns/energy/laser.dm index 94d58bb5e32..7e07a440de7 100644 --- a/code/modules/projectiles/guns/energy/laser.dm +++ b/code/modules/projectiles/guns/energy/laser.dm @@ -82,7 +82,7 @@ selfcharge = 1 resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | ACID_PROOF flags_1 = PREVENT_CONTENTS_EXPLOSION_1 - ammo_type = list(/obj/item/ammo_casing/energy/laser/hellfire/antique) + ammo_type = list(/obj/item/ammo_casing/energy/laser/hellfire) /obj/item/gun/energy/laser/captain/scattershot name = "scatter shot laser rifle" diff --git a/code/modules/reagents/chemistry/holder.dm b/code/modules/reagents/chemistry/holder.dm index c72bfbb6c3e..b210bde63a2 100644 --- a/code/modules/reagents/chemistry/holder.dm +++ b/code/modules/reagents/chemistry/holder.dm @@ -1361,7 +1361,7 @@ if(!.) ph = CHEMICAL_NORMAL_PH else - ph = clamp(total_ph / total_volume, 0, 14) + ph = clamp(total_ph / total_volume, CHEMICAL_MIN_PH, CHEMICAL_MAX_PH) //now send the signals after the volume & ph has been computed for(var/datum/reagent/deleted_reagent as anything in deleted_reagents) @@ -1626,9 +1626,9 @@ * Arguments: * * value - How much to adjust the base pH by */ -/datum/reagents/proc/adjust_all_reagents_ph(value, lower_limit = 0, upper_limit = 14) +/datum/reagents/proc/adjust_all_reagents_ph(value) for(var/datum/reagent/reagent as anything in reagent_list) - reagent.ph = clamp(reagent.ph + value, lower_limit, upper_limit) + reagent.ph = clamp(reagent.ph + value, CHEMICAL_MIN_PH, CHEMICAL_MAX_PH) /* * Adjusts the base pH of a specific type @@ -1638,14 +1638,12 @@ * Arguments: * * input_reagent - type path of the reagent * * value - How much to adjust the base pH by -* * lower_limit - how low the pH can go -* * upper_limit - how high the pH can go */ -/datum/reagents/proc/adjust_specific_reagent_ph(input_reagent, value, lower_limit = 0, upper_limit = 14) +/datum/reagents/proc/adjust_specific_reagent_ph(input_reagent, value) var/datum/reagent/reagent = get_reagent(input_reagent) if(!reagent) //We can call this with missing reagents. return FALSE - reagent.ph = clamp(reagent.ph + value, lower_limit, upper_limit) + reagent.ph = clamp(reagent.ph + value, CHEMICAL_MIN_PH, CHEMICAL_MAX_PH) /** * Outputs a log-friendly list of reagents based on an external reagent list. diff --git a/code/modules/reagents/chemistry/reagents/reaction_agents_reagents.dm b/code/modules/reagents/chemistry/reagents/reaction_agents_reagents.dm index c1da8b7424f..d6c4f0009b4 100644 --- a/code/modules/reagents/chemistry/reagents/reaction_agents_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/reaction_agents_reagents.dm @@ -24,22 +24,23 @@ inverse_chem = null fallback_icon = 'icons/obj/drinks/drink_effects.dmi' fallback_icon_state = "acid_buffer_fallback" - ///The strength of the buffer where (volume/holder.total_volume)*strength. So for 1u added to 50u the ph will decrease by 0.4 - var/strength = 30 //Consumes self on addition and shifts ph /datum/reagent/reaction_agent/acidic_buffer/intercept_reagents_transfer(datum/reagents/target, amount) . = ..() if(!.) return + + //do the ph change + var/message if(target.ph <= ph) - target.my_atom.audible_message(span_warning("The beaker froths as the buffer is added, to no effect.")) - playsound(target.my_atom, 'sound/chemistry/bufferadd.ogg', 50, TRUE) - holder.remove_reagent(type, amount)//Remove from holder because it's not transferred - return - var/ph_change = -((amount/target.total_volume)*strength) - target.adjust_all_reagents_ph(ph_change, ph, 14) - target.my_atom.audible_message(span_warning("The beaker fizzes as the ph changes!")) + message = "The beaker froths as the buffer is added, to no effect." + else + message = "The beaker froths as the pH changes!" + target.adjust_all_reagents_ph((-(amount / target.total_volume) * BUFFER_IONIZING_STRENGTH)) + + //give feedback & remove from holder because it's not transferred + target.my_atom.audible_message(span_warning(message)) playsound(target.my_atom, 'sound/chemistry/bufferadd.ogg', 50, TRUE) holder.remove_reagent(type, amount) @@ -51,21 +52,22 @@ inverse_chem = null fallback_icon = 'icons/obj/drinks/drink_effects.dmi' fallback_icon_state = "base_buffer_fallback" - ///The strength of the buffer where (volume/holder.total_volume)*strength. So for 1u added to 50u the ph will increase by 0.4 - var/strength = 30 /datum/reagent/reaction_agent/basic_buffer/intercept_reagents_transfer(datum/reagents/target, amount) . = ..() if(!.) return + + //do the ph change + var/message if(target.ph >= ph) - target.my_atom.audible_message(span_warning("The beaker froths as the buffer is added, to no effect.")) - playsound(target.my_atom, 'sound/chemistry/bufferadd.ogg', 50, TRUE) - holder.remove_reagent(type, amount)//Remove from holder because it's not transferred - return - var/ph_change = (amount/target.total_volume)*strength - target.adjust_all_reagents_ph(ph_change, 0, ph) - target.my_atom.audible_message(span_warning("The beaker froths as the ph changes!")) + message = "The beaker froths as the buffer is added, to no effect." + else + message = "The beaker froths as the pH changes!" + target.adjust_all_reagents_ph(((amount / target.total_volume) * BUFFER_IONIZING_STRENGTH)) + + //give feedback & remove from holder because it's not transferred + target.my_atom.audible_message(span_warning(message)) playsound(target.my_atom, 'sound/chemistry/bufferadd.ogg', 50, TRUE) holder.remove_reagent(type, amount) @@ -103,14 +105,14 @@ target.my_atom.audible_message(span_warning("The added reagent doesn't seem to do much.")) holder.remove_reagent(type, amount) +///How much the reaction speed is sped up by - for 5u added to 100u, an additional step of 1 will be done up to a max of 2x +#define SPEED_REAGENT_STRENGTH 20 + /datum/reagent/reaction_agent/speed_agent name = "Tempomyocin" description = "This reagent will consume itself and speed up an ongoing reaction, modifying the current reaction's purity by it's own." ph = 10 color = "#e61f82" - ///How much the reaction speed is sped up by - for 5u added to 100u, an additional step of 1 will be done up to a max of 2x - var/strength = 20 - /datum/reagent/reaction_agent/speed_agent/intercept_reagents_transfer(datum/reagents/target, amount) . = ..() @@ -123,8 +125,10 @@ var/datum/equilibrium/reaction = _reaction if(!reaction) CRASH("[_reaction] is in the reaction list, but is not an equilibrium") - var/power = (amount/reaction.target_vol)*strength + var/power = (amount / reaction.target_vol) * SPEED_REAGENT_STRENGTH power *= creation_purity power = clamp(power, 0, 2) reaction.react_timestep(power, creation_purity) holder.remove_reagent(type, amount) + +#undef SPEED_REAGENT_STRENGTH diff --git a/code/modules/reagents/reagent_dispenser.dm b/code/modules/reagents/reagent_dispenser.dm index ef48a50af21..8241331d7b0 100644 --- a/code/modules/reagents/reagent_dispenser.dm +++ b/code/modules/reagents/reagent_dispenser.dm @@ -181,7 +181,7 @@ // It did not account for how much fuel was actually in the tank at all, just the size of the tank. // I encourage others to better scale these numbers in the future. // As it stands this is a minor nerf in exchange for an easy bombing technique working that has been broken for a while. - switch(volatiles.volume) + switch(fuel_amt) if(25 to 150) explosion(src, light_impact_range = 1, flame_range = 2) if(150 to 300) diff --git a/code/modules/research/server.dm b/code/modules/research/server.dm index 45a0a520fa0..56be6864b54 100644 --- a/code/modules/research/server.dm +++ b/code/modules/research/server.dm @@ -154,7 +154,7 @@ if(HDD_OVERLOADED) . += "The front panel is dangling open. The hdd inside is destroyed and the wires are all burned." -/obj/machinery/rnd/server/master/tool_act(mob/living/user, obj/item/tool, tool_type) +/obj/machinery/rnd/server/master/tool_act(mob/living/user, obj/item/tool, tool_type, is_right_clicking) // Only antags are given the training and knowledge to disassemble this thing. if(is_special_character(user)) return ..() diff --git a/code/modules/surgery/bodyparts/_bodyparts.dm b/code/modules/surgery/bodyparts/_bodyparts.dm index f033c081ead..407ac67a43a 100644 --- a/code/modules/surgery/bodyparts/_bodyparts.dm +++ b/code/modules/surgery/bodyparts/_bodyparts.dm @@ -969,8 +969,8 @@ icon_state = initial(icon_state)//no overlays found, we default back to initial icon. return for(var/image/img as anything in standing) - img.pixel_x = px_x - img.pixel_y = px_y + img.pixel_x += px_x + img.pixel_y += px_y add_overlay(standing) ///Generates an /image for the limb to be used as an overlay diff --git a/code/modules/surgery/bodyparts/head_hair_and_lips.dm b/code/modules/surgery/bodyparts/head_hair_and_lips.dm index 607c8ad73c9..2370d3dc184 100644 --- a/code/modules/surgery/bodyparts/head_hair_and_lips.dm +++ b/code/modules/surgery/bodyparts/head_hair_and_lips.dm @@ -119,11 +119,12 @@ var/image/hair_overlay if(!(show_debrained && (head_flags & HEAD_DEBRAIN)) && !hair_hidden && hairstyle && (head_flags & HEAD_HAIR)) - sprite_accessory = GLOB.hairstyles_list[hairstyle] - if(sprite_accessory) + var/datum/sprite_accessory/hair/hair_sprite_accessory = GLOB.hairstyles_list[hairstyle] + if(hair_sprite_accessory) //Overlay - hair_overlay = image(sprite_accessory.icon, sprite_accessory.icon_state, -HAIR_LAYER, image_dir) + hair_overlay = image(hair_sprite_accessory.icon, hair_sprite_accessory.icon_state, -HAIR_LAYER, image_dir) hair_overlay.alpha = hair_alpha + hair_overlay.pixel_y = hair_sprite_accessory.y_offset //Emissive blocker if(blocks_emissive != EMISSIVE_BLOCK_NONE) hair_overlay.overlays += emissive_blocker(hair_overlay.icon, hair_overlay.icon_state, location, alpha = hair_alpha) @@ -139,12 +140,13 @@ var/hair_gradient_style = LAZYACCESS(gradient_styles, GRADIENT_HAIR_KEY) if(hair_gradient_style) var/hair_gradient_color = LAZYACCESS(gradient_colors, GRADIENT_HAIR_KEY) - var/image/hair_gradient_overlay = get_gradient_overlay(sprite_accessory.icon, sprite_accessory.icon_state, -HAIR_LAYER, GLOB.hair_gradients_list[hair_gradient_style], hair_gradient_color) + var/image/hair_gradient_overlay = get_gradient_overlay(hair_sprite_accessory.icon, hair_sprite_accessory.icon_state, -HAIR_LAYER, GLOB.hair_gradients_list[hair_gradient_style], hair_gradient_color) // SKYRAT ADD - Hair offset if(LAZYFIND(owner?.dna?.species?.offset_features, OFFSET_HAIR)) hair_gradient_overlay.pixel_x = owner.dna.species.offset_features[OFFSET_HAIR][INDEX_X] hair_gradient_overlay.pixel_y = owner.dna.species.offset_features[OFFSET_HAIR][INDEX_Y] // SKYRAT ADD END + . += hair_gradient_overlay if(show_debrained && (head_flags & HEAD_DEBRAIN)) diff --git a/code/modules/surgery/bodyparts/parts.dm b/code/modules/surgery/bodyparts/parts.dm index 4207f3541f6..7eee48f9a79 100644 --- a/code/modules/surgery/bodyparts/parts.dm +++ b/code/modules/surgery/bodyparts/parts.dm @@ -113,6 +113,8 @@ var/datum/worn_feature_offset/worn_glove_offset /// Datum describing how to offset things held in the hands of this arm, the x offset IS functional here var/datum/worn_feature_offset/held_hand_offset + /// The noun to use when referring to this arm's appendage, e.g. "hand" or "paw" + var/appendage_noun = "hand" biological_state = BIO_STANDARD_JOINTED @@ -211,6 +213,7 @@ unarmed_damage_low = 1 /// monkey punches must be really weak, considering they bite people instead and their bites are weak as hell. unarmed_damage_high = 2 unarmed_stun_threshold = 3 + appendage_noun = "paw" /obj/item/bodypart/arm/left/alien icon = 'icons/mob/human/species/alien/bodyparts.dmi' @@ -224,6 +227,7 @@ can_be_disabled = FALSE max_damage = 100 should_draw_greyscale = FALSE + appendage_noun = "scythe-like hand" /obj/item/bodypart/arm/right @@ -314,6 +318,7 @@ unarmed_damage_low = 1 unarmed_damage_high = 2 unarmed_stun_threshold = 3 + appendage_noun = "paw" /obj/item/bodypart/arm/right/alien icon = 'icons/mob/human/species/alien/bodyparts.dmi' @@ -327,6 +332,7 @@ can_be_disabled = FALSE max_damage = 100 should_draw_greyscale = FALSE + appendage_noun = "scythe-like hand" /// Parent Type for legs, should not appear in game. /obj/item/bodypart/leg diff --git a/code/modules/surgery/bodyparts/robot_bodyparts.dm b/code/modules/surgery/bodyparts/robot_bodyparts.dm index 99591daaa4b..d967f2da9ec 100644 --- a/code/modules/surgery/bodyparts/robot_bodyparts.dm +++ b/code/modules/surgery/bodyparts/robot_bodyparts.dm @@ -235,8 +235,50 @@ /obj/item/bodypart/chest/robot/Destroy() QDEL_NULL(cell) + UnregisterSignal(src, COMSIG_BODYPART_ATTACHED) return ..() +/obj/item/bodypart/chest/robot/Initialize(mapload) + . = ..() + RegisterSignal(src, COMSIG_BODYPART_ATTACHED, PROC_REF(on_attached)) + RegisterSignal(src, COMSIG_BODYPART_REMOVED, PROC_REF(on_detached)) + +/obj/item/bodypart/chest/robot/proc/on_attached(obj/item/bodypart/chest/robot/this_bodypart, mob/living/carbon/human/new_owner) + SIGNAL_HANDLER + + RegisterSignals(new_owner, list(COMSIG_CARBON_POST_ATTACH_LIMB, COMSIG_CARBON_POST_REMOVE_LIMB), PROC_REF(check_limbs)) + +/obj/item/bodypart/chest/robot/proc/on_detached(obj/item/bodypart/chest/robot/this_bodypart, mob/living/carbon/human/old_owner) + SIGNAL_HANDLER + + UnregisterSignal(old_owner, list(COMSIG_CARBON_POST_ATTACH_LIMB, COMSIG_CARBON_POST_REMOVE_LIMB)) + +/obj/item/bodypart/chest/robot/proc/check_limbs() + SIGNAL_HANDLER + + var/all_robotic = TRUE + for(var/obj/item/bodypart/part in owner.bodyparts) + all_robotic = all_robotic && IS_ROBOTIC_LIMB(part) + + if(all_robotic) + owner.add_traits(list( + /* SKYRAT EDIT REMOVAL BEGIN - Synths are not immune to temperature + TRAIT_RESISTCOLD, + TRAIT_RESISTHEAT, + SKYRAT EDIT REMOVAL END */ + TRAIT_RESISTLOWPRESSURE, + TRAIT_RESISTHIGHPRESSURE, + ), AUGMENTATION_TRAIT) + else + owner.remove_traits(list( + /* SKYRAT EDIT REMOVAL BEGIN - Synths are not immune to temperature + TRAIT_RESISTCOLD, + TRAIT_RESISTHEAT, + SKYRAT EDIT REMOVAL END */ + TRAIT_RESISTLOWPRESSURE, + TRAIT_RESISTHIGHPRESSURE, + ), AUGMENTATION_TRAIT) + /obj/item/bodypart/chest/robot/attackby(obj/item/weapon, mob/user, params) if(istype(weapon, /obj/item/stock_parts/cell)) if(cell) diff --git a/code/modules/surgery/organ_manipulation.dm b/code/modules/surgery/organ_manipulation.dm index 17a8e147fb3..25004d20d20 100644 --- a/code/modules/surgery/organ_manipulation.dm +++ b/code/modules/surgery/organ_manipulation.dm @@ -87,7 +87,7 @@ var/obj/item/tool = user.get_active_held_item() if(step.try_op(user, target, user.zone_selected, tool, src, try_to_fail)) return TRUE - if(tool && tool.item_flags) //Mechanic organ manipulation isn't done with just surgery tools + if(tool && tool.tool_behaviour) //Mechanic organ manipulation isn't done with just surgery tools to_chat(user, span_warning("This step requires a different tool!")) return TRUE diff --git a/code/modules/surgery/organs/internal/cyberimp/augments_arms.dm b/code/modules/surgery/organs/internal/cyberimp/augments_arms.dm index 86cdf855134..142cf8d5143 100644 --- a/code/modules/surgery/organs/internal/cyberimp/augments_arms.dm +++ b/code/modules/surgery/organs/internal/cyberimp/augments_arms.dm @@ -381,11 +381,11 @@ /obj/item/organ/internal/cyberimp/arm/muscle/Insert(mob/living/carbon/reciever, special = FALSE, drop_if_replaced = TRUE) . = ..() if(ishuman(reciever)) //Sorry, only humans - RegisterSignal(reciever, COMSIG_HUMAN_EARLY_UNARMED_ATTACK, PROC_REF(on_attack_hand)) + RegisterSignal(reciever, COMSIG_LIVING_EARLY_UNARMED_ATTACK, PROC_REF(on_attack_hand)) /obj/item/organ/internal/cyberimp/arm/muscle/Remove(mob/living/carbon/implant_owner, special = 0) . = ..() - UnregisterSignal(implant_owner, COMSIG_HUMAN_EARLY_UNARMED_ATTACK) + UnregisterSignal(implant_owner, COMSIG_LIVING_EARLY_UNARMED_ATTACK) /obj/item/organ/internal/cyberimp/arm/muscle/emp_act(severity) . = ..() @@ -402,15 +402,17 @@ /obj/item/organ/internal/cyberimp/arm/muscle/proc/on_attack_hand(mob/living/carbon/human/source, atom/target, proximity, modifiers) SIGNAL_HANDLER - if(source.get_active_hand() != source.get_bodypart(check_zone(zone)) || !proximity) - return + if(source.get_active_hand() != hand || !proximity) + return NONE if(!source.combat_mode || LAZYACCESS(modifiers, RIGHT_CLICK)) - return + return NONE if(!isliving(target)) - return + return NONE var/datum/dna/dna = source.has_dna() if(dna?.check_mutation(/datum/mutation/human/hulk)) //NO HULK - return + return NONE + if(!source.can_unarmed_attack()) + return COMPONENT_CANCEL_ATTACK_CHAIN var/mob/living/living_target = target source.changeNext_move(CLICK_CD_MELEE) diff --git a/code/modules/surgery/organs/internal/lungs/_lungs.dm b/code/modules/surgery/organs/internal/lungs/_lungs.dm index 71dc305ac5f..faf67a4596f 100644 --- a/code/modules/surgery/organs/internal/lungs/_lungs.dm +++ b/code/modules/surgery/organs/internal/lungs/_lungs.dm @@ -514,6 +514,7 @@ if(prob(20)) n2o_euphoria = EUPHORIA_ACTIVE breather.emote(pick("giggle", "laugh")) + breather.set_drugginess(30 SECONDS) else n2o_euphoria = EUPHORIA_INACTIVE return diff --git a/code/modules/tgui_input/say_modal/modal.dm b/code/modules/tgui_input/say_modal/modal.dm index 3bfff57bd68..1185aaa12af 100644 --- a/code/modules/tgui_input/say_modal/modal.dm +++ b/code/modules/tgui_input/say_modal/modal.dm @@ -36,6 +36,7 @@ /datum/tgui_say/New(client/client, id) src.client = client window = new(client, id) + winset(client, "tgui_say", "size=1,1;is-visible=0;") window.subscribe(src, PROC_REF(on_message)) window.is_browser = TRUE @@ -62,11 +63,14 @@ */ /datum/tgui_say/proc/load() window_open = FALSE - winshow(client, "tgui_say", FALSE) + + winset(client, "tgui_say", "pos=848,500;size=231,30;is-visible=0;") + window.send_message("props", list( lightMode = client.prefs?.read_preference(/datum/preference/toggle/tgui_say_light_mode), maxLength = max_length, )) + stop_thinking() return TRUE @@ -84,9 +88,7 @@ window_open = TRUE if(payload["channel"] != OOC_CHANNEL && payload["channel"] != ADMIN_CHANNEL && payload["channel"] != LOOC_CHANNEL) // SKYRAT EDIT CHANGE (Add LOOC_CHANNEL) start_thinking() - if(client.typing_indicators) - log_speech_indicators("[key_name(client)] started typing at [loc_name(client.mob)], indicators enabled.") - else + if(!client.typing_indicators) log_speech_indicators("[key_name(client)] started typing at [loc_name(client.mob)], indicators DISABLED.") return TRUE @@ -97,9 +99,7 @@ /datum/tgui_say/proc/close() window_open = FALSE stop_thinking() - if(client.typing_indicators) - log_speech_indicators("[key_name(client)] stopped typing at [loc_name(client.mob)], indicators enabled.") - else + if(!client.typing_indicators) log_speech_indicators("[key_name(client)] stopped typing at [loc_name(client.mob)], indicators DISABLED.") /** diff --git a/code/modules/unit_tests/_unit_tests.dm b/code/modules/unit_tests/_unit_tests.dm index dd3a7ec9eff..4b6c7a737a9 100644 --- a/code/modules/unit_tests/_unit_tests.dm +++ b/code/modules/unit_tests/_unit_tests.dm @@ -148,6 +148,7 @@ #include "heretic_rituals.dm" #include "high_five.dm" #include "holidays.dm" +#include "hulk.dm" #include "human_through_recycler.dm" #include "hunger_curse.dm" #include "hydroponics_extractor_storage.dm" diff --git a/code/modules/unit_tests/dcs_check_list_arguments.dm b/code/modules/unit_tests/dcs_check_list_arguments.dm index 8089896ba3d..67d7417062b 100644 --- a/code/modules/unit_tests/dcs_check_list_arguments.dm +++ b/code/modules/unit_tests/dcs_check_list_arguments.dm @@ -1,18 +1,36 @@ /** - * list arguments for bespoke elements are treated just like any other datum: as a text ref in the ID. - * Using un-cached lists in AddElement() and RemoveElement() calls will just create new elements over - * and over. That's what this unit test is for. It's not a catch-all, but it does a decent job at it. + * list arguments for bespoke elements are treated as a text ref in the ID, like any other datum. + * Which means that, unless cached, using lists as arguments will lead to multiple instance of the same element + * being created over and over. + * + * Because of how it works, this unit test checks that these list datum args + * do not share similar contents (when rearranged in descending alpha-numerical order), to ensure that + * the least necessary amount of elements is created. So, using static lists may not be enough, + * for example, in the case of two different critters using the death_drops element to drop ectoplasm on death, since, + * despite being static lists, the two are different instances assigned to different mob types. + * + * Most of the time, you won't encounter two different static lists with similar contents used as element args, + * meaning using static lists is accepted. However, should that happen, it's advised to replace the instances + * with various string_x procs: lists, assoc_lists, assoc_nested_lists or numbers_list, depending on the type. + * + * In the case of an element where the position of the contents of each datum list argument is important, + * ELEMENT_DONT_SORT_LIST_ARGS should be added to its flags, to prevent such issues where the contents are similar + * when sorted, but the element instances are not. + * + * In the off-chance the element is not compatible with this unit test (such as for connect_loc et simila), + * you can also use ELEMENT_NO_LIST_UNIT_TEST so that they won't be processed by this unit test at all. */ /datum/unit_test/dcs_check_list_arguments /** - * This unit test requires every (tangible) atom to have been created at least once - * so its search is more accurate. That's why it's run after create_and_destroy. + * This unit test requires every (unless ignored) atom to have been created at least once + * for a more accurate search, which is why it's run after create_and_destroy is done running. */ priority = TEST_AFTER_CREATE_AND_DESTROY /datum/unit_test/dcs_check_list_arguments/Run() + var/we_failed = FALSE for(var/element_type in SSdcs.arguments_that_are_lists_by_element) - // Keeps tracks of the lists that shouldn't be compared with again. + // Keeps track of the lists that shouldn't be compared with again. var/list/to_ignore = list() var/list/superlist = SSdcs.arguments_that_are_lists_by_element[element_type] for(var/list/current as anything in superlist) @@ -27,7 +45,11 @@ bad_lists += list(compare) to_ignore[compare] = TRUE if(bad_lists) + we_failed = TRUE //Include the original, unsorted list in the report. It should be easier to find by the contributor. var/list/unsorted_list = superlist[current] - TEST_FAIL("found [length(bad_lists)] identical lists used as argument for element [element_type]. List: [json_encode(unsorted_list)].\n\ - Make sure it's a cached list, or use one of the string_list proc. Also, use the ELEMENT_DONT_SORT_LIST_ARGS flag if the key position of your lists matters.") + TEST_FAIL("Found [length(bad_lists)] datum list arguments with similar contents for [element_type]. Contents: [json_encode(unsorted_list)].") + ///Let's avoid sending the same instructions over and over, as it's just going to clutter the CI and confuse someone. + if(we_failed) + TEST_FAIL("Ensure that each list is static or cached. string_lists() (as well as similar procs) is your friend here.\n\ + Check the documentation from dcs_check_list_arguments.dm for more information!") diff --git a/code/modules/unit_tests/dragon_expiration.dm b/code/modules/unit_tests/dragon_expiration.dm index 7b36b576291..45262dc9d60 100644 --- a/code/modules/unit_tests/dragon_expiration.dm +++ b/code/modules/unit_tests/dragon_expiration.dm @@ -2,9 +2,12 @@ /datum/unit_test/contents_barfer /datum/unit_test/contents_barfer/Run() - var/mob/living/simple_animal/hostile/space_dragon/dragon_time = allocate(/mob/living/simple_animal/hostile/space_dragon) + var/mob/living/basic/space_dragon/dragon_time = allocate(/mob/living/basic/space_dragon) var/mob/living/carbon/human/to_be_consumed = allocate(/mob/living/carbon/human/consistent) + to_be_consumed.adjust_fire_stacks(5) + to_be_consumed.ignite_mob() TEST_ASSERT(dragon_time.eat(to_be_consumed), "The space dragon failed to consume the dummy!") + TEST_ASSERT(!to_be_consumed.has_status_effect(/datum/status_effect/fire_handler/fire_stacks), "The space dragon failed to extinguish the dummy!") TEST_ASSERT_EQUAL(to_be_consumed.loc, dragon_time, "The dummy's location, after being successfuly consumed, was not within the space dragon's contents!") dragon_time.death() TEST_ASSERT(isturf(to_be_consumed.loc), "After dying, the space dragon did not eject the consumed dummy content barfer element.") @@ -13,7 +16,7 @@ /datum/unit_test/space_dragon_expiration /datum/unit_test/space_dragon_expiration/Run() - var/mob/living/simple_animal/hostile/space_dragon/dragon_time = allocate(/mob/living/simple_animal/hostile/space_dragon) + var/mob/living/basic/space_dragon/dragon_time = allocate(/mob/living/basic/space_dragon) var/mob/living/carbon/human/to_be_consumed = allocate(/mob/living/carbon/human/consistent) dragon_time.mind_initialize() diff --git a/code/modules/unit_tests/hulk.dm b/code/modules/unit_tests/hulk.dm new file mode 100644 index 00000000000..52706e9ac73 --- /dev/null +++ b/code/modules/unit_tests/hulk.dm @@ -0,0 +1,44 @@ +/// Tests hulk attacking over normal attacking +/datum/unit_test/hulk_attack + var/hulk_hits = 0 + var/hand_hits = 0 + +/datum/unit_test/hulk_attack/Run() + var/mob/living/carbon/human/hulk = allocate(/mob/living/carbon/human/consistent) + var/mob/living/carbon/human/dummy = allocate(/mob/living/carbon/human/consistent) + + + RegisterSignal(dummy, COMSIG_ATOM_HULK_ATTACK, PROC_REF(hulk_sig_fire)) + RegisterSignal(dummy, COMSIG_ATOM_ATTACK_HAND, PROC_REF(hand_sig_fire)) + + hulk.dna.add_mutation(/datum/mutation/human/hulk) + hulk.set_combat_mode(TRUE) + hulk.ClickOn(dummy) + + TEST_ASSERT_EQUAL(hulk_hits, 1, "Hulk should have hit the dummy once.") + TEST_ASSERT_EQUAL(hand_hits, 0, "Hulk should not have hit the dummy with attack_hand.") + TEST_ASSERT(dummy.getBruteLoss(), "Dummy should have taken brute damage from being hulk punched.") + +/datum/unit_test/hulk_attack/proc/hulk_sig_fire() + SIGNAL_HANDLER + hulk_hits += 1 + +/datum/unit_test/hulk_attack/proc/hand_sig_fire() + SIGNAL_HANDLER + hand_hits += 1 + +/// Tests that hulks aren't given rapid attacks from rapid attack gloves +/datum/unit_test/hulk_north_star + +/datum/unit_test/hulk_north_star/Run() + var/mob/living/carbon/human/hulk = allocate(/mob/living/carbon/human/consistent) + var/mob/living/carbon/human/dummy = allocate(/mob/living/carbon/human/consistent) + var/obj/item/clothing/gloves/rapid/fotns = allocate(/obj/item/clothing/gloves/rapid) + + hulk.equip_to_appropriate_slot(fotns) + hulk.dna.add_mutation(/datum/mutation/human/hulk) + hulk.set_combat_mode(TRUE) + hulk.ClickOn(dummy) + + TEST_ASSERT_NOTEQUAL(hulk.next_move, world.time + CLICK_CD_RAPID, "Hulk should not gain the effects of the Fists of the North Star.") + TEST_ASSERT_EQUAL(hulk.next_move, world.time + CLICK_CD_MELEE, "Hulk click cooldown was a value not expected.") diff --git a/code/modules/unit_tests/simple_animal_freeze.dm b/code/modules/unit_tests/simple_animal_freeze.dm index fc258596d4a..9771862ad6b 100644 --- a/code/modules/unit_tests/simple_animal_freeze.dm +++ b/code/modules/unit_tests/simple_animal_freeze.dm @@ -163,8 +163,6 @@ /mob/living/simple_animal/hostile/skeleton/plasmaminer, /mob/living/simple_animal/hostile/skeleton/plasmaminer/jackhammer, /mob/living/simple_animal/hostile/skeleton/templar, - /mob/living/simple_animal/hostile/space_dragon, - /mob/living/simple_animal/hostile/space_dragon/spawn_with_antag, /mob/living/simple_animal/hostile/vatbeast, /mob/living/simple_animal/hostile/wizard, /mob/living/simple_animal/hostile/zombie, diff --git a/config/lavaruinblacklist.txt b/config/lavaruinblacklist.txt index b2574fd7fd6..2c0642bffac 100644 --- a/config/lavaruinblacklist.txt +++ b/config/lavaruinblacklist.txt @@ -41,17 +41,4 @@ _maps/RandomRuins/LavaRuins/lavaland_surface_ash_walker1.dmm #_maps/RandomRuins/LavaRuins/lavaland_surface_watcher_grave.dmm #_maps/RandomRuins/LavaRuins/lavaland_surface_ww_vault.dmm #_maps/RandomRuins/LavaRuins/lavaland_surface_wwiioutpost.dmm -<<<<<<< HEAD -#_maps/RandomRuins/LavaRuins/lavaland_surface_tomb.dmm -#_maps/RandomRuins/LavaRuins/lavaland_surface_hierophant.dmm -#_maps/RandomRuins/LavaRuins/lavaland_surface_pizzaparty.dmm -#_maps/RandomRuins/LavaRuins/lavaland_surface_cultaltar.dmm -#_maps/RandomRuins/LavaRuins/lavaland_surface_hermit.dmm -#_maps/RandomRuins/LavaRuins/lavaland_surface_gaia.dmm -#_maps/RandomRuins/LavaRuins/lavaland_surface_elephant_graveyard.dmm -#_maps/RandomRuins/LavaRuins/lavaland_surface_library.dmm -#_maps/RandomRuins/AnywhereRuins/fountain_hall.dmm -#_maps/RandomRuins/LavaRuins/lavaland_surface_phonebooth.dmm -======= #_maps/RandomRuins/LavaRuins/lavaland_surface_xeno_nest.dmm ->>>>>>> 0f5d14e68b1 (Mook village and basic mook refactor (#78789)) diff --git a/html/changelogs/archive/2023-08.yml b/html/changelogs/archive/2023-08.yml index b2d87c8f66c..cd0ea66cfbb 100644 --- a/html/changelogs/archive/2023-08.yml +++ b/html/changelogs/archive/2023-08.yml @@ -377,6 +377,10 @@ vinylspiders: - bugfix: greyscale color selection menu is now working again in the loadout prefs menu + AnywayFarus: + - bugfix: Fixed auto-accent on 515 + Iajret: + - bugfix: several minor journey and kilo fixes 2023-08-09: Fazzie: - qol: 'Many changes in Birdshot''s Library. @@ -1261,6 +1265,18 @@ - bugfix: The decloning virus is curable with rezadone again. tf-4: - spellcheck: Fixed examine text for gemital. + Iajret: + - bugfix: Some more fixes to journey and kilo + - bugfix: fixed several redsec reskins. Namely satchel, wintercoat, new bluesec + skirt and eyepatch reskins + Lazar: + - rscadd: New weak body quirk + - qol: New bluck to hand quirk + - balance: rebalanced teshari pounch damage and incoming damage + - sound: added/ teshari sounds and more GAS sounds + - image: added teshari MOD suits and modules iconds + - code_imp: changed human ride and human base code + - config: Added teshari new teshari to raundstart races, remove old 2023-08-27: GoldenAlpharex: - bugfix: Fixes the recycler being able to grind the server to a halt by trying diff --git a/html/changelogs/archive/2023-09.yml b/html/changelogs/archive/2023-09.yml index a45513671ce..e617c03b805 100644 --- a/html/changelogs/archive/2023-09.yml +++ b/html/changelogs/archive/2023-09.yml @@ -76,6 +76,10 @@ - bugfix: anti-fauna arrows now do their bonus damage against mining mobs - bugfix: bows will now display their ammo count correctly (1 when loaded instead of 2) + HWSensum: + - bugfix: fixed CQD holster sprite hiding. + - bugfix: holster now can be attached to any uniform. + - rscadd: Added new CQD holster. 2023-09-03: Guillaume Prata: - rscadd: 'New funny internals for the clowns to spawn with. They come with O2 and diff --git a/html/changelogs/archive/2023-10.yml b/html/changelogs/archive/2023-10.yml index 45cb9cd9c76..3e5becdb3ed 100644 --- a/html/changelogs/archive/2023-10.yml +++ b/html/changelogs/archive/2023-10.yml @@ -252,6 +252,9 @@ - bugfix: fixes gender shaping and height offsets on underwear - bugfix: female gender shaping now works with digi jumpsuits - bugfix: fixed rainbow jumpsuit digi sprite + HWSensum: + - rscadd: Added sanguirite recipe. It's made from salglu, phenol, carbon and water + (check in-game wiki!) 2023-10-07: GoldenAlpharex: - bugfix: The round end report will no longer expose people's ckeys for the achievements @@ -613,6 +616,8 @@ - qol: Table flipping feedback is now in the form of balloon alerts - rscadd: Robo can now print standard and alien surgical tools - bugfix: Defibs now dont screw over organics if the user was robotic + delingar: + - rscadd: Added new Halloween-themed craftable decorations 2023-10-13: Hatterhat: - bugfix: The CIN replicator medipen pouch and pocket first-aid kit no longer have @@ -669,27 +674,167 @@ as see a blurb in examine about it - rscadd: You can now buckle yourself to washing machines! This serves no practical purpose except for FUN TIMES. +2023-10-14: + LT3: + - image: Nitrogen canisters are now yellow, antinob are grey/yellow, empty are grey, + hydrogen are red/white + Melbert: + - bugfix: Fixes Mauna Loa, Monover, Silibinin, Granibitaluri not exiting your system + on metabolism + - bugfix: Fixes holy water exiting your system at double the rate on metabolism + - bugfix: Holy Water no longer spams cultists with big text every time, it's much + more tame now + Rhials: + - rscadd: Two new psyker-oriented virtual domains -- Crate Chaos and Infected Domain. + - rscadd: Map helper for cyber-police corpse spawn. + - rscadd: Map helper for swapping the encrypted crate in an area with a random crate + from that same area. + - qol: You can now return to your old body after being summoned by a manifest rune. + - qol: You can now return to your old body after dying in CTF. + - qol: You can now return to your old body after dying in the Medisim Shuttle battle + area. + - qol: You can no longer suicide in CTF areas, for integrity purposes. + SkyratBot: + - bugfix: Space Dragons can now, once again, tear down walls and eat corpses. They + also have regained their special damage modifier when attacking mechs. + - bugfix: Pete's anger management training has worn off, and he will once again + sometimes pick a fight with you for absolutely no reason. + - qol: Attacking a goat will not spam messages so frequently. + - admin: VV can now display the contents of special byond lists like filters, or + client.images + - admin: VV on images now displays the image in the header + - admin: VV can now display filters and includes their type + - qol: apples can now be sliced + - bugfix: sqdl2 query readout displays location of turfs properly + - sound: laser2.ogg sound has been changed. Now laser carbine uses it. + - image: Laser carbine and orange laser sprite have been improved. + - bugfix: '"Mirror Walk" is once more the domain of the Maid in the Mirror rather + than "every heretic summon"' + - bugfix: Heretic mobs can once again survive space + - rscadd: targetting someone's arm with *slap now has a unique message + - bugfix: The crew is instructed to place fax machines properly in the center of + a table without hanging. + - bugfix: Modsuits can no longer be deepfried + - bugfix: Space Dragon can break walls, eat corpses and destroy mechs more efficiently + again + - bugfix: Player-controlled lavaland elites can once again return to their tumor + after winning their fight + TheSS13Melon: + - rscadd: Adds the Security Patrol Cap and Sol Police Helmet to the security vendor + - rscadd: Adds the Sol Police Helmet to /datum/supply_pack/security/helmets_skyrat + - rscdel: Removes redsec helmets from /datum/supply_pack/security/helmets_skyrat + nikothedude: + - bugfix: Experimental robotic tend wounds now actually shows up +2023-10-15: + LT3: + - bugfix: Fixed moldies event default weight overriding the configured event weight + Melbert: + - qol: Leaning now has a small animation associated. + - qol: Cyborgs can now lean against walls. + - bugfix: Fixed some runtimes associated with leaning. + - bugfix: Fixed being able to lean while dead or in otherwise invalid states. + SkyratBot: + - bugfix: Fixes Monkey's Delight recipe + - refactor: Space Dragons are now basic mobs, please report any unexpected behaviour. + - balance: You can now see that a space dragon is destroying a wall with a visual + indicator of the wall being damaged. + - balance: Space Dragons can pry open airlocks. + - bugfix: makes the riot helmet hide hair like other sec helmets + - rscadd: Vent Pumps can now be overclocked, do some light reading in the air alarm + to figure out what this means. + - balance: Vent Pumps now have fan integrity, the damaging of which reduces their + ability to move air. + - sound: Overclocking sounds, including spool, stop, and loop + - balance: Allows spacemen to use age-appropriate drugs by making it so you can + now huff N2O to get high. + honkpocket: + - bugfix: fixed ghost bedsheet wearable being an error sprite on digitigrade legged + characters + vinylspiders: + - bugfix: fixed an issue that could cause the hair the layering option to reset + itself upon unequipping a paper mask + - qol: paper masks have an action button for adjusting the mask drawing + hair layering, + as well as the ability to hide the strap with ctrl click. changing the drawings + on the mask now require a pen. +2023-10-16: + SkyratBot: + - bugfix: plumbing setups should(hopefully) no longer grind to a halt nor will overflow + with excess volume of reagents. + - code_imp: created defines for min & max ph. Improved some reaction_reagent code. + Made synthesizer dispensable reagent list values static to save memory. + - refactor: ph balancing mechanism for reaction chamber is significantly improved. + Optimized it's code overall + - refactor: examining each individual reagent will display their results back to + 2 decimal places again and not 4 for easy readability. + - qol: Bladists can now use silver *or* titanium while creating their blades + - spellcheck: Broken canisters now have a description + - rscadd: Added Afro (Huge) hairstyle + Wallem: + - bugfix: The active sonar module won't attempt to create 6000000 new pings per + process cycle anymore + nikothedude: + - rscadd: The nobility dresscoat, donator reward for NikoTheGuyDude 2023-10-17: - AnywayFarus: - - bugfix: Fixed auto-accent on 515 - HWSensum: - - bugfix: fixed CQD holster sprite hiding. - - bugfix: holster now can be attached to any uniform. - - rscadd: Added new CQD holster. - - rscadd: Added sanguirite recipe. It's made from salglu, phenol, carbon and water - (check in-game wiki!) - Iajret: - - bugfix: several minor journey and kilo fixes - - bugfix: Some more fixes to journey and kilo - - bugfix: fixed several redsec reskins. Namely satchel, wintercoat, new bluesec - skirt and eyepatch reskins - Lazar: - - rscadd: New weak body quirk - - qol: New bluck to hand quirk - - balance: rebalanced teshari pounch damage and incoming damage - - sound: added/ teshari sounds and more GAS sounds - - image: added teshari MOD suits and modules iconds - - code_imp: changed human ride and human base code - - config: Added teshari new teshari to raundstart races, remove old - delingar: - - rscadd: Added new Halloween-themed craftable decorations + Fazzie: + - bugfix: Fixed the doors on the Beach away mission + - bugfix: Fixed the railings on the Beach away mission + - rscadd: The free golem ship has been swapped for a much better one, with fishing + equipment. + GoldenAlpharex: + - code_imp: Documented a huge part of telecommunications machinery and signal code, + and did some minor code improvements to said code. + - code_imp: Got rid of a few more single-letter variables. Only over six thousand + left to go, woo! + - bugfix: Hands of cards will now properly display the last card added to the hand + all the time, even when there's more than five cards in that hand. + LT3: + - bugfix: Fixed font scaling for announcements + - bugfix: The remaining survival pod bed on Icebox is now a medical bed + - bugfix: Announcement text now uses the intended CSS + - bugfix: Microwave will no longer get stuck turned on if a PDA has no cell + - bugfix: Silicons can no longer silently change the microwave between cook and + charge + Melbert: + - refactor: Refactored unarmed attacking mechanisms, this means dis-coordinated + humans will now bite people like monkeys (like how coordinated monkeys punch + people like humans?) + - refactor: Dis-coordinated humans smashing up machines now use their hands, rather + than their paws + Motho: + - sound: Plasmamen all across the sector have begun to announce their fright or + pain in a new way. + Paxilmaniac: + - image: A large number of security's clothing has been unified in color palette + and updated in style. + - rscdel: Some really old or unfitting security outfits, like the correction's officer's + weird hat and the unusued tactical peacekeeper jumpsuit have been removed. + RatFromTheJungle: + - qol: moves the self authentication device's bulky desc to an examine more, and + puts a shorter on in it's place. + SkyratBot: + - bugfix: Fixes a bug with the plasma flower core MODsuit that would cause a butterfly + murder scene wherever there were turrets + - sound: added sounds for scanning valued items with an export scanner + - bugfix: Delta's cargo bay has been connected to the atmos pipe networks + - bugfix: TGC Mana and Health bars are correctly offset on the holodeck. + - qol: Icebox Visitation now has a door connected to brig + - bugfix: Having all augmented limbs will make you properly spaceproof once again. + - bugfix: Androids are immune to crit damage again. + - bugfix: Surgery on robotic limbs can be canceled. + - code_imp: removed unnecessary calls to `update_total()` + - bugfix: Megafauna, lavaland elites, and abstract mobs now correctly cannot be + spawned by a toolbox of ash drake summoning + - bugfix: Fuel tanks are explosive again + - bugfix: TGUI Say should no longer flash during initialization + - bugfix: Fixes respiration-transmission advanced viruses to no longer have an always-guaranteed + infection chance per tick. + honkpocket: + - balance: The Bolt Pepperball AHG is now small sized instead of normal sized + jjpark-kb: + - rscadd: added the worm/ant farm + - balance: ash farming can be worm fertilized (same as regen core), but now only + does one harvest + - image: added the worm/ant farm, worm fertilizer + vinylspiders: + - bugfix: air alarm and mass driver controller in Voidraptor disposals room will + no longer overlap diff --git a/icons/mob/human/human_face.dmi b/icons/mob/human/human_face.dmi index 6530b300aa6..886f0bf793b 100644 Binary files a/icons/mob/human/human_face.dmi and b/icons/mob/human/human_face.dmi differ diff --git a/icons/obj/machines/atmospherics/unary_devices.dmi b/icons/obj/machines/atmospherics/unary_devices.dmi index 3350500fde9..6a929f211b8 100644 Binary files a/icons/obj/machines/atmospherics/unary_devices.dmi and b/icons/obj/machines/atmospherics/unary_devices.dmi differ diff --git a/modular_skyrat/master_files/code/game/objects/items/stacks/sheets/sheet_types.dm b/modular_skyrat/master_files/code/game/objects/items/stacks/sheets/sheet_types.dm index b74721c63ae..3c1cbc2cb0e 100644 --- a/modular_skyrat/master_files/code/game/objects/items/stacks/sheets/sheet_types.dm +++ b/modular_skyrat/master_files/code/game/objects/items/stacks/sheets/sheet_types.dm @@ -73,6 +73,7 @@ GLOBAL_LIST_INIT(skyrat_wood_recipes, list( new/datum/stack_recipe("sauna oven", /obj/structure/sauna_oven, 30, time = 1.5 SECONDS, one_per_turf = TRUE, on_solid_ground = TRUE, category = CAT_ENTERTAINMENT), new/datum/stack_recipe("large wooden mortar", /obj/structure/large_mortar, 10, time = 3 SECONDS, one_per_turf = TRUE, on_solid_ground = TRUE, category = CAT_TOOLS), new/datum/stack_recipe("wooden cutting board", /obj/item/cutting_board, 5, time = 2 SECONDS, check_density = FALSE, category = CAT_TOOLS), + new/datum/stack_recipe("worm barrel", /obj/structure/wormfarm, 5, time = 2 SECONDS, one_per_turf = TRUE, on_solid_ground = TRUE, category = CAT_TOOLS), )) /obj/item/stack/sheet/mineral/wood/get_main_recipes() @@ -129,3 +130,13 @@ GLOBAL_LIST_INIT(skyrat_snow_recipes, list( /obj/item/stack/sheet/mineral/snow/get_main_recipes() . = ..() . += GLOB.skyrat_snow_recipes + +// Sand + +GLOBAL_LIST_INIT(skyrat_sand_recipes, list( + new/datum/stack_recipe("ant farm", /obj/structure/antfarm, 20, time = 2 SECONDS, one_per_turf = TRUE, on_solid_ground = TRUE, category = CAT_TOOLS), +)) + +/obj/item/stack/ore/glass/get_main_recipes() + . = ..() + . += GLOB.skyrat_sand_recipes diff --git a/modular_skyrat/master_files/code/modules/clothing/under/costume.dm b/modular_skyrat/master_files/code/modules/clothing/under/costume.dm index 8fd875d2289..9e5567e4496 100644 --- a/modular_skyrat/master_files/code/modules/clothing/under/costume.dm +++ b/modular_skyrat/master_files/code/modules/clothing/under/costume.dm @@ -9,7 +9,7 @@ worn_icon = 'modular_skyrat/master_files/icons/mob/clothing/under/costume.dmi' can_adjust = FALSE -//My least favorite file. Just... try to keep it sorted. And nothing over the top (The victorian dresses were way too much) +//My least favorite file. Just... try to keep it sorted. And nothing over the top /* * UNSORTED diff --git a/modular_skyrat/master_files/code/modules/projectiles/ammunition/energy/stun.dm b/modular_skyrat/master_files/code/modules/projectiles/ammunition/energy/stun.dm new file mode 100644 index 00000000000..8d05d57e551 --- /dev/null +++ b/modular_skyrat/master_files/code/modules/projectiles/ammunition/energy/stun.dm @@ -0,0 +1,2 @@ +/obj/item/ammo_casing/energy/disabler/skyrat + e_cost = LASER_SHOTS(1, STANDARD_CELL_CHARGE) diff --git a/modular_skyrat/master_files/icons/donator/mob/clothing/suit.dmi b/modular_skyrat/master_files/icons/donator/mob/clothing/suit.dmi index da2fa01153b..ec84bdf6e76 100644 Binary files a/modular_skyrat/master_files/icons/donator/mob/clothing/suit.dmi and b/modular_skyrat/master_files/icons/donator/mob/clothing/suit.dmi differ diff --git a/modular_skyrat/master_files/icons/donator/obj/clothing/suits.dmi b/modular_skyrat/master_files/icons/donator/obj/clothing/suits.dmi index cfb3b90e070..140bd772f44 100644 Binary files a/modular_skyrat/master_files/icons/donator/obj/clothing/suits.dmi and b/modular_skyrat/master_files/icons/donator/obj/clothing/suits.dmi differ diff --git a/modular_skyrat/master_files/icons/mob/clothing/head.dmi b/modular_skyrat/master_files/icons/mob/clothing/head.dmi index a67c748a66d..dcb4e45d41b 100644 Binary files a/modular_skyrat/master_files/icons/mob/clothing/head.dmi and b/modular_skyrat/master_files/icons/mob/clothing/head.dmi differ diff --git a/modular_skyrat/master_files/icons/mob/clothing/head/helmet.dmi b/modular_skyrat/master_files/icons/mob/clothing/head/helmet.dmi index 63e6d14124d..6043c7fa83e 100644 Binary files a/modular_skyrat/master_files/icons/mob/clothing/head/helmet.dmi and b/modular_skyrat/master_files/icons/mob/clothing/head/helmet.dmi differ diff --git a/modular_skyrat/master_files/icons/mob/clothing/head/winterhood.dmi b/modular_skyrat/master_files/icons/mob/clothing/head/winterhood.dmi index f4d68afba7b..f07efd1c011 100644 Binary files a/modular_skyrat/master_files/icons/mob/clothing/head/winterhood.dmi and b/modular_skyrat/master_files/icons/mob/clothing/head/winterhood.dmi differ diff --git a/modular_skyrat/master_files/icons/mob/clothing/mask.dmi b/modular_skyrat/master_files/icons/mob/clothing/mask.dmi index 07bef00e9c4..8b52d28c7cb 100644 Binary files a/modular_skyrat/master_files/icons/mob/clothing/mask.dmi and b/modular_skyrat/master_files/icons/mob/clothing/mask.dmi differ diff --git a/modular_skyrat/master_files/icons/mob/clothing/neck.dmi b/modular_skyrat/master_files/icons/mob/clothing/neck.dmi index 3e29bf945b9..93c9d34c648 100644 Binary files a/modular_skyrat/master_files/icons/mob/clothing/neck.dmi and b/modular_skyrat/master_files/icons/mob/clothing/neck.dmi differ diff --git a/modular_skyrat/master_files/icons/mob/clothing/suit.dmi b/modular_skyrat/master_files/icons/mob/clothing/suit.dmi index c00b68f50cf..dd76a562f7b 100644 Binary files a/modular_skyrat/master_files/icons/mob/clothing/suit.dmi and b/modular_skyrat/master_files/icons/mob/clothing/suit.dmi differ diff --git a/modular_skyrat/master_files/icons/mob/clothing/suits/armor.dmi b/modular_skyrat/master_files/icons/mob/clothing/suits/armor.dmi index 24004a9b260..9d6de8b7cfc 100644 Binary files a/modular_skyrat/master_files/icons/mob/clothing/suits/armor.dmi and b/modular_skyrat/master_files/icons/mob/clothing/suits/armor.dmi differ diff --git a/modular_skyrat/master_files/icons/mob/clothing/suits/armor_digi.dmi b/modular_skyrat/master_files/icons/mob/clothing/suits/armor_digi.dmi index f6f7defe702..5ec98ebafa8 100644 Binary files a/modular_skyrat/master_files/icons/mob/clothing/suits/armor_digi.dmi and b/modular_skyrat/master_files/icons/mob/clothing/suits/armor_digi.dmi differ diff --git a/modular_skyrat/master_files/icons/mob/clothing/suits/wintercoat.dmi b/modular_skyrat/master_files/icons/mob/clothing/suits/wintercoat.dmi index 11e61ac81d7..a92a34ccc90 100644 Binary files a/modular_skyrat/master_files/icons/mob/clothing/suits/wintercoat.dmi and b/modular_skyrat/master_files/icons/mob/clothing/suits/wintercoat.dmi differ diff --git a/modular_skyrat/master_files/icons/mob/clothing/under/security.dmi b/modular_skyrat/master_files/icons/mob/clothing/under/security.dmi index 2b69e02fd83..0aeace1f82e 100644 Binary files a/modular_skyrat/master_files/icons/mob/clothing/under/security.dmi and b/modular_skyrat/master_files/icons/mob/clothing/under/security.dmi differ diff --git a/modular_skyrat/master_files/icons/mob/clothing/under/security_digi.dmi b/modular_skyrat/master_files/icons/mob/clothing/under/security_digi.dmi index ea98435846f..5b5a709889c 100644 Binary files a/modular_skyrat/master_files/icons/mob/clothing/under/security_digi.dmi and b/modular_skyrat/master_files/icons/mob/clothing/under/security_digi.dmi differ diff --git a/modular_skyrat/master_files/icons/obj/clothing/glasses.dmi b/modular_skyrat/master_files/icons/obj/clothing/glasses.dmi index 7a86c3a396e..d42c3f245b1 100644 Binary files a/modular_skyrat/master_files/icons/obj/clothing/glasses.dmi and b/modular_skyrat/master_files/icons/obj/clothing/glasses.dmi differ diff --git a/modular_skyrat/master_files/icons/obj/clothing/neck.dmi b/modular_skyrat/master_files/icons/obj/clothing/neck.dmi index 792b56aba8d..a3a71e6a73c 100644 Binary files a/modular_skyrat/master_files/icons/obj/clothing/neck.dmi and b/modular_skyrat/master_files/icons/obj/clothing/neck.dmi differ diff --git a/modular_skyrat/master_files/icons/obj/clothing/suits.dmi b/modular_skyrat/master_files/icons/obj/clothing/suits.dmi index 45b23619f89..bd5fb3aebba 100644 Binary files a/modular_skyrat/master_files/icons/obj/clothing/suits.dmi and b/modular_skyrat/master_files/icons/obj/clothing/suits.dmi differ diff --git a/modular_skyrat/master_files/icons/obj/clothing/suits/armor.dmi b/modular_skyrat/master_files/icons/obj/clothing/suits/armor.dmi index e0a71694d5b..30fd1d4cb22 100644 Binary files a/modular_skyrat/master_files/icons/obj/clothing/suits/armor.dmi and b/modular_skyrat/master_files/icons/obj/clothing/suits/armor.dmi differ diff --git a/modular_skyrat/master_files/icons/obj/clothing/under/security.dmi b/modular_skyrat/master_files/icons/obj/clothing/under/security.dmi index c9b5e383fea..ac3891c27c1 100644 Binary files a/modular_skyrat/master_files/icons/obj/clothing/under/security.dmi and b/modular_skyrat/master_files/icons/obj/clothing/under/security.dmi differ diff --git a/modular_skyrat/modules/alerts/code/priority_announce.dm b/modular_skyrat/modules/alerts/code/priority_announce.dm deleted file mode 100644 index 196806f6130..00000000000 --- a/modular_skyrat/modules/alerts/code/priority_announce.dm +++ /dev/null @@ -1,139 +0,0 @@ -/** - * Make a big red text announcement to - * - * Formatted like: - * - * " Message from sender " - * - * " Title " - * - * " Text " - * - * Arguments - * * text - required, the text to announce - * * title - optional, the title of the announcement. - * * sound - optional, the sound played accompanying the announcement - * * type - optional, the type of the announcement, for some "preset" announcement templates. "Priority", "Captain", "Syndicate Captain" - * * sender_override - optional, modifies the sender of the announcement - * * has_important_message - is this message critical to the game (and should not be overridden by station traits), or not - * * players - a list of all players to send the message to. defaults to all players (not including new players) - * * encode_title - if TRUE, the title will be HTML encoded - * * encode_text - if TRUE, the text will be HTML encoded - */ -/proc/priority_announce(text, title = "", sound, type, sender_override, has_important_message = FALSE, list/mob/players, encode_title = TRUE, encode_text = TRUE) - if(!text) - return - - if(encode_title && title && length(title) > 0) - title = html_encode(title) - if(encode_text) - text = html_encode(text) - if(!length(text)) - return - - var/announcement - - if(!sound) - sound = SSstation.announcer.get_rand_alert_sound() - else if(SSstation.announcer.event_sounds[sound]) - var/list/picked = SSstation.announcer.event_sounds[sound] - sound = pick(picked) - - if(type == "Priority") - announcement += "

Priority Announcement

" - if (title && length(title) > 0) - announcement += "

[title]

" - else if(type == JOB_CAPTAIN) - announcement += "

Captain Announces

" - GLOB.news_network.submit_article(text, "Captain's Announcement", "Station Announcements", null) - else if(type == "Syndicate Captain") - announcement += "

Syndicate Captain Announces

" - - else - if(!sender_override) - announcement += "

[command_name()] Update

" - else - announcement += "

[sender_override]

" - if (title && length(title) > 0) - announcement += "

[title]

" - - if(!sender_override) - if(title == "") - GLOB.news_network.submit_article(text, "Central Command Update", "Station Announcements", null) - else - GLOB.news_network.submit_article(title + "

" + text, "Central Command", "Station Announcements", null) - - ///If the announcer overrides alert messages, use that message. - if(SSstation.announcer.custom_alert_message && !has_important_message) - announcement += SSstation.announcer.custom_alert_message - else - announcement += "
[text]
" - announcement += "
" - - if(!players) - players = GLOB.player_list - - var/sound_to_play = sound(sound) - - alert_sound_to_playing(sound_to_play, players = players) - - for(var/mob/target in players) - if(!isnewplayer(target) && target.can_hear()) - to_chat(target, announcement) - -/proc/print_command_report(text = "", title = null, announce=TRUE) - if(!title) - title = "Classified [command_name()] Update" - - if(announce) - priority_announce("A report has been downloaded and printed out at all communications consoles.", "Incoming Classified Message", SSstation.announcer.get_rand_report_sound(), has_important_message = TRUE) - - var/datum/comm_message/M = new - M.title = title - M.content = text - - SScommunications.send_message(M) - -/** - * Sends a minor annoucement to players. - * Minor announcements are large text, with the title in red and message in white. - * Only mobs that can hear can see the announcements. - * - * message - the message contents of the announcement. - * title - the title of the announcement, which is often "who sent it". - * alert - whether this announcement is an alert, or just a notice. Only changes the sound that is played by default. - * html_encode - if TRUE, we will html encode our title and message before sending it, to prevent player input abuse. - * players - optional, a list mobs to send the announcement to. If unset, sends to all palyers. - * sound_override - optional, use the passed sound file instead of the default notice sounds. We're not currently using those on Skyrat, since we use our own sounds. - */ -/proc/minor_announce(message, title = "Attention:", alert, html_encode = TRUE, list/players, sound_override, override_volume = FALSE) - if(!message) - return - - if (html_encode) - title = html_encode(title) - message = html_encode(message) - - if(!players) - players = GLOB.player_list - - for(var/mob/target in players) - if(isnewplayer(target)) - continue - if(!target.can_hear()) - continue - - to_chat(target, "[span_minorannounce("[title]
[message]")]
") - - if(sound_override) - if(SSstation.announcer.event_sounds[sound_override]) - var/list/picked = SSstation.announcer.event_sounds[sound_override] - sound_override = pick(picked) - alert_sound_to_playing(sound_override, override_volume = override_volume, players = players) - - else if(alert) - alert_sound_to_playing(sound('modular_skyrat/modules/alerts/sound/alerts/alert1.ogg'), players = players) - else - alert_sound_to_playing(sound('sound/misc/notice2.ogg'), players = players) - - diff --git a/modular_skyrat/modules/ashwalkers/code/buildings/antfarm.dm b/modular_skyrat/modules/ashwalkers/code/buildings/antfarm.dm new file mode 100644 index 00000000000..49065d0f5b7 --- /dev/null +++ b/modular_skyrat/modules/ashwalkers/code/buildings/antfarm.dm @@ -0,0 +1,80 @@ +/obj/structure/antfarm + name = "ant farm" + desc = "Though it may look natural, this was not made by ants." + icon = 'modular_skyrat/modules/ashwalkers/icons/structures.dmi' + icon_state = "anthill" + density = TRUE + anchored = TRUE + /// If the farm is occupied by ants + var/has_ants = FALSE + /// the chance for the farm to get ants + var/ant_chance = 0 + /// the list of ore-y stuff that ants can drag up from deep within their nest + var/list/ore_list = list( + /obj/item/stack/ore/iron = 20, + /obj/item/stack/ore/glass = 20, + /obj/item/stack/sheet/mineral/plasma = 14, + /obj/item/stack/sheet/mineral/silver = 8, + /obj/item/xenoarch/strange_rock = 8, + /obj/item/stack/sheet/mineral/coal = 8, + /obj/item/stack/sheet/mineral/titanium = 8, + /obj/item/stack/sheet/mineral/uranium = 3, + /obj/item/stack/sheet/mineral/gold = 3, + ) + // The cooldown between each worm "breeding" + COOLDOWN_DECLARE(ant_timer) + +/obj/structure/antfarm/Initialize(mapload) + . = ..() + var/turf/src_turf = get_turf(src) + if(!istype(get_turf(src), /turf/open/misc/asteroid/basalt)) + src_turf.balloon_alert_to_viewers("must be on basalt") + return INITIALIZE_HINT_QDEL + + for(var/obj/structure/antfarm/found_farm in range(2, get_turf(src))) + if(found_farm == src) + continue + + src_turf.balloon_alert_to_viewers("too close to another farm") + return INITIALIZE_HINT_QDEL + + START_PROCESSING(SSobj, src) + COOLDOWN_START(src, ant_timer, 30 SECONDS) + +/obj/structure/antfarm/Destroy() + STOP_PROCESSING(SSobj, src) + new /obj/item/stack/ore/glass/ten(get_turf(src)) + return ..() + +/obj/structure/antfarm/process(seconds_per_tick) + if(!COOLDOWN_FINISHED(src, ant_timer)) + return + + COOLDOWN_START(src, ant_timer, 30 SECONDS) + + if(!has_ants) + if(prob(ant_chance)) + balloon_alert_to_viewers("ants have appeared!") + has_ants = TRUE + + return + + var/spawned_ore = pick_weight(ore_list) + new spawned_ore(get_turf(src)) + +/obj/structure/antfarm/examine(mob/user) + . = ..() + . += span_notice("
There are currently [has_ants ? "" : "no "]ants in the farm.") + . += span_notice("To add ants, feed the farm some food.") + +/obj/structure/antfarm/attackby(obj/item/attacking_item, mob/user, params) + if(istype(attacking_item, /obj/item/food)) + qdel(attacking_item) + balloon_alert(user, "food has been placed") + ant_chance++ + return + + return ..() + +/obj/item/stack/ore/glass/ten + amount = 10 diff --git a/modular_skyrat/modules/ashwalkers/code/buildings/ash_farming.dm b/modular_skyrat/modules/ashwalkers/code/buildings/ash_farming.dm index 51f161ee81e..c1fcae5f962 100644 --- a/modular_skyrat/modules/ashwalkers/code/buildings/ash_farming.dm +++ b/modular_skyrat/modules/ashwalkers/code/buildings/ash_farming.dm @@ -80,8 +80,6 @@ var/obj/item/seeds/planted_seed ///the max amount harvested from the plants var/max_harvest = 3 - ///the amount of harvests from using a regen core - var/regen_harvest_num = 4 ///the cooldown amount between each harvest var/harvest_cooldown = 1 MINUTES //the cooldown between each harvest @@ -112,7 +110,7 @@ . += span_notice("
[src] will be ready for harvest in [DisplayTimeText(COOLDOWN_TIMELEFT(src, harvest_timer))]") . += span_notice("
You can use sinew to lower the time between each harvest!") . += span_notice("You can use goliath hides to increase the amount dropped per harvest!") - . += span_notice("You can use a regenerative core to force the plant to drop four harvests!") + . += span_notice("You can use a regenerative core or worm fertilizer to force the plant to drop a harvest!") /obj/structure/simple_farm/process(seconds_per_tick) update_appearance() @@ -186,11 +184,10 @@ balloon_alert_to_viewers("the plant drops more!") return - //if its a regen core, then create four harvests - else if(istype(attacking_item, /obj/item/organ/internal/monster_core/regenerative_core)) + //if its a regen core or worm fertilizer, then create four harvests + else if(istype(attacking_item, /obj/item/organ/internal/monster_core/regenerative_core) || istype(attacking_item, /obj/item/worm_fertilizer)) qdel(attacking_item) - for(var/i in 1 to regen_harvest_num) - create_harvest() + create_harvest() return return ..() diff --git a/modular_skyrat/modules/ashwalkers/code/buildings/wormfarm.dm b/modular_skyrat/modules/ashwalkers/code/buildings/wormfarm.dm new file mode 100644 index 00000000000..5d7a69d5a77 --- /dev/null +++ b/modular_skyrat/modules/ashwalkers/code/buildings/wormfarm.dm @@ -0,0 +1,116 @@ +/obj/structure/wormfarm + name = "worm farm" + desc = "A wonderfully dirty barrel where worms can have a happy little life." + icon = 'modular_skyrat/modules/ashwalkers/icons/structures.dmi' + icon_state = "wormbarrel" + density = TRUE + anchored = FALSE + /// How many worms can the barrel hold + var/max_worm = 10 + /// How many worms the barrel is currently holding + var/current_worm = 0 + /// If the barrel is currently being used by someone + var/in_use = FALSE + // The cooldown between each worm "breeding" + COOLDOWN_DECLARE(worm_timer) + +/obj/structure/wormfarm/Initialize(mapload) + . = ..() + START_PROCESSING(SSobj, src) + COOLDOWN_START(src, worm_timer, 1 MINUTES) + +/obj/structure/wormfarm/Destroy() + STOP_PROCESSING(SSobj, src) + return ..() + +//process is currently only used for making more worms +/obj/structure/wormfarm/process(seconds_per_tick) + if(!COOLDOWN_FINISHED(src, worm_timer)) + return + + COOLDOWN_START(src, worm_timer, 1 MINUTES) + + if(current_worm < 2 || current_worm >= max_worm) + return + + current_worm++ + +/obj/structure/wormfarm/examine(mob/user) + . = ..() + . += span_notice("
There are currently [current_worm]/[max_worm] worms in the barrel.") + if(current_worm < max_worm) + . += span_notice("You can place more worms in the barrel.") + if(current_worm > 0) + . += span_notice("You can get fertilizer by feeding the worms food.") + +/obj/structure/wormfarm/attack_hand(mob/living/user, list/modifiers) + if(in_use) + balloon_alert(user, "currently in use") + return ..() + + balloon_alert(user, "digging up worms") + if(!do_after(user, 5 SECONDS, src)) + balloon_alert(user, "stopped digging") + in_use = FALSE + return ..() + + if(current_worm <= 0) + balloon_alert(user, "no worms available") + in_use = FALSE + return ..() + + new /obj/item/food/bait/worm(get_turf(src)) + current_worm-- + in_use = FALSE + + return ..() + +/obj/structure/wormfarm/attackby(obj/item/attacking_item, mob/user, params) + //we want to check for worms first because they are a type of food as well... + if(istype(attacking_item, /obj/item/food/bait/worm)) + if(current_worm >= max_worm) + balloon_alert(user, "too many worms in the barrel") + return + + qdel(attacking_item) + balloon_alert(user, "worm released into barrel") + current_worm++ + return + + //if it aint a worm, lets check for any other food items + if(istype(attacking_item, /obj/item/food)) + if(in_use) + balloon_alert(user, "currently in use") + return + in_use = TRUE + + balloon_alert(user, "feeding the worms") + if(!do_after(user, 5 SECONDS, src)) + balloon_alert(user, "stopped feeding the worms") + in_use = FALSE + return + + // if someone has built multiple worm farms, I want to make sure they can't just use one singular piece of food for more than one barrel + if(!attacking_item) + in_use = FALSE + return + + qdel(attacking_item) + balloon_alert(user, "feeding complete") + + if(current_worm > 0) + new /obj/item/worm_fertilizer(get_turf(src)) + + in_use = FALSE + return + + //it wasn't a worm, or a piece of food + return ..() + +//produced by feeding worms food and can be ground up for plant nutriment or used directly on ash farming +/obj/item/worm_fertilizer + name = "worm fertilizer" + desc = "When you fed your worms, you should have expected this." + icon = 'modular_skyrat/modules/ashwalkers/icons/misc_tools.dmi' + icon_state = "fertilizer" + grind_results = list(/datum/reagent/plantnutriment/eznutriment = 3, /datum/reagent/plantnutriment/left4zednutriment = 3, /datum/reagent/plantnutriment/robustharvestnutriment = 3) diff --git a/modular_skyrat/modules/ashwalkers/icons/misc_tools.dmi b/modular_skyrat/modules/ashwalkers/icons/misc_tools.dmi index 21d7b4c967f..a619ff2e36c 100644 Binary files a/modular_skyrat/modules/ashwalkers/icons/misc_tools.dmi and b/modular_skyrat/modules/ashwalkers/icons/misc_tools.dmi differ diff --git a/modular_skyrat/modules/ashwalkers/icons/structures.dmi b/modular_skyrat/modules/ashwalkers/icons/structures.dmi new file mode 100644 index 00000000000..d4e229d8255 Binary files /dev/null and b/modular_skyrat/modules/ashwalkers/icons/structures.dmi differ diff --git a/modular_skyrat/modules/black_mesa/code/shockplant.dm b/modular_skyrat/modules/black_mesa/code/shockplant.dm index 3d77cbe6635..78b357677cb 100644 --- a/modular_skyrat/modules/black_mesa/code/shockplant.dm +++ b/modular_skyrat/modules/black_mesa/code/shockplant.dm @@ -11,7 +11,7 @@ light_power = 0.5 light_color = "#53fafa" /// Our faction - var/faction = FACTION_XEN + faction = list(FACTION_XEN) /// Our range to shock folks in. var/shock_range = 6 /// Our cooldown on the shocking. @@ -34,7 +34,7 @@ if(isliving(entered_atom)) var/mob/living/entering_mob = entered_atom - if(faction in entering_mob.faction) + if(faction_check_atom(entering_mob)) return tesla_zap(src, shock_range, shock_power, shocked_targets = list(entering_mob)) playsound(src, 'sound/magic/lightningbolt.ogg', 100, TRUE) diff --git a/modular_skyrat/modules/cellguns/code/medigun_cells.dm b/modular_skyrat/modules/cellguns/code/medigun_cells.dm index e846c2ec685..c02118d226e 100644 --- a/modular_skyrat/modules/cellguns/code/medigun_cells.dm +++ b/modular_skyrat/modules/cellguns/code/medigun_cells.dm @@ -6,7 +6,7 @@ projectile_type = /obj/projectile/energy/medical/oxygen select_name = "oxygen" fire_sound = 'sound/effects/stealthoff.ogg' - e_cost = 120 + e_cost = LASER_SHOTS(8, STANDARD_CELL_CHARGE) delay = 8 harmful = FALSE select_color = "#00d9ffff" diff --git a/modular_skyrat/modules/command_vendor/code/vending.dm b/modular_skyrat/modules/command_vendor/code/vending.dm index 432956fc3df..7e9c35f2471 100644 --- a/modular_skyrat/modules/command_vendor/code/vending.dm +++ b/modular_skyrat/modules/command_vendor/code/vending.dm @@ -119,10 +119,8 @@ access_lists["[ACCESS_HOS]"] = list( /obj/item/clothing/head/hats/hos/cap = 1, /obj/item/clothing/head/hats/hos/beret/navyhos = 1, - /obj/item/clothing/head/hats/hos/cap/peacekeeper/sol = 1, /obj/item/clothing/head/hats/imperial/hos = 1, /obj/item/clothing/under/rank/security/head_of_security/peacekeeper = 1, - /obj/item/clothing/under/rank/security/head_of_security/peacekeeper/sol = 1, /obj/item/clothing/under/rank/security/head_of_security/alt = 1, /obj/item/clothing/under/rank/security/head_of_security/alt/skirt = 1, /obj/item/clothing/under/rank/security/head_of_security/skyrat/imperial = 1, diff --git a/modular_skyrat/modules/customization/modules/clothing/head/head.dm b/modular_skyrat/modules/customization/modules/clothing/head/head.dm index 7fa2112f764..2d40cf577a2 100644 --- a/modular_skyrat/modules/customization/modules/clothing/head/head.dm +++ b/modular_skyrat/modules/customization/modules/clothing/head/head.dm @@ -55,51 +55,6 @@ acid = 50 wound = 6 -/obj/item/clothing/head/hats/sec/peacekeeper/sol - name = "sol police cap" - desc = "Be a proper boy in blue with this cap, comes with a black visor to block out inconvenient truths." - icon = 'modular_skyrat/master_files/icons/obj/clothing/hats.dmi' - worn_icon = 'modular_skyrat/master_files/icons/mob/clothing/head.dmi' - icon_state = "policeofficercap" - supports_variations_flags = CLOTHING_SNOUTED_VARIATION_NO_NEW_ICON - armor_type = /datum/armor/head_helmet - -/obj/item/clothing/head/hats/sec/cap/peacekeeper/sol/dark - name = "police patrol cap" - desc = "A dark colored hat with a silver badge, for the officer interested in style." - icon = 'modular_skyrat/master_files/icons/obj/clothing/hats.dmi' - worn_icon = 'modular_skyrat/master_files/icons/mob/clothing/head.dmi' - icon_state = "policeofficerpatrolcap" - supports_variations_flags = CLOTHING_SNOUTED_VARIATION_NO_NEW_ICON - armor_type = /datum/armor/head_helmet - -/obj/item/clothing/head/hats/hos/cap/peacekeeper/sol - name = "sol police chief cap" - desc = "A blue hat adorned with gold, rumoured to be used to distract Agents with its swag." - icon = 'modular_skyrat/master_files/icons/obj/clothing/hats.dmi' - worn_icon = 'modular_skyrat/master_files/icons/mob/clothing/head.dmi' - icon_state = "policechiefcap" - supports_variations_flags = CLOTHING_SNOUTED_VARIATION_NO_NEW_ICON - -/obj/item/clothing/head/hats/sec/peacekeeper/sol/traffic - name = "sol traffic cop cap" - desc = "You think that's Shitcurrity? That's just Civil Shitsputes, I'll show you REAL Shitcurrity." - icon = 'modular_skyrat/master_files/icons/obj/clothing/hats.dmi' - worn_icon = 'modular_skyrat/master_files/icons/mob/clothing/head.dmi' - icon_state = "policetrafficcap" - supports_variations_flags = CLOTHING_SNOUTED_VARIATION_NO_NEW_ICON - armor_type = /datum/armor/head_helmet -/obj/item/clothing/head/helmet/sec/sol - name = "sol police helmet" - desc = "A helmet to protect any officer from bludgeoning attacks, or the occasional bullet." - icon = 'modular_skyrat/master_files/icons/obj/clothing/head/helmet.dmi' - worn_icon = 'modular_skyrat/master_files/icons/mob/clothing/head/helmet.dmi' - icon_state = "security_helmet_novisor" - base_icon_state = "security_helmet_novisor" - actions_types = NONE - supports_variations_flags = CLOTHING_SNOUTED_VARIATION_NO_NEW_ICON - armor_type = /datum/armor/head_helmet - /obj/item/clothing/head/colourable_flatcap name = "colourable flat cap" desc = "You in the computers son? You work the computers?" diff --git a/modular_skyrat/modules/customization/modules/clothing/masks/breath.dm b/modular_skyrat/modules/customization/modules/clothing/masks/breath.dm index a65f4a57416..57365317844 100644 --- a/modular_skyrat/modules/customization/modules/clothing/masks/breath.dm +++ b/modular_skyrat/modules/customization/modules/clothing/masks/breath.dm @@ -38,7 +38,7 @@ to_chat(user, "You pull the balaclava up to cover your whole head.") open = 0 user.update_body_parts() - user.update_inv_ears(0) + user.update_inv_ears() user.update_worn_mask() //Updates mob icons /obj/item/clothing/mask/balaclavaadjust/attack_self(mob/user) diff --git a/modular_skyrat/modules/customization/modules/clothing/masks/paper.dm b/modular_skyrat/modules/customization/modules/clothing/masks/paper.dm index 97b52485b4b..e141f569004 100644 --- a/modular_skyrat/modules/customization/modules/clothing/masks/paper.dm +++ b/modular_skyrat/modules/customization/modules/clothing/masks/paper.dm @@ -1,3 +1,17 @@ +/datum/action/item_action/adjust/papermask + name = "Adjust paper mask" + desc = "LMB: Change mask face. RMB: Adjust mask." + +/datum/action/item_action/adjust/papermask/Trigger(trigger_flags) + . = ..() + if(!.) + return + var/obj/item/clothing/mask/paper/paper_mask = target + if(trigger_flags & TRIGGER_SECONDARY_ACTION) + paper_mask.adjust_mask(usr) + else + paper_mask.reskin_obj(usr) + /obj/item/clothing/mask/paper name = "paper mask" desc = "It's true. Once you wear a mask for so long, you forget about who you are. Wonder if that happens with shitty paper ones." @@ -7,8 +21,7 @@ clothing_flags = MASKINTERNALS flags_inv = HIDEFACIALHAIR|HIDESNOUT w_class = WEIGHT_CLASS_SMALL - /// Whether or not the mask is currently being layered over (or under!) hair. - var/wear_over_hair = TRUE + actions_types = list(/datum/action/item_action/adjust/papermask) unique_reskin = list( "Blank" = "mask_paper", "Neutral" = "mask_neutral", @@ -37,40 +50,85 @@ "Sad" = "mask_sad", ) + /// Whether or not the mask is currently being layered over (or under!) hair. FALSE/null means the mask is layered over the hair (this is how it starts off). + var/wear_hair_over + /// Whether or not the strap is currently hidden or visible + var/strap_hidden + /obj/item/clothing/mask/paper/Initialize(mapload) . = ..() register_context() - if(wear_over_hair) + if(wear_hair_over) alternate_worn_layer = BACK_LAYER +/obj/item/clothing/mask/paper/worn_overlays(mutable_appearance/standing, isinhands, icon_file) + . = ..() + if(!strap_hidden) + . += mutable_appearance(icon_file, "mask_paper_strap") + +/obj/item/clothing/mask/paper/alt_click_secondary(mob/user) + . = ..() + if(.) + return + if(user.can_perform_action(src, NEED_DEXTERITY)) + adjust_mask(user) + +/obj/item/clothing/mask/paper/CtrlClick(mob/user) + . = ..() + if(.) + return + if(user.can_perform_action(src, NEED_DEXTERITY)) + adjust_strap(user) + /obj/item/clothing/mask/paper/add_context(atom/source, list/context, obj/item/held_item, mob/user) . = ..() context[SCREENTIP_CONTEXT_ALT_LMB] = "Change Mask Face" + context[SCREENTIP_CONTEXT_ALT_RMB] = "Adjust Mask" + context[SCREENTIP_CONTEXT_CTRL_LMB] = "Hide/Show Strap" return CONTEXTUAL_SCREENTIP_SET /obj/item/clothing/mask/paper/reskin_obj(mob/user) + if(!user.is_holding_item_of_type(/obj/item/pen)) + balloon_alert(user, "must be holding a pen!") + return + . = ..() - user.update_worn_mask() + + var/mob/living/carbon/carbon_user + if(iscarbon(user)) + carbon_user = user + if(carbon_user && carbon_user.wear_mask == src) + carbon_user.update_worn_mask() + current_skin = null //so we can infinitely reskin /obj/item/clothing/mask/paper/proc/adjust_mask(mob/living/carbon/human/user) if(!istype(user)) return if(!user.incapacitated()) - wear_over_hair = !wear_over_hair - if(wear_over_hair) + var/is_worn = user.wear_mask == src + wear_hair_over = !wear_hair_over + if(wear_hair_over) alternate_worn_layer = BACK_LAYER - to_chat(user, "You sweep your hair over the mask.") + to_chat(user, "You [is_worn ? "" : "will "]sweep your hair over the mask.") else alternate_worn_layer = initial(alternate_worn_layer) - to_chat(user, "You sweep your hair under the mask.") + to_chat(user, "You [is_worn ? "" : "will "]sweep your hair under the mask.") + + user.update_worn_mask() + +/obj/item/clothing/mask/paper/proc/adjust_strap(mob/living/carbon/human/user) + if(!istype(user)) + return + if(!user.incapacitated()) + var/is_worn = user.wear_mask == src + strap_hidden = !strap_hidden + to_chat(user, "You [is_worn ? "" : "will "][strap_hidden ? "hide" : "show"] the mask strap.") - user.update_body_parts() - user.update_inv_ears(0) user.update_worn_mask() -/obj/item/clothing/mask/paper/verb/toggle() - set category = "Object" - set name = "Adjust Mask" - set src in usr - adjust_mask(usr) +// Because alternate_worn_layer can potentially get reset on unequipping the mask (ex: for 'Top' snouts), let's make sure we don't lose it our settings +/obj/item/clothing/mask/paper/dropped(mob/living/carbon/human/user) + var/prev_alternate_worn_layer = alternate_worn_layer + . = ..() + alternate_worn_layer = prev_alternate_worn_layer diff --git a/modular_skyrat/modules/customization/modules/clothing/under/security.dm b/modular_skyrat/modules/customization/modules/clothing/under/security.dm index fae7cb750aa..ffbbcdcccc3 100644 --- a/modular_skyrat/modules/customization/modules/clothing/under/security.dm +++ b/modular_skyrat/modules/customization/modules/clothing/under/security.dm @@ -44,37 +44,6 @@ supports_variations_flags = NONE can_adjust = FALSE -// Police Uniforms -///OFFICERS -/obj/item/clothing/under/rank/security/peacekeeper/sol/cadet - name = "sol police cadet uniform" - desc = "A light blue shirt with navy pants, and no other markings. This is essentially no more than a fancy blue suit." - icon_state = "policecadetalt" - -/obj/item/clothing/under/rank/security/peacekeeper/sol - name = "sol police uniform" - desc = "A light blue shirt with navy pants, and a golden insignia on the shoulder. Perfect for standing around idly during emergencies." - icon = 'modular_skyrat/master_files/icons/obj/clothing/under/security.dmi' - worn_icon = 'modular_skyrat/master_files/icons/mob/clothing/under/security.dmi' - icon_state = "policealt" - supports_variations_flags = CLOTHING_DIGITIGRADE_VARIATION | CLOTHING_MONKEY_VARIATION - -///WARDEN -/obj/item/clothing/under/rank/security/warden/peacekeeper/sol - name = "sol warden uniform" - desc = "A light blue shirt with navy pants. This one bears the insignia of a Warden, as well as the stretch marks." - icon_state = "policewardenalt" - -///HEAD OF SECURITY -/obj/item/clothing/under/rank/security/head_of_security/peacekeeper/sol - name = "sol chief of police uniform" - desc = "A white satin shirt with golden pauldrons and a leather belt, which has a large \"NT\" for a buckle. Nice to see where the budget went." - icon = 'modular_skyrat/master_files/icons/obj/clothing/under/security.dmi' - worn_icon = 'modular_skyrat/master_files/icons/mob/clothing/under/security.dmi' - icon_state = "policechiefalt" - -// End Police Uniforms - /// PRISONER /obj/item/clothing/under/rank/prisoner/protcust name = "protective custody prisoner jumpsuit" diff --git a/modular_skyrat/modules/customization/modules/clothing/~donator/donator_clothing.dm b/modular_skyrat/modules/customization/modules/clothing/~donator/donator_clothing.dm index 746380b59cb..f76fb35ac83 100644 --- a/modular_skyrat/modules/customization/modules/clothing/~donator/donator_clothing.dm +++ b/modular_skyrat/modules/customization/modules/clothing/~donator/donator_clothing.dm @@ -1657,3 +1657,71 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/structure/sign/poster/contraband/korpstech, 32) desc = "These boots make you feel like you can walk on space." icon_state = "archerboots" inhand_icon_state = "archerboots" + +// Donation reward for nikotheguydude +/obj/item/clothing/suit/toggle/labcoat/medical/vic_dresscoat_donator + icon = 'modular_skyrat/master_files/icons/donator/obj/clothing/suits.dmi' + worn_icon = 'modular_skyrat/master_files/icons/donator/mob/clothing/suit.dmi' + icon_state = "vickyred" + name = "nobility dresscoat" + desc = "An elaborate coat composed of a silky yet firm material. \ + The fabric is quite thin, and provides negligible protection or insulation, \ + but is pleasant on the skin.\nWhile extremely well made, it seems quite \ + fragile, and rather expensive. You get the feeling it might not \ + survive a washing machine without specialized treatment." + special_desc = "It's buttons are pressed with some kind of sigil - which, to those knowledgeable in \ + Tiziran politics or nobility, would be recognizable as the Kor'Yesh emblem, \ + a relatively minor house of nobility within Tizira.\n\n\ + On a closer inspection, it would appear the interior is modified with protective material and mounting points \ + most often found on medical labcoats." + limb_integrity = 100 // note that this is usually disabled by having it set to 0, so this is just strictly worse + body_parts_covered = CHEST|ARMS + supports_variations_flags = CLOTHING_DIGITIGRADE_VARIATION_NO_NEW_ICON + +/obj/item/clothing/suit/toggle/labcoat/medical/vic_dresscoat_donator/Initialize(mapload) + . = ..() + + qdel(GetComponent(/datum/component/toggle_icon)) // we dont have a toggle icon + +#define NOBILITY_DRESSCOAT_WASHING_CREDITS_NEEDED 2500 + +// this is based on an in-joke with the character whom inspires this donator item, where they need a fuckton of money to wash their coat. this takes it literally +/obj/item/clothing/suit/toggle/labcoat/medical/vic_dresscoat_donator/machine_wash(obj/machinery/washing_machine/washer) + + var/total_credits = 0 + var/list/obj/item/money_to_delete = list() + for (var/obj/item/holochip/chip in washer) + total_credits += chip.get_item_credit_value() + money_to_delete += chip + if (total_credits >= NOBILITY_DRESSCOAT_WASHING_CREDITS_NEEDED) + break + if (total_credits < NOBILITY_DRESSCOAT_WASHING_CREDITS_NEEDED) + for (var/obj/item/stack/spacecash/cash in washer) + total_credits += cash.get_item_credit_value() + money_to_delete += cash + if (total_credits >= NOBILITY_DRESSCOAT_WASHING_CREDITS_NEEDED) + break + + var/message + var/sound_effect_path + var/sound_effect_volume + if (total_credits >= NOBILITY_DRESSCOAT_WASHING_CREDITS_NEEDED) // all is well + message = span_notice("[src] seems to absorb the raw capital from its surroundings, and is successfully washed!") + sound_effect_path = 'sound/effects/whirthunk.ogg' + sound_effect_volume = 40 + for (var/obj/item/entry_to_delete as anything in money_to_delete) + qdel(entry_to_delete) + else // IT COSTS ME A THOUSAND CREDITS TO WASH THIS!! HALF MY BUDGET IS DRY CLEANING + message = span_warning("[src]'s delicate fabric is shredded by [washer]! How terrible!") + sound_effect_path = 'sound/effects/cloth_rip.ogg' + sound_effect_volume = 30 + for (var/zone as anything in cover_flags2body_zones(body_parts_covered)) + take_damage_zone(zone, limb_integrity * 1.1, BRUTE) // fucking shreds it + + var/turf/our_turf = get_turf(src) + our_turf.visible_message(message) + playsound(src, sound_effect_path, sound_effect_volume, FALSE) + + return ..() + +#undef NOBILITY_DRESSCOAT_WASHING_CREDITS_NEEDED diff --git a/modular_skyrat/modules/decay_subsystem/code/nests.dm b/modular_skyrat/modules/decay_subsystem/code/nests.dm index 74424371e87..dc883affe2a 100644 --- a/modular_skyrat/modules/decay_subsystem/code/nests.dm +++ b/modular_skyrat/modules/decay_subsystem/code/nests.dm @@ -12,12 +12,12 @@ light_range = 2 light_power = 1 light_color = LIGHT_COLOR_LAVA + faction = list(NEST_FACTION) var/spawn_delay = 0 /// What mob to spawn var/list/monster_types = list(/mob/living/simple_animal/hostile/blackmesa/xen/headcrab) /// How many mobs can we spawn? var/max_mobs = 3 - var/list/faction = list(NEST_FACTION) var/spawned_mobs = 0 /// How long it takes for a new mob to emerge after being triggered. var/spawn_cooldown = 30 SECONDS diff --git a/modular_skyrat/modules/emotes/code/dna_screams.dm b/modular_skyrat/modules/emotes/code/dna_screams.dm index 61905297d3b..c57a80d55aa 100644 --- a/modular_skyrat/modules/emotes/code/dna_screams.dm +++ b/modular_skyrat/modules/emotes/code/dna_screams.dm @@ -40,7 +40,7 @@ femalescreamsounds = null /datum/species/plasmaman - screamsounds = list('modular_skyrat/modules/emotes/sound/voice/scream_skeleton.ogg') + screamsounds = list('sound/voice/plasmaman/plasmeme_scream_1.ogg', 'sound/voice/plasmaman/plasmeme_scream_2.ogg', 'sound/voice/plasmaman/plasmeme_scream_3.ogg') femalescreamsounds = null /datum/species/vox diff --git a/modular_skyrat/modules/emotes/code/scream_datums.dm b/modular_skyrat/modules/emotes/code/scream_datums.dm index f85bf745093..8e75aa7f556 100644 --- a/modular_skyrat/modules/emotes/code/scream_datums.dm +++ b/modular_skyrat/modules/emotes/code/scream_datums.dm @@ -95,7 +95,10 @@ GLOBAL_LIST_EMPTY(scream_types) /datum/scream_type/ethereal name = "Ethereal Scream" - male_screamsounds = list('sound/voice/ethereal/ethereal_scream_1.ogg', 'sound/voice/ethereal/ethereal_scream_2.ogg', 'sound/voice/ethereal/ethereal_scream_3.ogg') + male_screamsounds = list( + 'sound/voice/ethereal/ethereal_scream_1.ogg', + 'sound/voice/ethereal/ethereal_scream_2.ogg', + 'sound/voice/ethereal/ethereal_scream_3.ogg') female_screamsounds = null //DONATOR SCREAMS @@ -118,3 +121,11 @@ GLOBAL_LIST_EMPTY(scream_types) name = "Skeleton Scream" male_screamsounds = list('modular_skyrat/modules/emotes/sound/voice/scream_skeleton.ogg') female_screamsounds = null + +/datum/scream_type/plasmaman + name = "Plasmaman Scream" + male_screamsounds = list( + 'sound/voice/plasmaman/plasmeme_scream_1.ogg', + 'sound/voice/plasmaman/plasmeme_scream_2.ogg', + 'sound/voice/plasmaman/plasmeme_scream_3.ogg') + female_screamsounds = null diff --git a/modular_skyrat/modules/goofsec/code/sec_clothing_overrides.dm b/modular_skyrat/modules/goofsec/code/sec_clothing_overrides.dm index f1bece74ab4..f19659068cb 100644 --- a/modular_skyrat/modules/goofsec/code/sec_clothing_overrides.dm +++ b/modular_skyrat/modules/goofsec/code/sec_clothing_overrides.dm @@ -461,10 +461,6 @@ RESKIN_ICON_STATE = "vest_white", RESKIN_WORN_ICON_STATE = "vest_white" ), - "Peacekeeper Variant" = list( - RESKIN_ICON_STATE = "peacekeeper_white", - RESKIN_WORN_ICON_STATE = "peacekeeper_white" - ) ) /obj/item/clothing/suit/armor/hos @@ -497,10 +493,6 @@ //Standard Bulletproof Vest /obj/item/clothing/suit/armor/bulletproof desc = "A Type-III-AD-P heavy bulletproof vest that excels in protecting the wearer against traditional projectile weaponry and explosives to a minor extent." - icon = 'modular_skyrat/master_files/icons/obj/clothing/suits/armor.dmi' - worn_icon = 'modular_skyrat/master_files/icons/mob/clothing/suits/armor.dmi' - icon_state = "vest_bulletproof" - body_parts_covered = CHEST|GROIN|ARMS //Our sprite has groin and arm protections, so we get it too. supports_variations_flags = CLOTHING_DIGITIGRADE_VARIATION_NO_NEW_ICON //Riot Armor diff --git a/modular_skyrat/modules/gunpoint/code/gunpoint_datum.dm b/modular_skyrat/modules/gunpoint/code/gunpoint_datum.dm index 2791dd9a66f..53cacafd360 100644 --- a/modular_skyrat/modules/gunpoint/code/gunpoint_datum.dm +++ b/modular_skyrat/modules/gunpoint/code/gunpoint_datum.dm @@ -76,7 +76,7 @@ /datum/gunpoint/Destroy() UnregisterSignal(aimed_gun, list(COMSIG_ITEM_DROPPED, COMSIG_ITEM_EQUIPPED)) - UnregisterSignal(target, list(COMSIG_QDELETING, COMSIG_MOB_ITEM_AFTERATTACK, COMSIG_ITEM_ATTACK_SELF, COMSIG_HUMAN_MELEE_UNARMED_ATTACK, COMSIG_ITEM_ATTACK_SELF, COMSIG_MOVABLE_RADIO_TALK_INTO, COMSIG_MOB_FIRED_GUN, COMSIG_MOVABLE_MOVED)) + UnregisterSignal(target, list(COMSIG_QDELETING, COMSIG_MOB_ITEM_AFTERATTACK, COMSIG_ITEM_ATTACK_SELF, COMSIG_LIVING_UNARMED_ATTACK, COMSIG_ITEM_ATTACK_SELF, COMSIG_MOVABLE_RADIO_TALK_INTO, COMSIG_MOB_FIRED_GUN, COMSIG_MOVABLE_MOVED)) UnregisterSignal(source, list(COMSIG_QDELETING, COMSIG_MOVABLE_MOVED, COMSIG_LIVING_STATUS_STUN, COMSIG_LIVING_STATUS_KNOCKDOWN, COMSIG_LIVING_STATUS_PARALYZE, COMSIG_LIVING_UPDATED_RESTING)) REMOVE_TRAIT(source, TRAIT_NORUNNING, "gunpoint") diff --git a/modular_skyrat/modules/icspawning/code/standard.dm b/modular_skyrat/modules/icspawning/code/standard.dm index 5de008c8901..bd30194d2bf 100644 --- a/modular_skyrat/modules/icspawning/code/standard.dm +++ b/modular_skyrat/modules/icspawning/code/standard.dm @@ -4,7 +4,7 @@ w_class = WEIGHT_CLASS_TINY /obj/item/ammo_casing/energy/electrode/debug - e_cost = 1 + e_cost = LASER_SHOTS(1000, STANDARD_CELL_CHARGE) /obj/item/clothing/suit/armor/vest/debug name = "Bluespace Tech vest" diff --git a/modular_skyrat/modules/loadouts/loadout_items/donator/personal/donator_personal.dm b/modular_skyrat/modules/loadouts/loadout_items/donator/personal/donator_personal.dm index c41311e4694..e02a25d1b0d 100644 --- a/modular_skyrat/modules/loadouts/loadout_items/donator/personal/donator_personal.dm +++ b/modular_skyrat/modules/loadouts/loadout_items/donator/personal/donator_personal.dm @@ -719,3 +719,8 @@ name = "Noble Boots" item_path = /obj/item/clothing/shoes/jackboots/noble ckeywhitelist = list("grasshand") + +/datum/loadout_item/suit/nobility_dresscoat + name = "Nobility Dresscoat" + item_path = /obj/item/clothing/suit/toggle/labcoat/medical/vic_dresscoat_donator + ckeywhitelist = list("nikotheguydude") diff --git a/modular_skyrat/modules/loadouts/loadout_items/loadout_datum_heads.dm b/modular_skyrat/modules/loadouts/loadout_items/loadout_datum_heads.dm index f48b9341ffa..1c161f8f380 100644 --- a/modular_skyrat/modules/loadouts/loadout_items/loadout_datum_heads.dm +++ b/modular_skyrat/modules/loadouts/loadout_items/loadout_datum_heads.dm @@ -496,16 +496,6 @@ GLOBAL_LIST_INIT(loadout_helmets, generate_loadout_items(/datum/loadout_item/hea item_path = /obj/item/clothing/head/beret/sec/navyofficer restricted_roles = list(JOB_SECURITY_OFFICER, JOB_HEAD_OF_SECURITY, JOB_WARDEN) -/datum/loadout_item/head/solofficercap - name = "Security Officer's Sol Cap" - item_path = /obj/item/clothing/head/hats/sec/peacekeeper/sol - restricted_roles = list(JOB_SECURITY_OFFICER, JOB_HEAD_OF_SECURITY, JOB_WARDEN) - -/datum/loadout_item/head/soltrafficoff - name = "Traffic Officer Cap" - item_path = /obj/item/clothing/head/hats/sec/peacekeeper/sol/traffic - restricted_roles = list(JOB_SECURITY_OFFICER, JOB_HEAD_OF_SECURITY, JOB_WARDEN) - /datum/loadout_item/head/navybluewardenberet name = "Warden's Navy Blue beret" item_path = /obj/item/clothing/head/beret/sec/navywarden diff --git a/modular_skyrat/modules/loadouts/loadout_items/under/loadout_datum_under.dm b/modular_skyrat/modules/loadouts/loadout_items/under/loadout_datum_under.dm index 528f8e6dc34..2d2c3a20fae 100644 --- a/modular_skyrat/modules/loadouts/loadout_items/under/loadout_datum_under.dm +++ b/modular_skyrat/modules/loadouts/loadout_items/under/loadout_datum_under.dm @@ -114,19 +114,14 @@ GLOBAL_LIST_INIT(loadout_miscunders, generate_loadout_items(/datum/loadout_item/ item_path = /obj/item/clothing/under/rank/captain/skyrat/imperial/generic/pants restricted_roles = list(JOB_CAPTAIN, JOB_HEAD_OF_PERSONNEL, JOB_BLUESHIELD, JOB_HEAD_OF_SECURITY, JOB_RESEARCH_DIRECTOR, JOB_QUARTERMASTER, JOB_CHIEF_MEDICAL_OFFICER, JOB_CHIEF_ENGINEER, JOB_NT_REP) -/datum/loadout_item/under/jumpsuit/solwarden - name = "Sol Warden Uniform" - item_path = /obj/item/clothing/under/rank/security/warden/peacekeeper/sol - restricted_roles = list(JOB_WARDEN) - /datum/loadout_item/under/jumpsuit/security_trousers name = "Security Trousers" item_path = /obj/item/clothing/under/rank/security/peacekeeper/trousers restricted_roles = list(JOB_SECURITY_OFFICER, JOB_WARDEN, JOB_HEAD_OF_SECURITY) -/datum/loadout_item/under/jumpsuit/solofficer - name = "Sol Officer Uniform" - item_path = /obj/item/clothing/under/rank/security/peacekeeper/sol +/datum/loadout_item/under/jumpsuit/security_peacekeeper + name = "Security Peacekeeper Uniform" + item_path = /obj/item/clothing/under/rank/security/peacekeeper restricted_roles = list(JOB_SECURITY_OFFICER, JOB_WARDEN, JOB_HEAD_OF_SECURITY) /datum/loadout_item/under/jumpsuit/disco diff --git a/modular_skyrat/modules/medical/code/wounds/muscle.dm b/modular_skyrat/modules/medical/code/wounds/muscle.dm index 35cc54c7099..329d69b9387 100644 --- a/modular_skyrat/modules/medical/code/wounds/muscle.dm +++ b/modular_skyrat/modules/medical/code/wounds/muscle.dm @@ -46,10 +46,10 @@ /datum/wound/muscle/set_victim(new_victim) if (victim) - UnregisterSignal(victim, COMSIG_HUMAN_EARLY_UNARMED_ATTACK) + UnregisterSignal(victim, COMSIG_LIVING_EARLY_UNARMED_ATTACK) if (new_victim) - RegisterSignal(new_victim, COMSIG_HUMAN_EARLY_UNARMED_ATTACK, PROC_REF(attack_with_hurt_hand)) + RegisterSignal(new_victim, COMSIG_LIVING_EARLY_UNARMED_ATTACK, PROC_REF(attack_with_hurt_hand)) return ..() diff --git a/modular_skyrat/modules/microfusion/code/projectiles.dm b/modular_skyrat/modules/microfusion/code/projectiles.dm index 6e90ebfda46..f14bb7c3888 100644 --- a/modular_skyrat/modules/microfusion/code/projectiles.dm +++ b/modular_skyrat/modules/microfusion/code/projectiles.dm @@ -5,7 +5,7 @@ /obj/item/ammo_casing/energy/laser/microfusion name = "microfusion energy lens" projectile_type = /obj/projectile/beam/laser/microfusion - e_cost = 100 // 12 shots with a normal cell. + e_cost = LASER_SHOTS(10, STANDARD_CELL_CHARGE) // 10 shots with a normal cell. select_name = "laser" fire_sound = 'modular_skyrat/modules/microfusion/sound/laser_1.ogg' fire_sound_volume = 100 diff --git a/modular_skyrat/modules/modular_implants/code/nifs.dm b/modular_skyrat/modules/modular_implants/code/nifs.dm index 6ce9f780f83..12d9c67ad81 100644 --- a/modular_skyrat/modules/modular_implants/code/nifs.dm +++ b/modular_skyrat/modules/modular_implants/code/nifs.dm @@ -505,10 +505,10 @@ new /obj/item/autosurgeon/organ/nif/ghost_role(src) new /obj/item/disk/nifsoft_uploader/shapeshifter(src) new /obj/item/disk/nifsoft_uploader/summoner(src) - new /obj/item/disk/nifsoft_uploader/money_sense(src) new /obj/item/disk/nifsoft_uploader/dorms(src) new /obj/item/disk/nifsoft_uploader/dorms/hypnosis(src) new /obj/item/disk/nifsoft_uploader/soulcatcher(src) + new /obj/item/disk/nifsoft_uploader/money_sense(src) /obj/item/storage/box/nif_ghost_box/ghost_role/PopulateContents() . = ..() diff --git a/modular_skyrat/modules/modular_implants/code/nifsofts/base_types/action_granter.dm b/modular_skyrat/modules/modular_implants/code/nifsofts/base_types/action_granter.dm index 05d1012d629..f43b6d1d058 100644 --- a/modular_skyrat/modules/modular_implants/code/nifsofts/base_types/action_granter.dm +++ b/modular_skyrat/modules/modular_implants/code/nifsofts/base_types/action_granter.dm @@ -1,4 +1,4 @@ -/// This type of NIFSoft grans the user an action when active. +/// This type of NIFSoft grants the user an action when active. /datum/nifsoft/action_granter active_mode = TRUE activation_cost = 10 diff --git a/modular_skyrat/modules/modular_implants/code/nifsofts/shapeshifter.dm b/modular_skyrat/modules/modular_implants/code/nifsofts/shapeshifter.dm index dfa70dc78eb..113ea015e76 100644 --- a/modular_skyrat/modules/modular_implants/code/nifsofts/shapeshifter.dm +++ b/modular_skyrat/modules/modular_implants/code/nifsofts/shapeshifter.dm @@ -1,6 +1,6 @@ /obj/item/disk/nifsoft_uploader/shapeshifter name = "Polymorph" - loaded_nifsoft = /datum/nifsoft/action_granter + loaded_nifsoft = /datum/nifsoft/action_granter/shapeshifter /datum/nifsoft/action_granter/shapeshifter name = "Polymorph" diff --git a/modular_skyrat/modules/modular_weapons/code/pepperball_gun.dm b/modular_skyrat/modules/modular_weapons/code/pepperball_gun.dm index e507cfe1a6a..aa24209512a 100644 --- a/modular_skyrat/modules/modular_weapons/code/pepperball_gun.dm +++ b/modular_skyrat/modules/modular_weapons/code/pepperball_gun.dm @@ -3,7 +3,7 @@ desc = "An incredibly mediocre 'firearm' designed to fire soft pepper balls meant to easily subdue targets." icon = 'modular_skyrat/modules/modular_weapons/icons/obj/pepperball/pepperball.dmi' icon_state = "peppergun" - w_class = WEIGHT_CLASS_NORMAL + w_class = WEIGHT_CLASS_SMALL accepted_magazine_type = /obj/item/ammo_box/magazine/pepperball can_suppress = FALSE fire_sound = 'sound/effects/pop_expl.ogg' diff --git a/modular_skyrat/modules/mold/code/mold_event.dm b/modular_skyrat/modules/mold/code/mold_event.dm index da6dee42b3f..7c8f32caff0 100644 --- a/modular_skyrat/modules/mold/code/mold_event.dm +++ b/modular_skyrat/modules/mold/code/mold_event.dm @@ -7,7 +7,6 @@ name = "Moldies" description = "A mold outbreak on the station. The mold will spread across the station if not contained." typepath = /datum/round_event/mold - weight = 5 max_occurrences = 1 earliest_start = 30 MINUTES min_players = EVENT_LOWPOP_THRESHOLD diff --git a/modular_skyrat/modules/novaya_ert/code/surplus_weapons.dm b/modular_skyrat/modules/novaya_ert/code/surplus_weapons.dm index bcc8b49c26d..aa9fda10f89 100644 --- a/modular_skyrat/modules/novaya_ert/code/surplus_weapons.dm +++ b/modular_skyrat/modules/novaya_ert/code/surplus_weapons.dm @@ -45,7 +45,7 @@ /obj/item/ammo_casing/energy/laser/plasma_glob projectile_type = /obj/projectile/beam/laser/plasma_glob fire_sound = 'modular_skyrat/modules/microfusion/sound/incinerate.ogg' - e_cost = 50 + e_cost = LASER_SHOTS(20, STANDARD_CELL_CHARGE) /obj/projectile/beam/laser/plasma_glob name = "plasma globule" diff --git a/modular_skyrat/modules/sec_haul/code/corrections_officer/corrections_officer.dm b/modular_skyrat/modules/sec_haul/code/corrections_officer/corrections_officer.dm index 48ff0b3905e..8b03d305bb0 100644 --- a/modular_skyrat/modules/sec_haul/code/corrections_officer/corrections_officer.dm +++ b/modular_skyrat/modules/sec_haul/code/corrections_officer/corrections_officer.dm @@ -52,7 +52,7 @@ satchel = /obj/item/storage/backpack/satchel/sec duffelbag = /obj/item/storage/backpack/duffelbag/sec messenger = /obj/item/storage/backpack/messenger/sec - head = /obj/item/clothing/head/corrections_officer + head = /obj/item/clothing/head/security_garrison box = /obj/item/storage/box/survival/security belt = /obj/item/modular_computer/pda/security diff --git a/modular_skyrat/modules/sec_haul/code/corrections_officer/corrections_officer_equipment.dm b/modular_skyrat/modules/sec_haul/code/corrections_officer/corrections_officer_equipment.dm index c8af0829db2..848c487ff57 100644 --- a/modular_skyrat/modules/sec_haul/code/corrections_officer/corrections_officer_equipment.dm +++ b/modular_skyrat/modules/sec_haul/code/corrections_officer/corrections_officer_equipment.dm @@ -31,14 +31,6 @@ icon_state = "sec_headset" keyslot = new /obj/item/encryptionkey/headset_sec -/obj/item/clothing/head/corrections_officer - name = "corrections officer's cap" - desc = "A black visor cap with a round Nanotrasen logo made out of silver in the center, the most it'll do is protect you from some light rain...Or a prisoner slopping out." - icon = 'modular_skyrat/master_files/icons/obj/clothing/hats.dmi' - worn_icon = 'modular_skyrat/master_files/icons/mob/clothing/head.dmi' - icon_state = "corrections_officer" - supports_variations_flags = CLOTHING_SNOUTED_VARIATION_NO_NEW_ICON - /obj/item/clothing/suit/toggle/jacket/corrections_officer name = "corrections officer's suit jacket" desc = "A pressed and ironed suit jacket, it has light armor against stabbings. There's some rank badges on the right breast." diff --git a/modular_skyrat/modules/sec_haul/code/misc/vending.dm b/modular_skyrat/modules/sec_haul/code/misc/vending.dm index e1dae691029..29e0c77cb50 100644 --- a/modular_skyrat/modules/sec_haul/code/misc/vending.dm +++ b/modular_skyrat/modules/sec_haul/code/misc/vending.dm @@ -47,19 +47,15 @@ /obj/item/storage/backpack/duffelbag/sec = 5, /obj/item/clothing/under/rank/security/officer = 10, /obj/item/clothing/under/rank/security/officer/skirt = 10, - /obj/item/clothing/under/rank/security/peacekeeper/tactical = 4, - /obj/item/clothing/under/rank/security/peacekeeper/sol/cadet = 3, - /obj/item/clothing/under/rank/security/peacekeeper/sol = 3, + /obj/item/clothing/under/rank/security/peacekeeper = 10, /obj/item/clothing/under/rank/security/skyrat/utility = 3, /obj/item/clothing/shoes/jackboots/sec = 10, /obj/item/clothing/head/security_garrison = 10, /obj/item/clothing/head/security_cap = 10, /obj/item/clothing/head/beret/sec/peacekeeper = 5, - /obj/item/clothing/head/costume/ushanka/sec = 10, /obj/item/clothing/head/helmet/sec/sol = 5, - /obj/item/clothing/head/hats/sec/peacekeeper/sol = 5, - /obj/item/clothing/head/hats/sec/peacekeeper/sol/traffic = 5, - /obj/item/clothing/head/hats/sec/cap/peacekeeper/sol/dark = 5, + /obj/item/clothing/head/hats/warden/police/patrol = 5, + /obj/item/clothing/head/costume/ushanka/sec = 10, /obj/item/clothing/gloves/color/black/security = 10, ) premium = list( /obj/item/clothing/under/rank/security/officer/formal = 3, diff --git a/modular_skyrat/modules/sec_haul/code/peacekeeper/peacekeeper_clothing.dm b/modular_skyrat/modules/sec_haul/code/peacekeeper/peacekeeper_clothing.dm index 2f3fbba8c63..68467bfb1bf 100644 --- a/modular_skyrat/modules/sec_haul/code/peacekeeper/peacekeeper_clothing.dm +++ b/modular_skyrat/modules/sec_haul/code/peacekeeper/peacekeeper_clothing.dm @@ -1,16 +1,3 @@ - -//PEACEKEEPER HELMET -/obj/item/clothing/head/helmet/sec/peacekeeper - name = "peacekeeper helmet" - desc = "A standard issue combat helmet for peacekeeper operators. Has decent tensile strength and armor. Keep your head down." - icon = 'modular_skyrat/master_files/icons/obj/clothing/head/helmet.dmi' - worn_icon = 'modular_skyrat/master_files/icons/mob/clothing/head/helmet.dmi' - icon_state = "peacekeeper_helmet" - base_icon_state = "peacekeeper_helmet" - can_toggle = FALSE - actions_types = null - supports_variations_flags = CLOTHING_SNOUTED_VARIATION_NO_NEW_ICON - /obj/item/clothing/head/beret/sec/peacekeeper name = "peacekeeper beret" desc = "A robust beret with the peacekeeper insignia emblazoned on it. Uses reinforced fabric to offer sufficient protection." @@ -28,15 +15,6 @@ icon_state = "beret" greyscale_colors = "#EAEAEA" -/obj/item/clothing/head/hats/sec/peacekeeper/sergeant - name = "peacekeeper sergeant hat" - desc = "A drill sergeants cap, wearing this increases your loudness. So they say." - icon = 'modular_skyrat/master_files/icons/obj/clothing/hats.dmi' - worn_icon = 'modular_skyrat/master_files/icons/mob/clothing/head.dmi' - icon_state = "peacekeeper_sergeant_cap" - supports_variations_flags = CLOTHING_SNOUTED_VARIATION_NO_NEW_ICON - armor_type = /datum/armor/hats_warden - /obj/item/clothing/head/hats/hos/beret/peacekeeper name = "head of security's peacekeeper beret" desc = "A special beret with the Head of Security's insignia emblazoned on it. A symbol of excellence, a badge of courage, a mark of distinction." @@ -48,11 +26,31 @@ desc = "A special beret with the Warden's insignia emblazoned on it. For wardens with class." greyscale_config = /datum/greyscale_config/beret_badge_fancy greyscale_config_worn = /datum/greyscale_config/beret_badge_fancy/worn - greyscale_colors = "#3F3C40#FF0000#00AEEF" + greyscale_colors = "#3f6e9e#FF0000#00AEEF" icon_state = "beret_badge_fancy_twist" supports_variations_flags = CLOTHING_SNOUTED_VARIATION_NO_NEW_ICON armor_type = /datum/armor/hats_warden +/obj/item/clothing/head/helmet/sec/sol + name = "sol police helmet" + desc = "A helmet to protect any officer from bludgeoning attacks, or the occasional bullet." + icon = 'modular_skyrat/master_files/icons/obj/clothing/head/helmet.dmi' + worn_icon = 'modular_skyrat/master_files/icons/mob/clothing/head/helmet.dmi' + icon_state = "security_helmet_novisor" + base_icon_state = "security_helmet_novisor" + actions_types = NONE + supports_variations_flags = CLOTHING_SNOUTED_VARIATION_NO_NEW_ICON + armor_type = /datum/armor/head_helmet + +/obj/item/clothing/head/hats/warden/police/patrol + name = "police patrol cap" + desc = "A dark colored hat with a silver badge, for the officer interested in style." + icon = 'modular_skyrat/master_files/icons/obj/clothing/hats.dmi' + worn_icon = 'modular_skyrat/master_files/icons/mob/clothing/head.dmi' + icon_state = "policeofficerpatrolcap" + supports_variations_flags = CLOTHING_SNOUTED_VARIATION_NO_NEW_ICON + armor_type = /datum/armor/head_helmet + /obj/item/clothing/glasses/hud/security/sunglasses/peacekeeper name = "peacekeeper hud glasses" icon_state = "peacekeeperglasses" @@ -70,16 +68,6 @@ sensor_mode = SENSOR_COORDS random_sensor = FALSE -/obj/item/clothing/under/rank/security/peacekeeper/tactical - name = "tactical peacekeeper uniform" - desc = "A tactical peacekeeper uniform, woven with a lightweight layer of kevlar to provide minor ballistic and stab protection." - icon_state = "peacekeeper_tac" - -/obj/item/clothing/under/rank/security/peacekeeper/sergeant - name = "peacekeeper sergeant uniform" - desc = "A sleek peackeeper uniform, signifying the rank of Sergeant." - icon_state = "peacekeeper_sergeant" - /obj/item/clothing/under/rank/security/warden/peacekeeper name = "peacekeeper wardens suit" desc = "A formal security suit for officers complete with Armadyne belt buckle." @@ -122,14 +110,6 @@ . = ..() AddComponent(/datum/component/toggle_icon, "zipper") -/obj/item/clothing/suit/armor/vest/warden/peacekeeper - name = "warden's peacekeeper jacket" - desc = "A deep blue jacket with some simple body armor strapped over the top." - icon = 'modular_skyrat/master_files/icons/obj/clothing/suits/armor.dmi' - worn_icon = 'modular_skyrat/master_files/icons/mob/clothing/suits/armor.dmi' - icon_state = "peacekeeper_trench_warden" - supports_variations_flags = CLOTHING_DIGITIGRADE_VARIATION_NO_NEW_ICON - /obj/item/clothing/suit/armor/vest/peacekeeper/spacecoat name = "peacekeeper sleek coat" desc = "An incredibly stylish and heavy black coat made of synthetic kangaroo leather, padded with durathread and lined with kevlar." diff --git a/modular_skyrat/modules/self_actualization_device/code/self_actualization_device.dm b/modular_skyrat/modules/self_actualization_device/code/self_actualization_device.dm index d50759e484f..08dec35e0de 100644 --- a/modular_skyrat/modules/self_actualization_device/code/self_actualization_device.dm +++ b/modular_skyrat/modules/self_actualization_device/code/self_actualization_device.dm @@ -14,12 +14,7 @@ /obj/machinery/self_actualization_device name = "Self-Actualization Device" - desc = "With the power of modern neurological scanning and synthflesh cosmetic surgery, the Veymed Corporation \ - has teamed up with Nanotrasen Human Resources (and elsewise) to bring you the Self-Actualization Device! \ - Ever revived a patient and had them file a malpractice lawsuit because their head got attached to the wrong body? \ - Just slap 'em in the SAD and turn it on! Their frown will turn upside down as they're reconstituted as their ideal self \ - via the magic technology of brain scanning! Within a few short moments, they'll be popped out as their ideal self, \ - ready to continue on with their day lawsuit-free!" + desc = "A state of the art medical device that can restore someone's phyiscal appearence to the last known database backup." icon = 'modular_skyrat/modules/self_actualization_device/icons/self_actualization_device.dmi' icon_state = "sad_open" circuit = /obj/item/circuitboard/machine/self_actualization_device @@ -42,6 +37,20 @@ "Have more questions about the Self-Actualization Device? Call your nearest Veymed Representative to requisition more information about the Self-Actualization Device!" \ ) + +/obj/machinery/self_actualization_device/examine_more(mob/user) + . = ..() + + . += "With the power of modern neurological scanning and synthflesh cosmetic surgery, the Veymed Corporation \ + has teamed up with Nanotrasen Human Resources (and elsewise) to bring you the Self-Actualization Device! \ + Ever revived a patient and had them file a malpractice lawsuit because their head got attached to the wrong body? \ + Just slap 'em in the SAD and turn it on! Their frown will turn upside down as they're reconstituted as their ideal self \ + via the magic technology of brain scanning! Within a few short moments, they'll be popped out as their ideal self, \ + ready to continue on with their day lawsuit-free!" + + return . + + /obj/machinery/self_actualization_device/update_appearance(updates) . = ..() if(occupant) diff --git a/sound/machines/fan_break.ogg b/sound/machines/fan_break.ogg new file mode 100644 index 00000000000..ca0549333ad Binary files /dev/null and b/sound/machines/fan_break.ogg differ diff --git a/sound/machines/fan_loop.ogg b/sound/machines/fan_loop.ogg new file mode 100644 index 00000000000..9c7820548f6 Binary files /dev/null and b/sound/machines/fan_loop.ogg differ diff --git a/sound/machines/fan_start.ogg b/sound/machines/fan_start.ogg new file mode 100644 index 00000000000..a0d11c3e969 Binary files /dev/null and b/sound/machines/fan_start.ogg differ diff --git a/sound/machines/fan_stop.ogg b/sound/machines/fan_stop.ogg new file mode 100644 index 00000000000..84d39c3ee5a Binary files /dev/null and b/sound/machines/fan_stop.ogg differ diff --git a/tff_modular/modules/nabbers/code/abilites/camouflage.dm b/tff_modular/modules/nabbers/code/abilites/camouflage.dm index 1602779b275..ec0817e6670 100644 --- a/tff_modular/modules/nabbers/code/abilites/camouflage.dm +++ b/tff_modular/modules/nabbers/code/abilites/camouflage.dm @@ -27,7 +27,7 @@ owner.balloon_alert(owner, "Can't now!") return FALSE - RegisterSignals(owner, list(COMSIG_MOB_ITEM_ATTACK, COMSIG_ATOM_ATTACKBY, COMSIG_ATOM_ATTACK_HAND, COMSIG_ATOM_HITBY, COMSIG_ATOM_HULK_ATTACK, COMSIG_ATOM_ATTACK_PAW, COMSIG_CARBON_CUFF_ATTEMPTED, COMSIG_ATOM_BULLET_ACT, COMSIG_HUMAN_MELEE_UNARMED_ATTACK, COMSIG_LIVING_MOB_BUMP, COMSIG_HUMAN_BURNING), PROC_REF(remove_camouflage)) + RegisterSignals(owner, list(COMSIG_MOB_ITEM_ATTACK, COMSIG_ATOM_ATTACKBY, COMSIG_ATOM_ATTACK_HAND, COMSIG_ATOM_HITBY, COMSIG_ATOM_HULK_ATTACK, COMSIG_ATOM_ATTACK_PAW, COMSIG_CARBON_CUFF_ATTEMPTED, COMSIG_ATOM_BULLET_ACT, COMSIG_LIVING_EARLY_UNARMED_ATTACK, COMSIG_LIVING_MOB_BUMP, COMSIG_HUMAN_BURNING), PROC_REF(remove_camouflage)) enter_camouflage() return TRUE @@ -55,7 +55,7 @@ owner.visible_message(span_notice("[owner] stops blending in with surroundings."), span_notice("You become visible again."), span_hear("You hear a low hiss.")) animate(owner, alpha = 255, time = 1.5 SECONDS) - UnregisterSignal(owner, list(COMSIG_HUMAN_MELEE_UNARMED_ATTACK, COMSIG_MOB_ITEM_ATTACK, COMSIG_ATOM_ATTACKBY, COMSIG_ATOM_ATTACK_HAND, COMSIG_ATOM_BULLET_ACT, COMSIG_ATOM_HITBY, COMSIG_ATOM_HULK_ATTACK, COMSIG_ATOM_ATTACK_PAW, COMSIG_CARBON_CUFF_ATTEMPTED, COMSIG_LIVING_MOB_BUMP, COMSIG_HUMAN_BURNING)) + UnregisterSignal(owner, list(COMSIG_LIVING_EARLY_UNARMED_ATTACK, COMSIG_MOB_ITEM_ATTACK, COMSIG_ATOM_ATTACKBY, COMSIG_ATOM_ATTACK_HAND, COMSIG_ATOM_BULLET_ACT, COMSIG_ATOM_HITBY, COMSIG_ATOM_HULK_ATTACK, COMSIG_ATOM_ATTACK_PAW, COMSIG_CARBON_CUFF_ATTEMPTED, COMSIG_LIVING_MOB_BUMP, COMSIG_HUMAN_BURNING)) button_icon_state = ICON_STATE_CAMOUFLAGE_OFF owner.update_action_buttons() diff --git a/tff_modular/modules/redsec/code/vending.dm b/tff_modular/modules/redsec/code/vending.dm index 6d35ab6a981..6baefc28eaf 100644 --- a/tff_modular/modules/redsec/code/vending.dm +++ b/tff_modular/modules/redsec/code/vending.dm @@ -9,53 +9,49 @@ "name" = "RedSec", "icon" = "hat-cowboy", "products" = list( - /obj/item/clothing/suit/hooded/wintercoat/security/redsec = 5, - /obj/item/storage/belt/security/redsec = 5, - /obj/item/storage/backpack/security/redsec = 5, - /obj/item/storage/backpack/satchel/sec/redsec = 5, - /obj/item/storage/backpack/duffelbag/sec/redsec = 5, - /obj/item/clothing/under/rank/security/officer/redsec = 5, - /obj/item/clothing/shoes/jackboots/sec/redsec = 5, - /obj/item/clothing/head/beret/sec = 5, - /obj/item/clothing/head/soft/sec = 5, - /obj/item/clothing/mask/bandana/red = 5, - /obj/item/clothing/glasses/hud/security/redsec = 5, - /obj/item/clothing/gloves/color/black = 5, - /obj/item/clothing/under/rank/security/officer/skirt/redsec = 5, - /obj/item/clothing/under/rank/security/skyrat/utility/redsec = 5, - /obj/item/clothing/suit/toggle/jacket/sec/old = 5, - /obj/item/clothing/suit/armor/vest/alt/sec/redsec = 2 + /obj/item/clothing/suit/hooded/wintercoat/security/redsec = 5, + /obj/item/storage/belt/security/redsec = 5, + /obj/item/storage/backpack/security/redsec = 5, + /obj/item/storage/backpack/satchel/sec/redsec = 5, + /obj/item/storage/backpack/duffelbag/sec/redsec = 5, + /obj/item/clothing/under/rank/security/officer/redsec = 5, + /obj/item/clothing/shoes/jackboots/sec/redsec = 5, + /obj/item/clothing/head/beret/sec = 5, + /obj/item/clothing/head/soft/sec = 5, + /obj/item/clothing/mask/bandana/red = 5, + /obj/item/clothing/glasses/hud/security/redsec = 5, + /obj/item/clothing/gloves/color/black = 5, + /obj/item/clothing/under/rank/security/officer/skirt/redsec = 5, + /obj/item/clothing/under/rank/security/skyrat/utility/redsec = 5, + /obj/item/clothing/suit/toggle/jacket/sec/old = 5, + /obj/item/clothing/suit/armor/vest/alt/sec/redsec = 2 ), ), list( "name" = "BlueSec", "icon" = "user-tie", "products" = list( - /obj/item/clothing/suit/hooded/wintercoat/security = 5, - /obj/item/clothing/suit/toggle/jacket/sec = 5, - /obj/item/clothing/suit/armor/vest/peacekeeper/brit = 5, - /obj/item/clothing/suit/armor/vest/peacekeeper = 5, - /obj/item/storage/belt/security = 5, - /obj/item/clothing/neck/security_cape = 5, - /obj/item/clothing/neck/security_cape/armplate = 5, - /obj/item/storage/backpack/security = 5, - /obj/item/storage/backpack/satchel/sec = 5, - /obj/item/storage/backpack/duffelbag/sec = 5, - /obj/item/clothing/under/rank/security/officer = 5, - /obj/item/clothing/under/rank/security/officer/skirt = 5, - /obj/item/clothing/under/rank/security/peacekeeper/tactical = 5, - /obj/item/clothing/under/rank/security/peacekeeper/sol/cadet = 5, - /obj/item/clothing/under/rank/security/peacekeeper/sol = 5, - /obj/item/clothing/under/rank/security/skyrat/utility = 5, - /obj/item/clothing/shoes/jackboots/sec = 5, - /obj/item/clothing/head/security_garrison = 5, - /obj/item/clothing/head/security_cap = 5, - /obj/item/clothing/head/beret/sec/peacekeeper = 5, - /obj/item/clothing/glasses/hud/security = 5, - /obj/item/clothing/head/costume/ushanka/sec = 5, - /obj/item/clothing/head/hats/sec/peacekeeper/sol = 5, - /obj/item/clothing/head/hats/sec/peacekeeper/sol/traffic = 5, - /obj/item/clothing/gloves/color/black/security = 5 + /obj/item/clothing/suit/hooded/wintercoat/security = 5, + /obj/item/clothing/suit/toggle/jacket/sec = 5, + /obj/item/clothing/suit/armor/vest/peacekeeper/brit = 5, + /obj/item/clothing/neck/security_cape = 5, + /obj/item/clothing/neck/security_cape/armplate = 5, + /obj/item/storage/backpack/security = 5, + /obj/item/storage/backpack/satchel/sec = 5, + /obj/item/storage/backpack/duffelbag/sec = 5, + /obj/item/storage/backpack/duffelbag/sec = 5, + /obj/item/clothing/under/rank/security/officer = 10, + /obj/item/clothing/under/rank/security/officer/skirt = 10, + /obj/item/clothing/under/rank/security/peacekeeper = 10, + /obj/item/clothing/under/rank/security/skyrat/utility = 3, + /obj/item/clothing/shoes/jackboots/sec = 10, + /obj/item/clothing/head/security_garrison = 10, + /obj/item/clothing/head/security_cap = 10, + /obj/item/clothing/head/beret/sec/peacekeeper = 5, + /obj/item/clothing/head/helmet/sec/sol = 5, + /obj/item/clothing/head/hats/warden/police/patrol = 5, + /obj/item/clothing/head/costume/ushanka/sec = 10, + /obj/item/clothing/gloves/color/black/security = 10, ), ), ) diff --git a/tgstation.dme b/tgstation.dme index 22b7e8f1e17..623f9cba181 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -138,6 +138,7 @@ #include "code\__DEFINES\MC.dm" #include "code\__DEFINES\mecha.dm" #include "code\__DEFINES\medical.dm" +#include "code\__DEFINES\megafauna.dm" #include "code\__DEFINES\melee.dm" #include "code\__DEFINES\memory_defines.dm" #include "code\__DEFINES\mergers.dm" @@ -1150,7 +1151,6 @@ #include "code\datums\components\phylactery.dm" #include "code\datums\components\pinata.dm" #include "code\datums\components\pricetag.dm" -#include "code\datums\components\pry_open_door.dm" #include "code\datums\components\punchcooldown.dm" #include "code\datums\components\puzzgrid.dm" #include "code\datums\components\radiation_countdown.dm" @@ -1221,6 +1221,7 @@ #include "code\datums\components\tippable.dm" #include "code\datums\components\toggle_attached_clothing.dm" #include "code\datums\components\toggle_suit.dm" +#include "code\datums\components\torn_wall.dm" #include "code\datums\components\transforming.dm" #include "code\datums\components\trapdoor.dm" #include "code\datums\components\tree_climber.dm" @@ -1397,6 +1398,7 @@ #include "code\datums\elements\dextrous.dm" #include "code\datums\elements\diggable.dm" #include "code\datums\elements\digitalcamo.dm" +#include "code\datums\elements\door_pryer.dm" #include "code\datums\elements\drag_pickup.dm" #include "code\datums\elements\dryable.dm" #include "code\datums\elements\earhealing.dm" @@ -1418,6 +1420,7 @@ #include "code\datums\elements\haunted.dm" #include "code\datums\elements\high_fiver.dm" #include "code\datums\elements\honkspam.dm" +#include "code\datums\elements\human_biter.dm" #include "code\datums\elements\immerse.dm" #include "code\datums\elements\item_fov.dm" #include "code\datums\elements\item_scaling.dm" @@ -1484,6 +1487,7 @@ #include "code\datums\elements\waddling.dm" #include "code\datums\elements\wall_engraver.dm" #include "code\datums\elements\wall_smasher.dm" +#include "code\datums\elements\wall_tearer.dm" #include "code\datums\elements\wall_walker.dm" #include "code\datums\elements\weapon_description.dm" #include "code\datums\elements\weather_listener.dm" @@ -1553,6 +1557,7 @@ #include "code\datums\looping_sounds\item_sounds.dm" #include "code\datums\looping_sounds\machinery_sounds.dm" #include "code\datums\looping_sounds\music.dm" +#include "code\datums\looping_sounds\vents.dm" #include "code\datums\looping_sounds\weather.dm" #include "code\datums\mapgen\_MapGenerator.dm" #include "code\datums\mapgen\CaveGenerator.dm" @@ -3990,6 +3995,7 @@ #include "code\modules\hallucination\hud_screw.dm" #include "code\modules\hallucination\ice_cube.dm" #include "code\modules\hallucination\inhand_fake_item.dm" +#include "code\modules\hallucination\mother.dm" #include "code\modules\hallucination\nearby_fake_item.dm" #include "code\modules\hallucination\on_fire.dm" #include "code\modules\hallucination\screwy_health_doll.dm" @@ -4624,6 +4630,9 @@ #include "code\modules\mob\living\basic\space_fauna\revenant\revenant_objectives.dm" #include "code\modules\mob\living\basic\space_fauna\snake\snake.dm" #include "code\modules\mob\living\basic\space_fauna\snake\snake_ai.dm" +#include "code\modules\mob\living\basic\space_fauna\space_dragon\dragon_breath.dm" +#include "code\modules\mob\living\basic\space_fauna\space_dragon\dragon_gust.dm" +#include "code\modules\mob\living\basic\space_fauna\space_dragon\space_dragon.dm" #include "code\modules\mob\living\basic\space_fauna\spider\spider.dm" #include "code\modules\mob\living\basic\space_fauna\spider\giant_spider\giant_spider_ai.dm" #include "code\modules\mob\living\basic\space_fauna\spider\giant_spider\giant_spider_subtrees.dm" @@ -4850,7 +4859,6 @@ #include "code\modules\mob\living\simple_animal\hostile\ooze.dm" #include "code\modules\mob\living\simple_animal\hostile\pirate.dm" #include "code\modules\mob\living\simple_animal\hostile\skeleton.dm" -#include "code\modules\mob\living\simple_animal\hostile\space_dragon.dm" #include "code\modules\mob\living\simple_animal\hostile\vatbeast.dm" #include "code\modules\mob\living\simple_animal\hostile\wizard.dm" #include "code\modules\mob\living\simple_animal\hostile\zombie.dm" @@ -6227,6 +6235,7 @@ #include "modular_skyrat\master_files\code\modules\power\powernet.dm" #include "modular_skyrat\master_files\code\modules\power\lighting\light_mapping_helpers.dm" #include "modular_skyrat\master_files\code\modules\power\singularity\containment_field.dm" +#include "modular_skyrat\master_files\code\modules\projectiles\ammunition\energy\stun.dm" #include "modular_skyrat\master_files\code\modules\projectiles\boxes_magazines\external\shotgun.dm" #include "modular_skyrat\master_files\code\modules\projectiles\boxes_magazines\external\smg.dm" #include "modular_skyrat\master_files\code\modules\projectiles\guns\ballistic.dm" @@ -6329,7 +6338,6 @@ #include "modular_skyrat\modules\alerts\code\alert_sound_to_playing.dm" #include "modular_skyrat\modules\alerts\code\config.dm" #include "modular_skyrat\modules\alerts\code\default_announcer.dm" -#include "modular_skyrat\modules\alerts\code\priority_announce.dm" #include "modular_skyrat\modules\alerts\code\security_level_datums.dm" #include "modular_skyrat\modules\alerts\code\security_level_procs.dm" #include "modular_skyrat\modules\alt_vox\code\voc_sounds_mil.dm" @@ -6352,12 +6360,14 @@ #include "modular_skyrat\modules\armaments\code\armament_component.dm" #include "modular_skyrat\modules\armaments\code\armament_entries.dm" #include "modular_skyrat\modules\armaments\code\armament_station.dm" +#include "modular_skyrat\modules\ashwalkers\code\buildings\antfarm.dm" #include "modular_skyrat\modules\ashwalkers\code\buildings\ash_clothing_vendor.dm" #include "modular_skyrat\modules\ashwalkers\code\buildings\ash_farming.dm" #include "modular_skyrat\modules\ashwalkers\code\buildings\ash_tendril.dm" #include "modular_skyrat\modules\ashwalkers\code\buildings\fuelwell.dm" #include "modular_skyrat\modules\ashwalkers\code\buildings\railroad.dm" #include "modular_skyrat\modules\ashwalkers\code\buildings\tendril_cursing.dm" +#include "modular_skyrat\modules\ashwalkers\code\buildings\wormfarm.dm" #include "modular_skyrat\modules\ashwalkers\code\clothing\ash_armour.dm" #include "modular_skyrat\modules\ashwalkers\code\clothing\hands.dm" #include "modular_skyrat\modules\ashwalkers\code\clothing\head.dm" diff --git a/tgui/packages/tgui-panel/styles/tgchat/chat-dark.scss b/tgui/packages/tgui-panel/styles/tgchat/chat-dark.scss index 43e2fa93343..b3fa0eb66fa 100644 --- a/tgui/packages/tgui-panel/styles/tgchat/chat-dark.scss +++ b/tgui/packages/tgui-panel/styles/tgchat/chat-dark.scss @@ -437,8 +437,36 @@ em { } .minorannounce { + color: #c51e1e; font-weight: bold; font-size: 185%; + margin-top: 1rem; +} + +.minoralert { + color: #a4bad6; + font-size: 125%; + margin-top: 1rem; +} + +.priorityannounce { + color: #a4bad6; + font-weight: bold; + font-size: 225%; + margin-top: 1rem; +} + +.prioritytitle { + color: #9ab0ff; + font-weight: bold; + font-size: 185%; + margin-top: 1rem; +} + +.priorityalert { + color: #c51e1e; + font-size: 140%; + margin-top: 1rem; } .greenannounce { diff --git a/tgui/packages/tgui-panel/styles/tgchat/chat-light.scss b/tgui/packages/tgui-panel/styles/tgchat/chat-light.scss index e685cded774..efa16db9fc4 100644 --- a/tgui/packages/tgui-panel/styles/tgchat/chat-light.scss +++ b/tgui/packages/tgui-panel/styles/tgchat/chat-light.scss @@ -469,10 +469,27 @@ h2.alert { } .minorannounce { + color: #ff0000; font-weight: bold; font-size: 185%; } +.minoralert { + color: #000000; + font-size: 125%; +} + +.priorityannounce { + color: #000000; + font-weight: bold; + font-size: 210%; +} + +.priorityalert { + color: #ff0000; + font-size: 140%; +} + .greenannounce { color: #00ff00; font-weight: bold; diff --git a/tgui/packages/tgui-say/TguiSay.tsx b/tgui/packages/tgui-say/TguiSay.tsx index b2de8cea1a9..267febef650 100644 --- a/tgui/packages/tgui-say/TguiSay.tsx +++ b/tgui/packages/tgui-say/TguiSay.tsx @@ -4,7 +4,7 @@ import { Component, createRef, InfernoKeyboardEvent, RefObject } from 'inferno'; import { LINE_LENGTHS, RADIO_PREFIXES, WINDOW_SIZES } from './constants'; import { byondMessages } from './timers'; import { dragStartHandler } from 'tgui/drag'; -import { windowOpen, windowLoad, windowClose, windowSet } from './helpers'; +import { windowOpen, windowClose, windowSet } from './helpers'; import { BooleanLike } from 'common/react'; import { KEY } from 'common/keys'; @@ -68,7 +68,6 @@ export class TguiSay extends Component<{}, State> { Byond.subscribeTo('props', this.handleProps); Byond.subscribeTo('force', this.handleForceSay); Byond.subscribeTo('open', this.handleOpen); - windowLoad(); } handleArrowKeys(direction: KEY.Up | KEY.Down) { diff --git a/tgui/packages/tgui-say/helpers.ts b/tgui/packages/tgui-say/helpers.ts index 195d71a740a..100e3c03668 100644 --- a/tgui/packages/tgui-say/helpers.ts +++ b/tgui/packages/tgui-say/helpers.ts @@ -22,19 +22,6 @@ export const windowClose = () => { Byond.sendMessage('close'); }; -/** Some QoL to hide the window on load. Doesn't log this event */ -export const windowLoad = () => { - Byond.winset('tgui_say', { - pos: '848,500', - size: `${WINDOW_SIZES.width}x${WINDOW_SIZES.small}`, - visible: false, - }); - - Byond.winset('map', { - focus: true, - }); -}; - /** * Modifies the window size. */ diff --git a/tgui/packages/tgui/interfaces/MessageMonitor.tsx b/tgui/packages/tgui/interfaces/MessageMonitor.tsx index ea5216365a2..86f87b55339 100644 --- a/tgui/packages/tgui/interfaces/MessageMonitor.tsx +++ b/tgui/packages/tgui/interfaces/MessageMonitor.tsx @@ -28,7 +28,7 @@ type Request = { ref: string; message: string; stamp: string; - send_dpt: string; + sender_department: string; id_auth: string; }; @@ -75,7 +75,7 @@ const RequestLogsScreen = (props, context) => { {request.message} {request.stamp} - {request.send_dpt} + {request.sender_department} {request.id_auth} ))} diff --git a/tgui/packages/tgui/interfaces/common/AtmosControls.tsx b/tgui/packages/tgui/interfaces/common/AtmosControls.tsx index 099de593558..e67f7ba385e 100644 --- a/tgui/packages/tgui/interfaces/common/AtmosControls.tsx +++ b/tgui/packages/tgui/interfaces/common/AtmosControls.tsx @@ -8,6 +8,8 @@ export type VentProps = { refID: string; long_name: string; power: BooleanLike; + overclock: BooleanLike; + integrity: number; checks: number; excheck: BooleanLike; incheck: BooleanLike; @@ -37,6 +39,8 @@ export const Vent = (props: VentProps, context) => { refID, long_name, power, + overclock, + integrity, checks, excheck, incheck, @@ -50,19 +54,41 @@ export const Vent = (props: VentProps, context) => {
- act('power', { - ref: refID, - val: Number(!power), - }) - } - /> + <> +