diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index 4eff81fe93d79b8..e08634924e56c68 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -68,8 +68,6 @@ These are the few directives we have for project maintainers. These are not steadfast rules as maintainers are expected to use their best judgement when operating. -Our team is entirely voluntary, as such we extend our thanks to maintainers, issue managers, and contributors alike for helping keep the project alive. - ### Issue Managers @@ -94,6 +92,10 @@ For more information reference the [Issue Manager Guide](.github/guides/ISSUE_MA +--- + +Our team is entirely voluntary, as such we extend our thanks to maintainers, issue managers, and contributors alike for helping keep the project alive. + ## Development Guides #### Writing readable code diff --git a/.github/alternate_byond_versions.txt b/.github/alternate_byond_versions.txt index 111e573827e8e3b..e1496d438cdc4aa 100644 --- a/.github/alternate_byond_versions.txt +++ b/.github/alternate_byond_versions.txt @@ -5,4 +5,4 @@ # Format is version: map # Example: # 500.1337: runtimestation -515.1621: runtimestation +515.1627: runtimestation diff --git a/.vscode/launch.json b/.vscode/launch.json index 42a293a3338057e..bf3a209531db006 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -8,6 +8,13 @@ "preLaunchTask": "Build All", "dmb": "${workspaceFolder}/${command:CurrentDMB}" }, + { + "type": "byond", + "request": "launch", + "name": "Launch DreamSeeker (low memory mode)", + "preLaunchTask": "Build All (low memory mode)", + "dmb": "${workspaceFolder}/${command:CurrentDMB}" + }, { "type": "byond", "request": "launch", @@ -16,6 +23,14 @@ "dmb": "${workspaceFolder}/${command:CurrentDMB}", "dreamDaemon": true }, + { + "type": "byond", + "request": "launch", + "name": "Launch DreamDaemon (low memory mode)", + "preLaunchTask": "Build All (low memory mode)", + "dmb": "${workspaceFolder}/${command:CurrentDMB}", + "dreamDaemon": true + }, { "name": "Debug External Libraries", "type": "cppvsdbg", @@ -27,6 +42,18 @@ "-trusted" ], "preLaunchTask": "Build All" + }, + { + "name": "Debug External Libraries (low memory mode)", + "type": "cppvsdbg", + "request": "launch", + "program": "${command:dreammaker.returnDreamDaemonPath}", + "cwd": "${workspaceRoot}", + "args": [ + "${command:dreammaker.getFilenameDmb}", + "-trusted" + ], + "preLaunchTask": "Build All (low memory mode)" } ] } diff --git a/.vscode/settings.json b/.vscode/settings.json index 35e9fafdb333c3d..d7c1bfc1d1e3112 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -13,6 +13,7 @@ }, "files.eol": "\n", "files.insertFinalNewline": true, + "git.branchProtection": ["master"], "gitlens.advanced.blame.customArguments": ["-w"], "tgstationTestExplorer.project.resultsType": "json", "[javascript]": { diff --git a/.vscode/tasks.json b/.vscode/tasks.json index 711a13c7846c127..18fb2fde1529624 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -24,6 +24,30 @@ "dependsOn": "dm: reparse", "label": "Build All" }, + { + "type": "process", + "command": "tools/build/build", + "args": ["-DLOWMEMORYMODE"], + "windows": { + "command": ".\\tools\\build\\build.bat", + "args": ["-DLOWMEMORYMODE"] + }, + "options": { + "env": { + "DM_EXE": "${config:dreammaker.byondPath}" + } + }, + "problemMatcher": [ + "$dreammaker", + "$tsc", + "$eslint-stylish" + ], + "group": { + "kind": "build" + }, + "dependsOn": "dm: reparse", + "label": "Build All (low memory mode)" + }, { "type": "dreammaker", "dme": "tgstation.dme", diff --git a/_maps/RandomRuins/IceRuins/icemoon_surface_smoking_room.dmm b/_maps/RandomRuins/IceRuins/icemoon_surface_smoking_room.dmm index 7d422677278e6fb..faa5cf18ae978ae 100644 --- a/_maps/RandomRuins/IceRuins/icemoon_surface_smoking_room.dmm +++ b/_maps/RandomRuins/IceRuins/icemoon_surface_smoking_room.dmm @@ -54,6 +54,10 @@ /obj/structure/chair/comfy{ dir = 1 }, +/obj/effect/decal/remains/human/smokey{ + pixel_x = -3; + pixel_y = 9 + }, /turf/open/floor/carpet/blue, /area/ruin/smoking_room/room) "k" = ( @@ -245,11 +249,6 @@ /turf/open/misc/asteroid/snow/icemoon, /area/icemoon/surface/outdoors/nospawn) "R" = ( -/obj/effect/spawner/random/entertainment/cigarette_pack, -/obj/effect/decal/cleanable/ash/large{ - pixel_x = -1; - pixel_y = 5 - }, /obj/structure/showcase/machinery/tv/broken, /turf/open/floor/carpet/blue, /area/ruin/smoking_room/room) @@ -279,17 +278,12 @@ /turf/open/floor/stone, /area/ruin/smoking_room/house) "W" = ( -/obj/effect/spawner/random/entertainment/cigarette_pack, /obj/structure/chair/plastic{ dir = 8 }, /obj/effect/spawner/random/entertainment/cigarette_pack, /obj/effect/decal/cleanable/ash/large, /obj/structure/sign/calendar/directional/east, -/obj/effect/decal/remains/human/smokey{ - pixel_x = -3; - pixel_y = 9 - }, /turf/open/floor/carpet/blue, /area/ruin/smoking_room/room) "X" = ( diff --git a/_maps/RandomRuins/IceRuins/skyrat/icemoon_underground_syndicate_base1_skyrat.dmm b/_maps/RandomRuins/IceRuins/skyrat/icemoon_underground_syndicate_base1_skyrat.dmm index cbd04cdced2034c..53732130d59eddc 100644 --- a/_maps/RandomRuins/IceRuins/skyrat/icemoon_underground_syndicate_base1_skyrat.dmm +++ b/_maps/RandomRuins/IceRuins/skyrat/icemoon_underground_syndicate_base1_skyrat.dmm @@ -250,11 +250,7 @@ /turf/open/floor/iron/dark/textured_large, /area/ruin/syndicate_lava_base/bar) "bv" = ( -/obj/structure/frame/machine{ - anchored = 1; - state = 2; - icon_state = "box_1" - }, +/obj/structure/frame/machine/secured, /obj/item/circuitboard/machine/ore_redemption, /obj/item/assembly/igniter, /obj/structure/marker_beacon/burgundy, @@ -406,11 +402,7 @@ /turf/open/floor/iron/dark/textured_large, /area/ruin/syndicate_lava_base/main) "cm" = ( -/obj/structure/frame/machine{ - anchored = 1; - state = 2; - icon_state = "box_1" - }, +/obj/structure/frame/machine/secured, /obj/item/circuitboard/machine/ore_silo, /obj/structure/marker_beacon/burgundy, /obj/structure/sign/flag/syndicate/directional/north, diff --git a/_maps/RandomRuins/LavaRuins/lavaland_surface_gas.dmm b/_maps/RandomRuins/LavaRuins/lavaland_surface_gas.dmm new file mode 100644 index 000000000000000..ef32d3e8ed9c6bc --- /dev/null +++ b/_maps/RandomRuins/LavaRuins/lavaland_surface_gas.dmm @@ -0,0 +1,1244 @@ +//MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE +"aK" = ( +/obj/structure/rack, +/obj/effect/spawner/random/entertainment/cigarette_pack, +/obj/effect/spawner/random/entertainment/cigarette_pack, +/obj/effect/spawner/random/entertainment/cigarette_pack, +/obj/effect/spawner/random/entertainment/lighter, +/obj/effect/spawner/random/entertainment/lighter, +/obj/effect/spawner/random/entertainment/lighter, +/obj/machinery/light/directional/south, +/obj/machinery/airalarm/directional/west, +/turf/open/floor/iron, +/area/ruin/lizard_gaslava) +"bT" = ( +/obj/structure/table/reinforced, +/obj/machinery/atmospherics/pipe/smart/manifold4w/general/hidden, +/turf/open/floor/iron, +/area/ruin/lizard_gaslava) +"ck" = ( +/obj/machinery/duct, +/obj/machinery/atmospherics/pipe/smart/manifold4w/general/hidden, +/turf/open/floor/iron/smooth, +/area/ruin/lizard_gaslava) +"dm" = ( +/obj/machinery/door/airlock/engineering, +/obj/machinery/duct, +/obj/machinery/atmospherics/pipe/smart/manifold4w/general/hidden, +/turf/open/floor/iron/smooth, +/area/ruin/lizard_gaslava) +"fy" = ( +/obj/machinery/light/directional/south, +/obj/structure/table/reinforced, +/obj/item/stack/sheet/mineral/plasma/thirty, +/obj/item/stack/sheet/mineral/plasma/five, +/obj/item/stack/sheet/mineral/plasma/five, +/obj/item/stack/sheet/mineral/plasma/five, +/obj/item/stack/sheet/mineral/plasma/five, +/obj/machinery/light/directional/north, +/turf/open/misc/ashplanet/rocky, +/area/ruin/lizard_gaslava) +"fF" = ( +/obj/effect/turf_decal/arrows{ + dir = 8 + }, +/turf/open/misc/ashplanet/rocky, +/area/ruin/lizard_gaslava) +"fH" = ( +/turf/open/misc/ashplanet/rocky, +/area/ruin/lizard_gaslava) +"fX" = ( +/obj/structure/sink/directional/east{ + has_water_reclaimer = 0 + }, +/turf/open/misc/ashplanet/rocky, +/area/ruin/lizard_gaslava) +"go" = ( +/obj/machinery/power/terminal{ + dir = 1 + }, +/obj/structure/cable, +/turf/open/floor/iron/smooth, +/area/ruin/lizard_gaslava) +"ia" = ( +/obj/effect/spawner/random/structure/billboard/lizardsgas, +/obj/effect/turf_decal/arrows{ + dir = 4 + }, +/turf/open/misc/ashplanet/rocky, +/area/ruin/lizard_gaslava) +"iK" = ( +/obj/structure/cable, +/obj/machinery/power/rtg/advanced, +/obj/effect/turf_decal/bot, +/turf/open/floor/iron/smooth, +/area/ruin/lizard_gaslava) +"jY" = ( +/obj/structure/window/reinforced/spawner/directional/west, +/obj/structure/window/reinforced/spawner/directional/north, +/obj/structure/rack, +/obj/item/reagent_containers/condiment/yoghurt{ + pixel_x = -3; + pixel_y = 1 + }, +/obj/item/reagent_containers/condiment/yoghurt{ + pixel_x = 6; + pixel_y = -1 + }, +/turf/open/floor/iron/freezer, +/area/ruin/lizard_gaslava) +"ks" = ( +/obj/structure/sign/warning/fire/directional/north, +/obj/machinery/duct, +/obj/machinery/atmospherics/pipe/smart/manifold4w/general/hidden, +/obj/machinery/light/small/dim/directional/north, +/turf/open/floor/iron/smooth, +/area/ruin/lizard_gaslava) +"mn" = ( +/obj/structure/reagent_dispensers/plumbed/fuel, +/turf/open/floor/iron/smooth, +/area/ruin/lizard_gaslava) +"mz" = ( +/obj/structure/rack, +/obj/item/food/candy, +/obj/item/food/candy, +/obj/item/food/candy, +/obj/item/food/chocolatebar, +/obj/item/food/chocolatebar{ + pixel_y = 3 + }, +/obj/item/food/chocolatebar{ + pixel_y = 6 + }, +/obj/structure/sign/poster/contraband/hacking_guide/directional/north, +/turf/open/floor/iron, +/area/ruin/lizard_gaslava) +"mG" = ( +/obj/effect/turf_decal/arrows{ + dir = 4 + }, +/turf/open/misc/ashplanet/rocky, +/area/ruin/lizard_gaslava) +"mY" = ( +/obj/effect/spawner/random/structure/billboard/lizardsgas, +/obj/effect/turf_decal/arrows{ + dir = 8 + }, +/turf/open/misc/ashplanet/rocky, +/area/ruin/lizard_gaslava) +"nc" = ( +/obj/effect/decal/cleanable/dirt/dust, +/obj/machinery/duct, +/obj/machinery/atmospherics/pipe/smart/manifold4w/general/hidden, +/turf/open/floor/iron/smooth, +/area/ruin/lizard_gaslava) +"ng" = ( +/obj/machinery/door/airlock/external/ruin, +/turf/open/floor/plating, +/area/ruin/lizard_gaslava) +"om" = ( +/obj/effect/turf_decal/arrows{ + dir = 1 + }, +/turf/open/misc/ashplanet/rocky, +/area/ruin/lizard_gaslava) +"pp" = ( +/obj/structure/sign/poster/contraband/jumbo_bar/directional/east, +/turf/open/floor/iron, +/area/ruin/lizard_gaslava) +"pJ" = ( +/turf/open/floor/iron/smooth, +/area/ruin/lizard_gaslava) +"rM" = ( +/obj/structure/window/reinforced/spawner/directional/north, +/obj/structure/window/reinforced/spawner/directional/east, +/obj/structure/rack, +/obj/item/food/cheese/mozzarella{ + pixel_y = 5; + pixel_x = -5 + }, +/obj/item/food/cheese/mozzarella{ + pixel_y = -4; + pixel_x = 1 + }, +/obj/item/food/cheese/wheel, +/obj/item/food/cheese/cheese_curds, +/obj/item/food/cheese/curd_cheese, +/turf/open/floor/iron/freezer, +/area/ruin/lizard_gaslava) +"sY" = ( +/obj/machinery/door/airlock/external/ruin, +/obj/machinery/duct, +/obj/machinery/atmospherics/pipe/smart/manifold4w/general/hidden, +/turf/open/floor/plating, +/area/ruin/lizard_gaslava) +"tD" = ( +/obj/structure/rack, +/obj/item/food/chips{ + pixel_x = 7 + }, +/obj/item/food/chips{ + pixel_y = 7; + pixel_x = -4 + }, +/obj/item/food/chips/shrimp{ + pixel_y = 10; + pixel_x = 7 + }, +/obj/item/food/chips/shrimp{ + pixel_y = -4; + pixel_x = -5 + }, +/turf/open/floor/iron, +/area/ruin/lizard_gaslava) +"ub" = ( +/obj/structure/railing{ + dir = 9 + }, +/turf/open/misc/ashplanet/rocky, +/area/ruin/lizard_gaslava) +"uV" = ( +/obj/machinery/atmospherics/components/unary/vent_pump/on{ + dir = 8 + }, +/turf/open/floor/iron, +/area/ruin/lizard_gaslava) +"vt" = ( +/obj/machinery/duct, +/obj/machinery/atmospherics/components/tank/oxygen{ + dir = 4 + }, +/turf/open/floor/iron/smooth, +/area/ruin/lizard_gaslava) +"vH" = ( +/obj/machinery/atmospherics/components/unary/vent_pump/on{ + dir = 1 + }, +/obj/machinery/light/small/dim/directional/south, +/turf/open/floor/iron/smooth, +/area/ruin/lizard_gaslava) +"wl" = ( +/obj/structure/sink/directional/west{ + has_water_reclaimer = 0 + }, +/turf/open/misc/ashplanet/rocky, +/area/ruin/lizard_gaslava) +"xH" = ( +/obj/machinery/light/directional/south, +/turf/open/misc/ashplanet/rocky, +/area/ruin/lizard_gaslava) +"xW" = ( +/turf/open/floor/iron, +/area/ruin/lizard_gaslava) +"yH" = ( +/obj/structure/rack, +/obj/item/food/sticko/nutty{ + pixel_y = 5; + pixel_x = -5 + }, +/obj/item/food/sticko{ + pixel_y = 2; + pixel_x = 6 + }, +/turf/open/floor/iron, +/area/ruin/lizard_gaslava) +"Ag" = ( +/obj/structure/table, +/obj/item/coffee_cartridge, +/obj/item/coffee_cartridge, +/obj/effect/mapping_helpers/apc/cell_10k, +/obj/effect/mapping_helpers/apc/unlocked, +/obj/machinery/power/apc/auto_name/directional/north, +/obj/structure/cable, +/turf/open/floor/iron/smooth, +/area/ruin/lizard_gaslava) +"Ao" = ( +/obj/structure/sign/poster/contraband/tipper_cream_soda/directional/south, +/turf/open/floor/iron, +/area/ruin/lizard_gaslava) +"Bf" = ( +/mob/living/basic/lizard, +/obj/machinery/atmospherics/components/unary/vent_pump/on{ + dir = 4 + }, +/turf/open/floor/iron, +/area/ruin/lizard_gaslava) +"BH" = ( +/obj/structure/table/reinforced, +/obj/item/food/hotdog{ + pixel_y = 4; + pixel_x = -2 + }, +/obj/item/food/hotdog{ + pixel_y = -3; + pixel_x = 1 + }, +/obj/machinery/atmospherics/pipe/smart/manifold4w/general/hidden, +/turf/open/floor/iron, +/area/ruin/lizard_gaslava) +"BX" = ( +/obj/effect/decal/cleanable/dirt/dust, +/obj/machinery/light/directional/south, +/turf/open/floor/iron, +/area/ruin/lizard_gaslava) +"DI" = ( +/turf/template_noop, +/area/template_noop) +"Ef" = ( +/obj/effect/decal/cleanable/dirt/dust, +/obj/machinery/atmospherics/components/unary/vent_pump/on{ + dir = 8 + }, +/turf/open/floor/iron, +/area/ruin/lizard_gaslava) +"Eh" = ( +/obj/structure/table/reinforced, +/obj/item/food/honeybar{ + pixel_y = 5; + pixel_x = -1 + }, +/obj/item/food/honeybar{ + pixel_x = 2; + pixel_y = 2 + }, +/obj/item/food/honeybar{ + pixel_y = 8; + pixel_x = -1 + }, +/obj/item/food/honeybar{ + pixel_x = 2; + pixel_y = 5 + }, +/obj/item/food/granola_bar{ + pixel_y = 9; + pixel_x = -1 + }, +/obj/item/food/granola_bar{ + pixel_y = 6; + pixel_x = 2 + }, +/obj/effect/decal/cleanable/dirt/dust, +/turf/open/floor/iron, +/area/ruin/lizard_gaslava) +"El" = ( +/obj/structure/window/reinforced/spawner/directional/west, +/obj/structure/rack, +/obj/item/food/popsicle/creamsicle_berry{ + pixel_y = 4; + pixel_x = -1 + }, +/obj/item/food/popsicle/creamsicle_berry{ + pixel_y = 1; + pixel_x = 5 + }, +/obj/item/food/popsicle/creamsicle_orange, +/obj/item/food/popsicle/creamsicle_orange{ + pixel_y = 6; + pixel_x = 3 + }, +/turf/open/floor/iron/freezer, +/area/ruin/lizard_gaslava) +"Es" = ( +/obj/structure/sign/warning/fire/directional/south, +/obj/effect/decal/cleanable/dirt/dust, +/obj/machinery/atmospherics/components/unary/vent_pump/on{ + dir = 1 + }, +/turf/open/floor/iron/smooth, +/area/ruin/lizard_gaslava) +"EA" = ( +/obj/structure/window/reinforced/spawner/directional/east, +/obj/structure/rack, +/obj/item/storage/fancy/egg_box, +/obj/item/storage/fancy/egg_box{ + pixel_y = 9 + }, +/obj/item/storage/fancy/pickles_jar, +/turf/open/floor/iron/freezer, +/area/ruin/lizard_gaslava) +"FA" = ( +/obj/structure/railing{ + dir = 8 + }, +/turf/open/misc/ashplanet/rocky, +/area/ruin/lizard_gaslava) +"FC" = ( +/obj/structure/sign/poster/fluff/lizards_gas_power/directional/west, +/turf/open/floor/iron/smooth, +/area/ruin/lizard_gaslava) +"FL" = ( +/obj/effect/decal/cleanable/dirt/dust, +/obj/machinery/light/directional/north, +/turf/open/floor/iron, +/area/ruin/lizard_gaslava) +"Gv" = ( +/obj/structure/table/reinforced, +/obj/structure/window/reinforced/spawner/directional/north, +/obj/structure/window/reinforced/spawner/directional/east, +/obj/item/food/sandwich/blt{ + pixel_y = 6; + pixel_x = -2 + }, +/obj/item/food/little_shiro_sandwich{ + pixel_y = 1 + }, +/turf/open/floor/iron, +/area/ruin/lizard_gaslava) +"GK" = ( +/obj/structure/railing{ + dir = 10 + }, +/turf/open/misc/ashplanet/rocky, +/area/ruin/lizard_gaslava) +"HI" = ( +/obj/structure/table/reinforced, +/obj/structure/closet/mini_fridge{ + pixel_y = 5 + }, +/obj/effect/spawner/random/food_or_drink/refreshing_beverage, +/obj/effect/spawner/random/food_or_drink/refreshing_beverage, +/obj/effect/spawner/random/food_or_drink/refreshing_beverage, +/obj/effect/spawner/random/food_or_drink/booze, +/obj/effect/spawner/random/food_or_drink/booze, +/obj/effect/spawner/random/food_or_drink/booze, +/obj/structure/window/reinforced/spawner/directional/north, +/turf/open/floor/iron, +/area/ruin/lizard_gaslava) +"HL" = ( +/obj/effect/decal/cleanable/dirt/dust, +/obj/machinery/duct, +/obj/machinery/atmospherics/pipe/smart/manifold4w/general/hidden, +/turf/open/floor/iron, +/area/ruin/lizard_gaslava) +"HS" = ( +/obj/structure/window/reinforced/spawner/directional/west, +/obj/structure/window/reinforced/spawner/directional/south, +/obj/structure/rack, +/obj/item/food/cornuto{ + pixel_y = 4; + pixel_x = -3 + }, +/obj/item/food/cornuto{ + pixel_y = -5; + pixel_x = 2 + }, +/obj/item/food/cornuto{ + pixel_y = 5; + pixel_x = 6 + }, +/obj/item/food/cornuto{ + pixel_y = -5; + pixel_x = -3 + }, +/turf/open/floor/iron/freezer, +/area/ruin/lizard_gaslava) +"HW" = ( +/obj/machinery/door/airlock/external/ruin, +/obj/machinery/duct, +/turf/open/floor/plating, +/area/ruin/lizard_gaslava) +"IU" = ( +/obj/effect/decal/cleanable/dirt/dust, +/obj/machinery/light/directional/south, +/obj/machinery/atmospherics/pipe/smart/manifold4w/general/hidden, +/turf/open/floor/iron, +/area/ruin/lizard_gaslava) +"JX" = ( +/obj/structure/railing, +/turf/open/misc/ashplanet/rocky, +/area/ruin/lizard_gaslava) +"Kl" = ( +/obj/structure/rack, +/obj/item/food/cornchips/random, +/obj/item/food/cornchips/random, +/obj/item/food/cornchips/random, +/obj/item/food/cornchips/random, +/obj/item/food/cornchips/random, +/obj/item/food/cornchips/random, +/obj/machinery/light/directional/north, +/turf/open/floor/iron, +/area/ruin/lizard_gaslava) +"Km" = ( +/obj/structure/table/reinforced, +/turf/open/floor/iron, +/area/ruin/lizard_gaslava) +"KJ" = ( +/obj/structure/railing{ + dir = 1 + }, +/turf/open/misc/ashplanet/rocky, +/area/ruin/lizard_gaslava) +"Mv" = ( +/obj/effect/decal/cleanable/dirt/dust, +/obj/structure/sign/poster/fluff/lizards_gas_payment/directional/west, +/turf/open/floor/iron, +/area/ruin/lizard_gaslava) +"Nr" = ( +/obj/structure/window/plasma/spawner/directional/west, +/obj/structure/window/spawner/directional/east, +/obj/effect/spawner/random/structure/grille, +/turf/open/floor/plating, +/area/ruin/lizard_gaslava) +"Ov" = ( +/obj/structure/table, +/obj/machinery/coffeemaker{ + pixel_y = 5 + }, +/turf/open/floor/iron/smooth, +/area/ruin/lizard_gaslava) +"PS" = ( +/obj/effect/turf_decal/bot, +/obj/structure/cable, +/obj/machinery/power/rtg/advanced, +/turf/open/floor/iron/smooth, +/area/ruin/lizard_gaslava) +"Qb" = ( +/obj/machinery/atmospherics/pipe/smart/manifold4w/general/hidden, +/turf/open/floor/iron, +/area/ruin/lizard_gaslava) +"Qt" = ( +/obj/effect/decal/cleanable/dirt/dust, +/turf/open/floor/iron, +/area/ruin/lizard_gaslava) +"Rq" = ( +/obj/machinery/computer/security/telescreen/bar{ + pixel_y = -32 + }, +/obj/effect/decal/cleanable/dirt/dust, +/turf/open/floor/iron, +/area/ruin/lizard_gaslava) +"RA" = ( +/turf/closed/wall, +/area/ruin/lizard_gaslava) +"RK" = ( +/obj/machinery/light/directional/east, +/turf/open/misc/ashplanet/rocky, +/area/ruin/lizard_gaslava) +"SL" = ( +/obj/machinery/duct, +/turf/open/misc/ashplanet/rocky, +/area/ruin/lizard_gaslava) +"SZ" = ( +/obj/machinery/duct, +/obj/machinery/atmospherics/pipe/smart/manifold4w/general/hidden, +/turf/open/floor/iron, +/area/ruin/lizard_gaslava) +"TA" = ( +/obj/machinery/atmospherics/components/unary/vent_pump/on, +/turf/open/floor/iron/smooth, +/area/ruin/lizard_gaslava) +"Uk" = ( +/obj/machinery/duct, +/obj/machinery/light/directional/north, +/turf/open/misc/ashplanet/rocky, +/area/ruin/lizard_gaslava) +"UK" = ( +/obj/structure/cable, +/obj/machinery/power/smes/engineering, +/turf/open/floor/iron/smooth, +/area/ruin/lizard_gaslava) +"VD" = ( +/obj/effect/spawner/random/trash/food_packaging, +/turf/open/floor/iron, +/area/ruin/lizard_gaslava) +"Wa" = ( +/obj/structure/rack, +/obj/item/reagent_containers/condiment/vegetable_oil{ + pixel_y = 5; + pixel_x = -1 + }, +/obj/item/reagent_containers/condiment/vegetable_oil{ + pixel_y = 1; + pixel_x = 3 + }, +/obj/item/reagent_containers/condiment/olive_oil, +/turf/open/floor/iron, +/area/ruin/lizard_gaslava) +"Xe" = ( +/obj/structure/window/reinforced/spawner/directional/south, +/obj/structure/window/reinforced/spawner/directional/east, +/obj/structure/rack, +/obj/item/storage/cans/sixbeer, +/obj/item/storage/cans/sixsoda, +/turf/open/floor/iron/freezer, +/area/ruin/lizard_gaslava) +"Zf" = ( +/obj/machinery/door/airlock/glass, +/turf/open/floor/iron, +/area/ruin/lizard_gaslava) + +(1,1,1) = {" +DI +DI +DI +fF +fF +mY +DI +DI +DI +DI +DI +DI +DI +DI +DI +DI +DI +DI +DI +DI +ia +mG +mG +DI +DI +"} +(2,1,1) = {" +DI +DI +DI +fH +fH +fH +DI +DI +DI +DI +DI +DI +DI +DI +DI +DI +DI +DI +DI +DI +fH +fH +fH +DI +DI +"} +(3,1,1) = {" +DI +DI +DI +fH +fH +fH +DI +DI +ub +FA +FA +FA +FA +FA +FA +FA +FA +GK +DI +DI +fH +fH +fH +DI +DI +"} +(4,1,1) = {" +DI +DI +DI +fH +fH +fH +DI +DI +KJ +fH +SL +SL +SL +SL +SL +SL +SL +JX +DI +DI +fH +fH +fH +DI +DI +"} +(5,1,1) = {" +DI +DI +DI +fH +fH +fH +om +fH +fH +fH +wl +fH +wl +wl +fH +wl +SL +fH +fH +om +fH +fH +fH +DI +DI +"} +(6,1,1) = {" +DI +DI +DI +fH +fH +fH +om +fH +fH +xH +RA +fy +RA +RA +fy +RA +Uk +fH +fH +om +fH +fH +fH +DI +DI +"} +(7,1,1) = {" +DI +DI +DI +fH +fH +fH +om +fH +fH +fH +fX +fH +fX +fX +fH +fX +SL +fH +fH +om +fH +fH +fH +DI +DI +"} +(8,1,1) = {" +DI +DI +DI +DI +DI +DI +DI +DI +fH +fH +SL +SL +SL +SL +SL +SL +SL +fH +DI +DI +DI +DI +DI +DI +DI +"} +(9,1,1) = {" +DI +DI +DI +DI +DI +DI +DI +DI +RK +fH +fH +fH +fH +fH +fH +SL +fH +RK +DI +DI +DI +DI +DI +DI +DI +"} +(10,1,1) = {" +DI +DI +DI +DI +DI +DI +DI +DI +RA +Nr +Nr +Nr +RA +RA +RA +HW +ng +RA +DI +DI +DI +DI +DI +DI +DI +"} +(11,1,1) = {" +DI +DI +DI +DI +DI +DI +DI +DI +RA +Kl +xW +HI +Mv +aK +RA +ks +Es +RA +DI +DI +DI +DI +DI +DI +DI +"} +(12,1,1) = {" +DI +DI +DI +RA +RA +RA +RA +RA +RA +tD +VD +Gv +Bf +Rq +RA +nc +vH +RA +DI +DI +DI +DI +DI +DI +DI +"} +(13,1,1) = {" +DI +DI +DI +RA +Ov +FC +mn +vt +RA +mz +Qt +Km +bT +Zf +RA +sY +ng +RA +DI +DI +DI +DI +DI +DI +DI +"} +(14,1,1) = {" +DI +DI +DI +RA +Ag +pJ +TA +ck +dm +SZ +SZ +HL +SZ +HL +SZ +SZ +IU +RA +DI +DI +DI +DI +DI +DI +DI +"} +(15,1,1) = {" +DI +DI +DI +RA +UK +go +iK +PS +RA +Qt +Qb +xW +xW +jY +El +HS +uV +RA +DI +DI +DI +DI +DI +DI +DI +"} +(16,1,1) = {" +DI +DI +DI +RA +RA +RA +RA +RA +RA +xW +BH +yH +Qt +xW +VD +Qt +Ao +RA +DI +DI +DI +DI +DI +DI +DI +"} +(17,1,1) = {" +DI +DI +DI +DI +DI +DI +DI +DI +RA +xW +Ef +xW +xW +rM +EA +Xe +xW +RA +DI +DI +DI +DI +DI +DI +DI +"} +(18,1,1) = {" +DI +DI +DI +DI +DI +DI +DI +DI +RA +FL +Wa +Eh +xW +Qt +pp +xW +BX +RA +DI +DI +DI +DI +DI +DI +DI +"} +(19,1,1) = {" +DI +DI +DI +DI +DI +DI +DI +DI +RA +RA +RA +RA +RA +RA +RA +RA +RA +RA +DI +DI +DI +DI +DI +DI +DI +"} +(20,1,1) = {" +DI +DI +DI +DI +DI +DI +DI +DI +DI +DI +DI +DI +DI +DI +DI +DI +DI +DI +DI +DI +DI +DI +DI +DI +DI +"} +(21,1,1) = {" +DI +DI +DI +DI +DI +DI +DI +DI +DI +DI +DI +DI +DI +DI +DI +DI +DI +DI +DI +DI +DI +DI +DI +DI +DI +"} +(22,1,1) = {" +DI +DI +DI +DI +DI +DI +DI +DI +DI +DI +DI +DI +DI +DI +DI +DI +DI +DI +DI +DI +DI +DI +DI +DI +DI +"} +(23,1,1) = {" +DI +DI +DI +DI +DI +DI +DI +DI +DI +DI +DI +DI +DI +DI +DI +DI +DI +DI +DI +DI +DI +DI +DI +DI +DI +"} +(24,1,1) = {" +DI +DI +DI +DI +DI +DI +DI +DI +DI +DI +DI +DI +DI +DI +DI +DI +DI +DI +DI +DI +DI +DI +DI +DI +DI +"} +(25,1,1) = {" +DI +DI +DI +DI +DI +DI +DI +DI +DI +DI +DI +DI +DI +DI +DI +DI +DI +DI +DI +DI +DI +DI +DI +DI +DI +"} diff --git a/_maps/RandomRuins/LavaRuins/skyrat/lavaland_surface_syndicate_base1_skyrat.dmm b/_maps/RandomRuins/LavaRuins/skyrat/lavaland_surface_syndicate_base1_skyrat.dmm index 7fee6e4aa99fa1e..587709ac808522c 100644 --- a/_maps/RandomRuins/LavaRuins/skyrat/lavaland_surface_syndicate_base1_skyrat.dmm +++ b/_maps/RandomRuins/LavaRuins/skyrat/lavaland_surface_syndicate_base1_skyrat.dmm @@ -1284,11 +1284,7 @@ /turf/open/floor/iron/dark/textured_large, /area/ruin/syndicate_lava_base/arrivals) "iu" = ( -/obj/structure/frame/machine{ - anchored = 1; - state = 2; - icon_state = "box_1" - }, +/obj/structure/frame/machine/secured, /obj/item/circuitboard/machine/ore_redemption, /obj/item/assembly/igniter, /obj/structure/marker_beacon/burgundy, @@ -4830,11 +4826,7 @@ /turf/closed/wall/r_wall/syndicate/nodiagonal, /area/ruin/syndicate_lava_base/bar) "Gc" = ( -/obj/structure/frame/machine{ - anchored = 1; - state = 2; - icon_state = "box_1" - }, +/obj/structure/frame/machine/secured, /obj/item/circuitboard/machine/ore_silo, /obj/structure/marker_beacon/burgundy, /obj/structure/sign/flag/syndicate/directional/north, diff --git a/_maps/RandomRuins/SpaceRuins/garbagetruck4.dmm b/_maps/RandomRuins/SpaceRuins/garbagetruck4.dmm index a636b7220cab54d..33c5893bcee4c2f 100644 --- a/_maps/RandomRuins/SpaceRuins/garbagetruck4.dmm +++ b/_maps/RandomRuins/SpaceRuins/garbagetruck4.dmm @@ -78,7 +78,7 @@ /turf/open/floor/plating, /area/ruin/space/has_grav/garbagetruck/toystore) "hH" = ( -/obj/structure/spider/solid, +/obj/structure/spider/stickyweb/sealed/tough, /obj/item/book/manual/wiki/cytology, /obj/effect/decal/cleanable/plastic, /turf/open/floor/plating, @@ -122,7 +122,7 @@ /area/ruin/space/has_grav/garbagetruck/toystore) "lm" = ( /obj/structure/spider/stickyweb, -/obj/structure/spider/sticky, +/obj/structure/spider/stickyweb/very_sticky, /turf/open/floor/plating, /area/ruin/space/has_grav/garbagetruck/toystore) "mf" = ( @@ -182,7 +182,7 @@ /turf/open/floor/plating, /area/ruin/space/has_grav/garbagetruck/toystore) "qX" = ( -/obj/structure/spider/sticky, +/obj/structure/spider/stickyweb/very_sticky, /obj/item/food/badrecipe/moldy, /obj/structure/spider/stickyweb, /obj/item/food/spidereggs{ @@ -255,7 +255,7 @@ /turf/open/floor/plating, /area/ruin/space/has_grav/garbagetruck/toystore) "ts" = ( -/obj/structure/spider/solid, +/obj/structure/spider/stickyweb/sealed/tough, /obj/structure/spider/stickyweb, /obj/structure/closet/crate/trashcart/filled, /turf/open/floor/plating, @@ -841,7 +841,7 @@ /turf/open/floor/plating, /area/ruin/space/has_grav/garbagetruck/toystore) "XI" = ( -/obj/structure/spider/solid, +/obj/structure/spider/stickyweb/sealed/tough, /obj/item/food/badrecipe/moldy/bacteria, /turf/open/floor/plating, /area/ruin/space/has_grav/garbagetruck/toystore) diff --git a/_maps/RandomRuins/SpaceRuins/meatderelict.dmm b/_maps/RandomRuins/SpaceRuins/meatderelict.dmm index 0c4e9cd740b372e..3e4bece11e8e59a 100644 --- a/_maps/RandomRuins/SpaceRuins/meatderelict.dmm +++ b/_maps/RandomRuins/SpaceRuins/meatderelict.dmm @@ -733,7 +733,7 @@ /turf/open/indestructible/white, /area/ruin/space/has_grav/powered/biooutpost) "oQ" = ( -/obj/machinery/puzzle_button/meatderelict{ +/obj/machinery/puzzle/button/meatderelict{ pixel_y = 32; queue_size = 4 }, @@ -1669,7 +1669,7 @@ "FI" = ( /obj/item/instrument/piano_synth/headphones, /obj/structure/table, -/obj/machinery/puzzle_button/directional/north{ +/obj/machinery/puzzle/button/directional/north{ used = 1 }, /obj/effect/turf_decal/tile/neutral/opposingcorners, @@ -1820,7 +1820,7 @@ /turf/open/floor/iron/dark/textured_large, /area/ruin/space/has_grav/powered/biooutpost/vault) "Jt" = ( -/obj/machinery/puzzle_button/directional/north{ +/obj/machinery/puzzle/button/directional/north{ id = "md_tosci"; name = "shield power panel" }, @@ -1889,7 +1889,7 @@ /turf/open/indestructible/white, /area/ruin/space/has_grav/powered/biooutpost) "KC" = ( -/obj/machinery/puzzle_button/directional/north{ +/obj/machinery/puzzle/button/directional/north{ id = "md_toeng"; queue_size = 4 }, @@ -2138,7 +2138,7 @@ id = "md_armory" }, /obj/effect/turf_decal/stripes/full, -/obj/machinery/puzzle_keycardpad/directional/south{ +/obj/machinery/puzzle/keycardpad/directional/south{ id = "md_armory"; name = "armory authentication pad"; queue_size = 5 diff --git a/_maps/RandomRuins/SpaceRuins/skyrat/interdynefob.dmm b/_maps/RandomRuins/SpaceRuins/skyrat/interdynefob.dmm index 24753333b4b8349..57ff783e409ee2f 100644 --- a/_maps/RandomRuins/SpaceRuins/skyrat/interdynefob.dmm +++ b/_maps/RandomRuins/SpaceRuins/skyrat/interdynefob.dmm @@ -46,11 +46,7 @@ /turf/open/floor/iron/dark/textured_large, /area/ruin/space/has_grav/skyrat/interdynefob/security/prison) "aj" = ( -/obj/structure/frame/machine{ - anchored = 1; - icon_state = "box_1"; - state = 2 - }, +/obj/structure/frame/machine/secured, /obj/item/circuitboard/machine/mech_recharger, /obj/effect/turf_decal/trimline/dark_red/filled/line, /obj/effect/turf_decal/siding/dark{ @@ -801,11 +797,7 @@ }, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/structure/frame/machine{ - anchored = 1; - icon_state = "box_1"; - state = 2 - }, +/obj/structure/frame/machine/secured, /obj/item/circuitboard/machine/ore_redemption, /obj/item/assembly/igniter, /turf/open/floor/iron/dark/textured_large, @@ -1477,11 +1469,7 @@ /turf/closed/wall/r_wall/syndicate, /area/ruin/space/has_grav/skyrat/interdynefob/bridge/vault) "gw" = ( -/obj/structure/frame/machine{ - anchored = 1; - icon_state = "box_1"; - state = 2 - }, +/obj/structure/frame/machine/secured, /obj/item/circuitboard/machine/component_printer, /obj/effect/turf_decal/trimline/dark_red/filled/line{ dir = 5 @@ -1942,11 +1930,7 @@ dir = 4 }, /obj/item/circuitboard/machine/circuit_imprinter/offstation, -/obj/structure/frame/machine{ - anchored = 1; - icon_state = "box_1"; - state = 2 - }, +/obj/structure/frame/machine/secured, /turf/open/floor/iron/dark, /area/ruin/space/has_grav/skyrat/interdynefob/research) "il" = ( @@ -2302,11 +2286,7 @@ /turf/open/floor/plating/elevatorshaft, /area/ruin/space/has_grav/skyrat/interdynefob/cargo/hangar) "jJ" = ( -/obj/structure/frame/machine{ - anchored = 1; - icon_state = "box_1"; - state = 2 - }, +/obj/structure/frame/machine/secured, /obj/item/circuitboard/machine/mechfab, /obj/effect/turf_decal/trimline/dark_red/filled/line, /turf/open/floor/iron/dark, @@ -2773,11 +2753,7 @@ /obj/effect/turf_decal/siding/dark{ dir = 9 }, -/obj/structure/frame/machine{ - anchored = 1; - icon_state = "box_1"; - state = 2 - }, +/obj/structure/frame/machine/secured, /obj/item/circuitboard/machine/smes, /turf/open/floor/plating, /area/ruin/space/has_grav/skyrat/interdynefob/engineering) @@ -3510,11 +3486,7 @@ /turf/open/floor/mineral/plastitanium/red, /area/ruin/space/has_grav/skyrat/interdynefob/security) "pk" = ( -/obj/structure/frame/machine{ - anchored = 1; - icon_state = "box_1"; - state = 2 - }, +/obj/structure/frame/machine/secured, /obj/item/circuitboard/machine/module_duplicator, /obj/effect/turf_decal/trimline/dark_red/filled/line{ dir = 4 @@ -4781,11 +4753,7 @@ /turf/open/floor/iron/dark/small, /area/ruin/space/has_grav/skyrat/interdynefob/security/prison) "vd" = ( -/obj/structure/frame/machine{ - anchored = 1; - icon_state = "box_1"; - state = 2 - }, +/obj/structure/frame/machine/secured, /obj/item/circuitboard/machine/cyborgrecharger, /obj/effect/turf_decal/siding/dark{ dir = 8 @@ -5500,11 +5468,7 @@ /obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2{ dir = 4 }, -/obj/structure/frame/machine{ - anchored = 1; - icon_state = "box_1"; - state = 2 - }, +/obj/structure/frame/machine/secured, /turf/open/floor/iron/dark, /area/ruin/space/has_grav/skyrat/interdynefob/research) "zh" = ( @@ -5912,11 +5876,7 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/machinery/light/red/directional/north, /obj/item/folded_navigation_gigabeacon, -/obj/structure/frame/machine{ - anchored = 1; - icon_state = "box_1"; - state = 2 - }, +/obj/structure/frame/machine/secured, /turf/open/floor/iron/dark, /area/ruin/space/has_grav/skyrat/interdynefob/bridge/vault) "Bj" = ( @@ -7477,11 +7437,7 @@ dir = 5 }, /obj/item/circuitboard/machine/destructive_analyzer, -/obj/structure/frame/machine{ - anchored = 1; - icon_state = "box_1"; - state = 2 - }, +/obj/structure/frame/machine/secured, /turf/open/floor/iron/dark, /area/ruin/space/has_grav/skyrat/interdynefob/research) "IM" = ( @@ -7522,11 +7478,7 @@ /area/ruin/space/has_grav/skyrat/interdynefob/service/dorms/fitness) "IU" = ( /obj/item/circuitboard/machine/ammo_workbench, -/obj/structure/frame/machine{ - anchored = 1; - icon_state = "box_1"; - state = 2 - }, +/obj/structure/frame/machine/secured, /obj/item/disk/ammo_workbench/advanced, /obj/effect/turf_decal/siding/dark{ dir = 8 @@ -10411,11 +10363,7 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /obj/machinery/light/red/directional/south, /obj/item/circuitboard/machine/ore_silo, -/obj/structure/frame/machine{ - anchored = 1; - icon_state = "box_1"; - state = 2 - }, +/obj/structure/frame/machine/secured, /turf/open/floor/iron/dark, /area/ruin/space/has_grav/skyrat/interdynefob/bridge/vault) "VJ" = ( diff --git a/_maps/RandomZLevels/museum.dmm b/_maps/RandomZLevels/museum.dmm index f40ecc09015c658..64fd580b80f78c2 100644 --- a/_maps/RandomZLevels/museum.dmm +++ b/_maps/RandomZLevels/museum.dmm @@ -9,11 +9,18 @@ /obj/machinery/computer/old{ name = "replica computer"; dir = 8; - icon_keyboard = "rd_key"; - icon_screen = "rdcomp" + icon_screen = "rdcomp"; + icon_keyboard = "rd_key" }, /turf/open/floor/iron/smooth_large, /area/awaymission/museum) +"ac" = ( +/obj/structure/sign/poster/contraband/fake_bombable/directional/west, +/obj/structure/closet/crate/bin, +/obj/machinery/light/warm/directional/south, +/obj/effect/decal/cleanable/dirt/dust, +/turf/open/floor/iron/cafeteria, +/area/awaymission/museum/cafeteria) "ai" = ( /obj/structure/railing{ dir = 8 @@ -59,6 +66,11 @@ }, /turf/open/indestructible/plating, /area/awaymission/museum) +"ax" = ( +/obj/structure/sink/directional/north, +/obj/structure/mirror/directional/south, +/turf/open/floor/iron/white/small, +/area/awaymission/museum) "az" = ( /obj/structure/table/reinforced, /obj/effect/spawner/random/entertainment/musical_instrument, @@ -76,6 +88,22 @@ /obj/structure/closet/crate/preopen, /turf/open/indestructible/plating, /area/awaymission/museum) +"aO" = ( +/obj/machinery/button/door/directional/north{ + name = "Lock Control"; + id = "museum_toilet_wontwork" + }, +/obj/effect/mob_spawn/corpse/human/skeleton/museum_chef, +/obj/structure/toilet/museum{ + dir = 4 + }, +/obj/item/keycard/cafeteria, +/obj/item/paper/fluff/museum/chefs_ultimatum, +/obj/machinery/light/small/dim/directional/west, +/obj/effect/decal/cleanable/dirt/dust, +/obj/effect/decal/cleanable/cobweb, +/turf/open/floor/iron/white/small, +/area/awaymission/museum) "aR" = ( /obj/effect/turf_decal/tile/neutral/opposingcorners, /obj/effect/turf_decal/siding/dark_blue{ @@ -147,8 +175,8 @@ }, /turf/open/mirage{ dir = 8; - target_turf_x = 11; - range = 1 + range = 1; + target_turf_x = 11 }, /area/awaymission/museum) "bC" = ( @@ -177,8 +205,8 @@ /area/awaymission/museum) "bJ" = ( /mob/living/basic/statue/mannequin{ - dir = 8; - name = "Dale Knox" + name = "Dale Knox"; + dir = 8 }, /obj/effect/turf_decal/tile/blue/opposingcorners, /turf/open/floor/holofloor/white, @@ -229,6 +257,14 @@ /obj/item/storage/box/stickers/googly, /turf/open/floor/iron/dark, /area/awaymission/museum) +"ci" = ( +/obj/effect/turf_decal/siding/dark_blue{ + dir = 1 + }, +/obj/effect/turf_decal/tile/neutral/opposingcorners, +/obj/effect/decal/cleanable/dirt/dust, +/turf/open/floor/iron/dark, +/area/awaymission/museum) "cm" = ( /obj/machinery/door/airlock/grunge, /obj/structure/barricade/wooden/crude, @@ -255,8 +291,8 @@ /turf/open/floor/iron/smooth_half, /area/awaymission/museum) "ct" = ( -/obj/structure/chair/comfy, /mob/living/basic/mothroach, +/obj/structure/chair/comfy, /obj/effect/mapping_helpers/mob_buckler, /obj/machinery/light/dim/directional/north, /turf/open/floor/iron/dark/textured_large, @@ -313,8 +349,8 @@ /obj/effect/turf_decal/tile/neutral/opposingcorners, /obj/item/toy/balloon/corgi, /obj/machinery/status_display/random_message{ - firstline_to_secondline = list("NO" = "LITTERING","YOU ARE" = "BEING WATCHED", "DO NOT TOUCH" = "THE EXHIBITS"); - pixel_x = 32 + pixel_x = 32; + firstline_to_secondline = list(NO="LITTERING", "YOU ARE"="BEING WATCHED", "DO NOT TOUCH"="THE EXHIBITS") }, /turf/open/floor/iron/dark, /area/awaymission/museum) @@ -328,9 +364,9 @@ "cS" = ( /obj/effect/step_trigger/thrower{ direction = 1; - facedir = 1; + mobs_only = 1; tiles = 10; - mobs_only = 1 + facedir = 1 }, /obj/machinery/light/floor, /turf/open/floor/iron, @@ -343,6 +379,14 @@ /obj/structure/plaque/static_plaque/golden/commission/dream, /turf/closed/indestructible/reinforced, /area/awaymission/museum) +"cY" = ( +/obj/structure/fluff/fake_camera{ + dir = 5 + }, +/obj/machinery/light/warm/directional/east, +/obj/structure/fluff/fake_scrubber, +/turf/open/floor/iron/cafeteria, +/area/awaymission/museum/cafeteria) "cZ" = ( /obj/structure/fluff/divine/nexus, /turf/open/floor/cult, @@ -398,9 +442,9 @@ /area/awaymission/museum) "dK" = ( /turf/open/mirage{ + dir = 1; range = 2; - target_turf_y = -4; - dir = 1 + target_turf_y = -4 }, /area/awaymission/museum) "dL" = ( @@ -434,8 +478,8 @@ /area/awaymission/museum) "dY" = ( /mob/living/basic/statue/mannequin{ - hat = /obj/item/clothing/head/helmet/space; - dir = 1 + dir = 1; + hat = /obj/item/clothing/head/helmet/space }, /turf/open/floor/holofloor/hyperspace/ns, /area/awaymission/museum) @@ -462,7 +506,7 @@ /obj/machinery/door/poddoor/shutters/indestructible{ id = "museum_secret" }, -/obj/machinery/puzzle_keycardpad/directional/east{ +/obj/machinery/puzzle/keycardpad/directional/east{ id = "museum_secret" }, /turf/open/floor/iron/dark, @@ -521,10 +565,10 @@ /turf/open/floor/grass, /area/awaymission/museum) "ex" = ( +/mob/living/basic/mothroach, /obj/structure/chair/stool/bar/directional/west{ can_buckle = 1 }, -/mob/living/basic/mothroach, /obj/effect/mapping_helpers/mob_buckler, /turf/open/floor/wood/large, /area/awaymission/museum) @@ -596,6 +640,15 @@ /obj/structure/plaque/static_plaque/golden/commission/omega, /turf/closed/indestructible/reinforced, /area/awaymission/museum) +"eW" = ( +/obj/effect/turf_decal/tile/neutral/opposingcorners, +/obj/effect/turf_decal/siding/dark_blue, +/obj/structure/fluff/wallsign/directional/north{ + name = "Restrooms"; + dir = 4 + }, +/turf/open/floor/iron/dark, +/area/awaymission/museum) "eX" = ( /obj/effect/turf_decal/siding/wideplating{ dir = 4 @@ -605,11 +658,11 @@ }, /area/awaymission/museum) "fa" = ( -/obj/effect/turf_decal/sand/plating, /mob/living/basic/statue/mannequin{ held_item = /obj/item/pickaxe; hat = /obj/item/clothing/suit/hooded/explorer }, +/obj/effect/turf_decal/sand/plating, /obj/effect/turf_decal/mining, /turf/open/indestructible/plating, /area/awaymission/museum) @@ -627,6 +680,13 @@ /obj/item/kitchen/fork, /turf/open/floor/wood/tile, /area/awaymission/museum) +"fl" = ( +/obj/machinery/status_display/random_message{ + pixel_x = -32; + firstline_to_secondline = list(CAFETERIA="YUMMY", CAFETERIA="HOTDOGS", ENJOY="YOUR MEAL") + }, +/turf/open/floor/iron/cafeteria, +/area/awaymission/museum/cafeteria) "fn" = ( /turf/open/floor/holofloor/hyperspace/ns, /area/awaymission/museum) @@ -706,6 +766,11 @@ }, /turf/open/floor/iron, /area/awaymission/museum) +"gg" = ( +/obj/effect/decal/cleanable/dirt/dust, +/obj/machinery/shower/directional/east, +/turf/open/floor/iron/white/small, +/area/awaymission/museum) "gj" = ( /obj/machinery/door/poddoor/shutters/preopen{ dir = 8 @@ -751,6 +816,10 @@ /obj/machinery/light/small/dim/directional/south, /turf/open/indestructible/plating, /area/awaymission/museum) +"gE" = ( +/obj/item/clothing/suit/caution, +/turf/open/floor/iron/white/small, +/area/awaymission/museum) "gG" = ( /obj/effect/turf_decal/siding/dark_blue/corner{ dir = 4 @@ -814,8 +883,8 @@ "hk" = ( /obj/effect/smooths_with_walls, /turf/open/mirage{ - target_turf_y = -29; - dir = 1 + dir = 1; + target_turf_y = -29 }, /area/awaymission/museum) "hl" = ( @@ -827,6 +896,12 @@ }, /turf/open/indestructible/plating, /area/awaymission/museum) +"hm" = ( +/obj/structure/table, +/obj/effect/spawner/random/food_or_drink/condiment, +/obj/machinery/light/floor, +/turf/open/floor/iron/cafeteria, +/area/awaymission/museum/cafeteria) "hp" = ( /mob/living/basic/mothroach/bar, /turf/open/floor/wood/tile, @@ -874,10 +949,18 @@ "hM" = ( /turf/closed/wall/rock/porous, /area/awaymission/museum) +"hS" = ( +/obj/effect/turf_decal/tile/neutral/opposingcorners, +/obj/effect/decal/cleanable/dirt/dust, +/obj/effect/turf_decal/siding/dark_blue{ + dir = 5 + }, +/turf/open/floor/iron/dark, +/area/awaymission/museum) "hT" = ( /mob/living/basic/statue/mannequin{ - dir = 8; name = "Dale Knox"; + dir = 8; held_item = /obj/item/circuitboard }, /obj/structure/sign/flag/nanotrasen/directional/south, @@ -892,8 +975,8 @@ /area/awaymission/museum) "hX" = ( /obj/item/circuitboard{ - icon_state = "flopdrive"; - name = "microprocessor" + name = "microprocessor"; + icon_state = "flopdrive" }, /obj/structure/table/reinforced, /turf/open/floor/circuit/green, @@ -983,6 +1066,15 @@ /obj/machinery/light/floor, /turf/open/floor/iron/dark, /area/awaymission/museum) +"iJ" = ( +/obj/effect/decal/cleanable/dirt/dust, +/obj/structure/toilet/museum{ + dir = 1 + }, +/obj/structure/curtain, +/obj/structure/broken_flooring/plating, +/turf/open/floor/iron/white/small, +/area/awaymission/museum) "iK" = ( /obj/effect/turf_decal/sand/plating, /obj/effect/turf_decal/siding{ @@ -1031,9 +1123,9 @@ }, /obj/effect/step_trigger/thrower{ direction = 1; - facedir = 1; + mobs_only = 1; tiles = 10; - mobs_only = 1 + facedir = 1 }, /turf/open/floor/iron/dark, /area/awaymission/museum) @@ -1067,10 +1159,20 @@ }, /turf/open/floor/cult, /area/awaymission/museum) +"ju" = ( +/obj/effect/turf_decal/tile/neutral/opposingcorners, +/obj/effect/turf_decal/siding/dark_blue{ + dir = 6 + }, +/obj/structure/fluff/wallsign/directional/north{ + name = "Restrooms" + }, +/turf/open/floor/iron/dark, +/area/awaymission/museum) "jy" = ( /mob/living/basic/statue/mannequin{ - dir = 8; name = "Dale Knox"; + dir = 8; held_item = /obj/item/circuitboard }, /obj/effect/turf_decal/stripes{ @@ -1082,6 +1184,14 @@ /obj/effect/spawner/structure/window, /turf/open/indestructible/plating, /area/awaymission/museum) +"jC" = ( +/obj/effect/puzzle_poddoor_open{ + icon = 'icons/effects/mapping_helpers.dmi'; + id = "museum_right_wing"; + queue_id = "museum_right_wing" + }, +/turf/closed/indestructible/reinforced, +/area/awaymission/museum) "jF" = ( /obj/machinery/suit_storage_unit/open, /obj/effect/turf_decal/box, @@ -1110,6 +1220,18 @@ /obj/effect/decal/cleanable/dirt/dust, /turf/open/floor/iron/dark, /area/awaymission/museum) +"jO" = ( +/obj/structure/toilet/museum, +/obj/structure/sign/poster/contraband/fake_bombable/directional/north, +/obj/machinery/button/door/directional/east{ + name = "Lock Control"; + id = "museum_toilet6"; + specialfunctions = 4; + normaldoorcontrol = 1 + }, +/obj/machinery/light/small/dim/directional/north, +/turf/open/floor/iron/white/small, +/area/awaymission/museum) "jP" = ( /obj/effect/turf_decal/tile/neutral/opposingcorners, /obj/effect/turf_decal/siding/dark_blue/corner{ @@ -1120,13 +1242,16 @@ dir = 9 }, /obj/item/reagent_containers/cup/glass/coffee, +/obj/item/paper/fluff/scrambled_pass{ + puzzle_id = "museum_r_wing_puzzle" + }, /turf/open/floor/iron/dark, /area/awaymission/museum) "jU" = ( /obj/effect/landmark/transport/nav_beacon/tram/platform{ + name = "Exhibit Loading Bay"; specific_transport_id = "museum_cargo"; - platform_code = 2; - name = "Exhibit Loading Bay" + platform_code = 2 }, /turf/open/chasm/true/no_smooth, /area/awaymission/museum) @@ -1193,6 +1318,12 @@ }, /turf/open/floor/iron, /area/awaymission/museum) +"kx" = ( +/obj/machinery/door/airlock/public{ + name = "Restrooms" + }, +/turf/open/floor/iron, +/area/awaymission/museum) "kA" = ( /obj/machinery/conveyor{ dir = 1 @@ -1200,6 +1331,16 @@ /obj/item/vending_refill/wardrobe/coroner_wardrobe, /turf/open/indestructible/plating, /area/awaymission/museum) +"kL" = ( +/obj/machinery/door/poddoor/shutters/window/indestructible{ + dir = 8; + id = "museum_cafeteria" + }, +/obj/machinery/puzzle/keycardpad/directional/south{ + id = "museum_cafeteria" + }, +/turf/open/floor/iron, +/area/awaymission/museum) "kO" = ( /obj/structure/railing{ dir = 8 @@ -1227,6 +1368,19 @@ /obj/effect/decal/cleanable/dirt/dust, /turf/open/indestructible/plating, /area/awaymission/museum) +"kZ" = ( +/obj/structure/toilet/museum{ + dir = 4 + }, +/obj/machinery/button/door/directional/north{ + name = "Lock Control"; + id = "museum_toilet5"; + specialfunctions = 4; + normaldoorcontrol = 1 + }, +/obj/machinery/light/small/dim/directional/west, +/turf/open/floor/iron/white/small, +/area/awaymission/museum) "la" = ( /obj/effect/turf_decal/siding/wood{ dir = 4 @@ -1324,11 +1478,11 @@ /turf/open/floor/iron, /area/awaymission/museum) "lT" = ( -/obj/structure/chair/office{ - dir = 1 - }, /mob/living/basic/statue/mannequin{ - hat = /obj/item/clothing/suit/toggle/labcoat/science; + dir = 1; + hat = /obj/item/clothing/suit/toggle/labcoat/science + }, +/obj/structure/chair/office{ dir = 1 }, /obj/machinery/light/floor, @@ -1345,9 +1499,9 @@ specific_transport_id = "museum_cargo" }, /obj/effect/landmark/transport/nav_beacon/tram/platform{ + name = "Internal Loading Bay"; specific_transport_id = "museum_cargo"; - platform_code = 1; - name = "Internal Loading Bay" + platform_code = 1 }, /turf/open/chasm/true/no_smooth, /area/awaymission/museum) @@ -1379,6 +1533,9 @@ }, /turf/open/chasm/true/no_smooth, /area/awaymission/museum) +"ms" = ( +/turf/open/floor/iron, +/area/awaymission/museum/cafeteria) "mA" = ( /obj/structure/window/reinforced/spawner/directional/west, /turf/open/floor/holofloor/beach/water, @@ -1403,9 +1560,9 @@ /area/awaymission/museum) "mS" = ( /mob/living/basic/statue/mannequin{ + dir = 1; held_item = /obj/item/wrench; - hat = /obj/item/clothing/head/utility/hardhat; - dir = 1 + hat = /obj/item/clothing/head/utility/hardhat }, /obj/effect/decal/cleanable/dirt/dust, /obj/effect/decal/cleanable/blood/gibs, @@ -1436,8 +1593,8 @@ /obj/structure/transport/linear/tram/slow, /obj/structure/tram, /obj/machinery/transport/tram_controller{ - configured_transport_id = "museum_cargo"; - cover_locked = 0 + cover_locked = 0; + configured_transport_id = "museum_cargo" }, /turf/open/chasm/true/no_smooth, /area/awaymission/museum) @@ -1477,8 +1634,8 @@ /turf/open/floor/iron/white, /area/awaymission/museum) "nu" = ( -/obj/effect/decal/cleanable/glass/titanium, /mob/living/basic/mouse/rat, +/obj/effect/decal/cleanable/glass/titanium, /turf/open/floor/iron/white, /area/awaymission/museum) "nv" = ( @@ -1510,9 +1667,9 @@ "nz" = ( /obj/structure/lattice/catwalk/mining, /obj/structure/fluff{ + name = "old plasma extractor"; icon = 'icons/mob/simple/hivebot.dmi'; - icon_state = "fab_robot"; - name = "old plasma extractor" + icon_state = "fab_robot" }, /turf/open/lava/plasma/mafia, /area/awaymission/museum) @@ -1537,9 +1694,9 @@ }, /obj/effect/step_trigger/thrower{ direction = 1; - facedir = 1; + mobs_only = 1; tiles = 10; - mobs_only = 1 + facedir = 1 }, /turf/open/floor/iron/dark, /area/awaymission/museum) @@ -1588,6 +1745,16 @@ }, /turf/open/floor/iron/dark, /area/awaymission/museum) +"nY" = ( +/obj/structure/sign/poster/official/no_erp/directional/north, +/turf/open/floor/iron/white/small, +/area/awaymission/museum) +"nZ" = ( +/obj/structure/chair/sofa/bench/left{ + dir = 1 + }, +/turf/open/floor/iron/cafeteria, +/area/awaymission/museum/cafeteria) "od" = ( /obj/structure/fluff/fake_vent, /turf/open/floor/iron, @@ -1648,11 +1815,31 @@ /obj/structure/flora/coconuts, /turf/open/misc/beach/sand, /area/awaymission/museum/mothroachvoid) +"oD" = ( +/obj/structure/toilet/museum{ + dir = 4 + }, +/obj/machinery/button/door/directional/north{ + name = "Lock Control"; + id = "museum_toilet4"; + specialfunctions = 4; + normaldoorcontrol = 1 + }, +/obj/machinery/light/small/dim/directional/west, +/turf/open/floor/iron/white/small, +/area/awaymission/museum) "oI" = ( /obj/effect/decal/cleanable/dirt/dust, /obj/machinery/light/floor, /turf/open/floor/iron, /area/awaymission/museum) +"oP" = ( +/obj/effect/puzzle_poddoor_open{ + id = "museum_cafeteria"; + queue_id = "museum_cafeteria" + }, +/turf/closed/indestructible/reinforced, +/area/awaymission/museum) "oQ" = ( /turf/open/floor/holofloor/beach/coast{ dir = 1 @@ -1694,8 +1881,8 @@ /area/awaymission/museum) "pi" = ( /mob/living/basic/statue/mannequin{ - hat = /obj/item/clothing/head/costume/nursehat; - held_item = /obj/item/clothing/neck/stethoscope + held_item = /obj/item/clothing/neck/stethoscope; + hat = /obj/item/clothing/head/costume/nursehat }, /obj/effect/turf_decal/tile/blue/opposingcorners, /turf/open/floor/holofloor/white, @@ -1729,6 +1916,13 @@ /obj/effect/decal/cleanable/dirt/dust, /turf/open/floor/iron/white, /area/awaymission/museum) +"pz" = ( +/obj/machinery/door/poddoor/shutters/window/indestructible{ + dir = 8; + id = "museum_cafeteria" + }, +/turf/open/floor/iron, +/area/awaymission/museum) "pD" = ( /obj/structure/broken_flooring/corner/always_floorplane/directional/west, /obj/effect/decal/cleanable/dirt/dust, @@ -1758,6 +1952,17 @@ }, /turf/open/indestructible/plating, /area/awaymission/museum) +"pN" = ( +/obj/effect/decal/cleanable/dirt/dust, +/obj/effect/turf_decal/tile/neutral/opposingcorners, +/obj/effect/turf_decal/siding/dark_blue{ + dir = 6 + }, +/obj/structure/fluff/fake_camera{ + dir = 4 + }, +/turf/open/floor/iron/dark, +/area/awaymission/museum) "pX" = ( /obj/structure/rack, /obj/effect/spawner/random/maintenance/two, @@ -1773,6 +1978,10 @@ /obj/effect/decal/cleanable/dirt/dust, /turf/open/floor/iron, /area/awaymission/museum) +"ql" = ( +/obj/structure/chair/sofa/bench, +/turf/open/floor/iron/cafeteria, +/area/awaymission/museum/cafeteria) "qo" = ( /obj/effect/oneway{ dir = 8 @@ -1784,15 +1993,15 @@ /area/awaymission/museum) "qt" = ( /obj/effect/spawner/random/food_or_drink/booze{ - loot = list(/obj/item/reagent_containers/cup/glass/bottle/beer = 10, /obj/item/reagent_containers/cup/glass/bottle/ale = 10, /obj/item/reagent_containers/cup/glass/bottle/beer/light = 5, /obj/item/reagent_containers/cup/glass/bottle/maltliquor = 5, /obj/item/reagent_containers/cup/glass/bottle/whiskey = 5, /obj/item/reagent_containers/cup/glass/bottle/gin = 5, /obj/item/reagent_containers/cup/glass/bottle/vodka = 5, /obj/item/reagent_containers/cup/glass/bottle/tequila = 5, /obj/item/reagent_containers/cup/glass/bottle/rum = 5, /obj/item/reagent_containers/cup/glass/bottle/vermouth = 5, /obj/item/reagent_containers/cup/glass/bottle/cognac = 5, /obj/item/reagent_containers/cup/glass/bottle/wine = 5, /obj/item/reagent_containers/cup/glass/bottle/kahlua = 5, /obj/item/reagent_containers/cup/glass/bottle/amaretto = 5, /obj/item/reagent_containers/cup/glass/bottle/hcider = 5, /obj/item/reagent_containers/cup/glass/bottle/absinthe = 5, /obj/item/reagent_containers/cup/glass/bottle/sake = 5, /obj/item/reagent_containers/cup/glass/bottle/grappa = 5, /obj/item/reagent_containers/cup/glass/bottle/applejack = 5, /obj/item/reagent_containers/cup/glass/bottle/wine_voltaic = 5, /obj/item/reagent_containers/cup/bottle/ethanol = 2, /obj/item/reagent_containers/cup/glass/bottle/fernet = 2, /obj/item/reagent_containers/cup/glass/bottle/champagne = 2, /obj/item/reagent_containers/cup/glass/bottle/absinthe/premium = 2, /obj/item/reagent_containers/cup/glass/bottle/goldschlager = 2, /obj/item/reagent_containers/cup/glass/bottle/patron = 1, /obj/item/reagent_containers/cup/glass/bottle/kong = 1, /obj/item/reagent_containers/cup/glass/bottle/lizardwine = 1, /obj/item/reagent_containers/cup/glass/bottle/vodka/badminka = 1, /obj/item/reagent_containers/cup/glass/bottle/trappist = 1); + loot = list(/obj/item/reagent_containers/cup/glass/bottle/beer=10, /obj/item/reagent_containers/cup/glass/bottle/ale=10, /obj/item/reagent_containers/cup/glass/bottle/beer/light=5, /obj/item/reagent_containers/cup/glass/bottle/maltliquor=5, /obj/item/reagent_containers/cup/glass/bottle/whiskey=5, /obj/item/reagent_containers/cup/glass/bottle/gin=5, /obj/item/reagent_containers/cup/glass/bottle/vodka=5, /obj/item/reagent_containers/cup/glass/bottle/tequila=5, /obj/item/reagent_containers/cup/glass/bottle/rum=5, /obj/item/reagent_containers/cup/glass/bottle/vermouth=5, /obj/item/reagent_containers/cup/glass/bottle/cognac=5, /obj/item/reagent_containers/cup/glass/bottle/wine=5, /obj/item/reagent_containers/cup/glass/bottle/kahlua=5, /obj/item/reagent_containers/cup/glass/bottle/amaretto=5, /obj/item/reagent_containers/cup/glass/bottle/hcider=5, /obj/item/reagent_containers/cup/glass/bottle/absinthe=5, /obj/item/reagent_containers/cup/glass/bottle/sake=5, /obj/item/reagent_containers/cup/glass/bottle/grappa=5, /obj/item/reagent_containers/cup/glass/bottle/applejack=5, /obj/item/reagent_containers/cup/glass/bottle/wine_voltaic=5, /obj/item/reagent_containers/cup/bottle/ethanol=2, /obj/item/reagent_containers/cup/glass/bottle/fernet=2, /obj/item/reagent_containers/cup/glass/bottle/champagne=2, /obj/item/reagent_containers/cup/glass/bottle/absinthe/premium=2, /obj/item/reagent_containers/cup/glass/bottle/goldschlager=2, /obj/item/reagent_containers/cup/glass/bottle/patron=1, /obj/item/reagent_containers/cup/glass/bottle/kong=1, /obj/item/reagent_containers/cup/glass/bottle/lizardwine=1, /obj/item/reagent_containers/cup/glass/bottle/vodka/badminka=1, /obj/item/reagent_containers/cup/glass/bottle/trappist=1); spawn_random_offset = 2 }, /turf/open/floor/carpet/cyan, /area/awaymission/museum/mothroachvoid) "qw" = ( /obj/item/flashlight/flare{ - start_on = 1; - icon_state = "flare-on" + icon_state = "flare-on"; + start_on = 1 }, /obj/structure/table, /obj/effect/decal/cleanable/dirt/dust, @@ -1822,6 +2031,10 @@ /obj/effect/decal/cleanable/dirt/dust, /turf/open/floor/engine, /area/awaymission/museum) +"qK" = ( +/obj/machinery/vending/hotdog/museum, +/turf/open/floor/iron/cafeteria, +/area/awaymission/museum/cafeteria) "qL" = ( /obj/effect/turf_decal/tile/neutral/opposingcorners, /obj/effect/turf_decal/siding/dark_blue{ @@ -1879,8 +2092,8 @@ /area/awaymission/museum) "qY" = ( /obj/machinery/power/shuttle_engine/heater{ - dir = 4; - opacity = 1 + opacity = 1; + dir = 4 }, /obj/structure/window/reinforced/spawner/directional/west, /turf/open/indestructible/plating, @@ -1909,22 +2122,29 @@ /turf/open/floor/carpet/executive, /area/awaymission/museum) "rq" = ( +/mob/living/basic/statue/mannequin/suspicious, /obj/effect/decal/cleanable/blood/old, /obj/effect/gibspawner/human, /obj/effect/gibspawner/human, /obj/effect/gibspawner/human, /obj/effect/gibspawner/human, -/mob/living/basic/statue/mannequin/suspicious, /turf/open/floor/iron, /area/awaymission/museum) "rr" = ( /turf/open/floor/wood/tile, /area/awaymission/museum) +"ry" = ( +/obj/machinery/door/airlock{ + name = "Restroom Cabin 6"; + id_tag = "museum_toilet6" + }, +/turf/open/floor/iron/white/small, +/area/awaymission/museum) "rA" = ( +/mob/living/basic/mothroach, /obj/structure/chair/comfy/beige{ dir = 8 }, -/mob/living/basic/mothroach, /obj/effect/mapping_helpers/mob_buckler, /turf/open/floor/wood/large, /area/awaymission/museum) @@ -1964,13 +2184,17 @@ dir = 1 }, /obj/structure/railing/corner/end, +/obj/structure/fluff/wallsign/directional/south{ + name = "Cafeteria"; + dir = 4 + }, /turf/open/floor/iron/dark, /area/awaymission/museum) "rU" = ( /mob/living/basic/statue/mannequin{ + name = "Michael Trasen"; dir = 4; - held_item = /obj/item/wrench; - name = "Michael Trasen" + held_item = /obj/item/wrench }, /obj/structure/sign/flag/nanotrasen/directional/south, /obj/machinery/light/small/dim/directional/west, @@ -1997,9 +2221,9 @@ /turf/open/floor/engine, /area/awaymission/museum) "rY" = ( +/mob/living/basic/mouse/rat, /obj/machinery/light/small/broken/directional/north, /obj/effect/decal/cleanable/dirt/dust, -/mob/living/basic/mouse/rat, /turf/open/floor/iron/dark/textured_large, /area/awaymission/museum) "sd" = ( @@ -2110,13 +2334,20 @@ /obj/effect/decal/cleanable/dirt/dust, /turf/open/floor/iron/dark, /area/awaymission/museum) +"ta" = ( +/obj/machinery/door/airlock{ + name = "Restroom Cabin 5"; + id_tag = "museum_toilet5" + }, +/turf/open/floor/iron/white/small, +/area/awaymission/museum) "tc" = ( +/mob/living/basic/mothroach, /obj/structure/lattice/catwalk/mining, /obj/structure/railing{ dir = 6 }, /obj/structure/chair, -/mob/living/basic/mothroach, /obj/effect/mapping_helpers/mob_buckler, /turf/open/misc/grass, /area/awaymission/museum/mothroachvoid) @@ -2136,15 +2367,15 @@ /turf/open/floor/holofloor/asteroid, /area/awaymission/museum) "tj" = ( +/mob/living/basic/statue/mannequin{ + dir = 1; + held_item = /obj/item/wrench; + hat = /obj/item/clothing/head/utility/hardhat + }, /obj/effect/turf_decal/sand/plating, /obj/effect/turf_decal/stripes/asteroid/line{ dir = 1 }, -/mob/living/basic/statue/mannequin{ - dir = 1; - hat = /obj/item/clothing/head/utility/hardhat; - held_item = /obj/item/wrench - }, /turf/open/indestructible/plating, /area/awaymission/museum) "tk" = ( @@ -2185,7 +2416,7 @@ "tx" = ( /obj/structure/table/wood, /obj/effect/spawner/random/food_or_drink/booze{ - loot = list(/obj/item/reagent_containers/cup/glass/bottle/beer = 10, /obj/item/reagent_containers/cup/glass/bottle/ale = 10, /obj/item/reagent_containers/cup/glass/bottle/beer/light = 5, /obj/item/reagent_containers/cup/glass/bottle/maltliquor = 5, /obj/item/reagent_containers/cup/glass/bottle/whiskey = 5, /obj/item/reagent_containers/cup/glass/bottle/gin = 5, /obj/item/reagent_containers/cup/glass/bottle/vodka = 5, /obj/item/reagent_containers/cup/glass/bottle/tequila = 5, /obj/item/reagent_containers/cup/glass/bottle/rum = 5, /obj/item/reagent_containers/cup/glass/bottle/vermouth = 5, /obj/item/reagent_containers/cup/glass/bottle/cognac = 5, /obj/item/reagent_containers/cup/glass/bottle/wine = 5, /obj/item/reagent_containers/cup/glass/bottle/kahlua = 5, /obj/item/reagent_containers/cup/glass/bottle/amaretto = 5, /obj/item/reagent_containers/cup/glass/bottle/hcider = 5, /obj/item/reagent_containers/cup/glass/bottle/absinthe = 5, /obj/item/reagent_containers/cup/glass/bottle/sake = 5, /obj/item/reagent_containers/cup/glass/bottle/grappa = 5, /obj/item/reagent_containers/cup/glass/bottle/applejack = 5, /obj/item/reagent_containers/cup/glass/bottle/wine_voltaic = 5, /obj/item/reagent_containers/cup/bottle/ethanol = 2, /obj/item/reagent_containers/cup/glass/bottle/fernet = 2, /obj/item/reagent_containers/cup/glass/bottle/champagne = 2, /obj/item/reagent_containers/cup/glass/bottle/absinthe/premium = 2, /obj/item/reagent_containers/cup/glass/bottle/goldschlager = 2, /obj/item/reagent_containers/cup/glass/bottle/patron = 1, /obj/item/reagent_containers/cup/glass/bottle/kong = 1, /obj/item/reagent_containers/cup/glass/bottle/lizardwine = 1, /obj/item/reagent_containers/cup/glass/bottle/vodka/badminka = 1, /obj/item/reagent_containers/cup/glass/bottle/trappist = 1); + loot = list(/obj/item/reagent_containers/cup/glass/bottle/beer=10, /obj/item/reagent_containers/cup/glass/bottle/ale=10, /obj/item/reagent_containers/cup/glass/bottle/beer/light=5, /obj/item/reagent_containers/cup/glass/bottle/maltliquor=5, /obj/item/reagent_containers/cup/glass/bottle/whiskey=5, /obj/item/reagent_containers/cup/glass/bottle/gin=5, /obj/item/reagent_containers/cup/glass/bottle/vodka=5, /obj/item/reagent_containers/cup/glass/bottle/tequila=5, /obj/item/reagent_containers/cup/glass/bottle/rum=5, /obj/item/reagent_containers/cup/glass/bottle/vermouth=5, /obj/item/reagent_containers/cup/glass/bottle/cognac=5, /obj/item/reagent_containers/cup/glass/bottle/wine=5, /obj/item/reagent_containers/cup/glass/bottle/kahlua=5, /obj/item/reagent_containers/cup/glass/bottle/amaretto=5, /obj/item/reagent_containers/cup/glass/bottle/hcider=5, /obj/item/reagent_containers/cup/glass/bottle/absinthe=5, /obj/item/reagent_containers/cup/glass/bottle/sake=5, /obj/item/reagent_containers/cup/glass/bottle/grappa=5, /obj/item/reagent_containers/cup/glass/bottle/applejack=5, /obj/item/reagent_containers/cup/glass/bottle/wine_voltaic=5, /obj/item/reagent_containers/cup/bottle/ethanol=2, /obj/item/reagent_containers/cup/glass/bottle/fernet=2, /obj/item/reagent_containers/cup/glass/bottle/champagne=2, /obj/item/reagent_containers/cup/glass/bottle/absinthe/premium=2, /obj/item/reagent_containers/cup/glass/bottle/goldschlager=2, /obj/item/reagent_containers/cup/glass/bottle/patron=1, /obj/item/reagent_containers/cup/glass/bottle/kong=1, /obj/item/reagent_containers/cup/glass/bottle/lizardwine=1, /obj/item/reagent_containers/cup/glass/bottle/vodka/badminka=1, /obj/item/reagent_containers/cup/glass/bottle/trappist=1); spawn_random_offset = 2 }, /turf/open/floor/wood/tile, @@ -2193,9 +2424,9 @@ "ty" = ( /obj/structure/table, /obj/item/clothing/gloves/color/yellow{ - siemens_coefficient = 10; name = "fake stungloves"; - desc = "A crude replica of stungloves. Essentially gloves wrapped with wire. Extremely unsafe." + desc = "A crude replica of stungloves. Essentially gloves wrapped with wire. Extremely unsafe."; + siemens_coefficient = 10 }, /obj/machinery/light/floor, /turf/open/floor/iron, @@ -2293,6 +2524,13 @@ dir = 2 }, /area/awaymission/museum/mothroachvoid) +"um" = ( +/obj/structure/window/reinforced/spawner/directional/east, +/obj/structure/sign/warning/fire/directional/west, +/obj/structure/tank_holder/extinguisher/anti, +/obj/effect/decal/cleanable/dirt/dust, +/turf/open/floor/iron/white/small, +/area/awaymission/museum) "up" = ( /obj/effect/turf_decal/siding/wood{ dir = 4 @@ -2302,6 +2540,21 @@ }, /turf/open/floor/iron/showroomfloor, /area/awaymission/museum) +"us" = ( +/obj/machinery/door/airlock{ + name = "Restroom Cabin 2"; + id_tag = "museum_toilet2" + }, +/turf/open/floor/iron, +/area/awaymission/museum) +"ut" = ( +/obj/machinery/light/very_dim/directional/north, +/obj/effect/decal/cleanable/dirt/dust, +/obj/structure/fluff/fake_vent, +/obj/structure/mop_bucket, +/obj/effect/decal/cleanable/cobweb/cobweb2, +/turf/open/floor/iron/white/small, +/area/awaymission/museum) "uu" = ( /obj/structure/rack, /obj/effect/spawner/random/engineering/material, @@ -2315,6 +2568,10 @@ }, /turf/open/floor/grass, /area/awaymission/museum) +"uH" = ( +/obj/structure/sign/clock/directional/north, +/turf/open/floor/iron/cafeteria, +/area/awaymission/museum/cafeteria) "uM" = ( /obj/structure/fluff/fake_camera{ dir = 10 @@ -2345,8 +2602,8 @@ "vc" = ( /obj/effect/turf_decal/tile/neutral/fourcorners, /obj/structure/sign/painting/large{ - persistence_id = "museumgate_big"; - dir = 1 + dir = 1; + persistence_id = "museumgate_big" }, /obj/effect/decal/cleanable/dirt/dust, /turf/open/floor/iron/dark, @@ -2418,6 +2675,11 @@ /obj/structure/filingcabinet, /turf/open/floor/iron, /area/awaymission/museum) +"vG" = ( +/turf/closed/indestructible/fakedoor{ + name = "Kitchen" + }, +/area/awaymission/museum/cafeteria) "vM" = ( /mob/living/basic/statue/mannequin{ dir = 1; @@ -2448,6 +2710,16 @@ /obj/effect/turf_decal/siding/dark_blue, /turf/open/floor/mineral/titanium/blue, /area/awaymission/museum) +"wg" = ( +/obj/machinery/door/airlock{ + name = "Restroom Cabin 3" + }, +/obj/effect/mapping_helpers/airlock/locked, +/obj/effect/mapping_helpers/airlock_note_placer{ + note_info = "I'VE WORKED HERE FOR 7 YEARS! JUST TO BE REPLACED BY A VENDING MACHINE?! YOU KNOW WHAT? FUCK YOU, I'VE LOCKED DOWN THE CAFETERIA AND WON'T BE COMING OUT 'TILL YOU GIVE ME MY JOB BACK!" + }, +/turf/open/floor/iron, +/area/awaymission/museum) "wh" = ( /obj/structure/broken_flooring/corner/always_floorplane/directional/west, /obj/structure/lattice, @@ -2456,7 +2728,7 @@ "wi" = ( /obj/machinery/door/poddoor/shutters/indestructible{ dir = 8; - id = "nothing" + id = "museum_secret" }, /turf/open/floor/iron, /area/awaymission/museum) @@ -2526,8 +2798,8 @@ "wN" = ( /obj/effect/turf_decal/tile/neutral/fourcorners, /obj/structure/sign/painting/large{ - persistence_id = "museumgate_big"; - dir = 1 + dir = 1; + persistence_id = "museumgate_big" }, /turf/open/floor/iron/dark, /area/awaymission/museum) @@ -2535,6 +2807,13 @@ /obj/item/kirbyplants/random, /turf/open/floor/wood/large, /area/awaymission/museum) +"wV" = ( +/obj/effect/turf_decal/siding/dark_blue{ + dir = 1 + }, +/obj/effect/turf_decal/tile/neutral/opposingcorners, +/turf/open/floor/iron/dark, +/area/awaymission/museum) "wZ" = ( /turf/open/misc/beach/coast{ dir = 1 @@ -2558,8 +2837,8 @@ /obj/structure/table/reinforced, /obj/structure/window/spawner/directional/west, /obj/effect/spawner/random/bureaucracy/paper{ - spawn_random_offset = 7; - spawn_loot_count = 8 + spawn_loot_count = 8; + spawn_random_offset = 7 }, /obj/effect/decal/cleanable/dirt/dust, /turf/open/floor/iron/white, @@ -2575,8 +2854,8 @@ "xg" = ( /obj/structure/table/reinforced, /obj/item/circuitboard{ - icon_state = "bluespacearray"; - name = "fancy replica tech" + name = "fancy replica tech"; + icon_state = "bluespacearray" }, /turf/open/floor/iron/smooth_large, /area/awaymission/museum) @@ -2599,6 +2878,10 @@ }, /turf/open/misc/beach/sand, /area/awaymission/museum/mothroachvoid) +"xp" = ( +/obj/structure/table, +/turf/open/floor/iron/cafeteria, +/area/awaymission/museum/cafeteria) "xr" = ( /obj/effect/decal/cleanable/dirt/dust, /obj/structure/closet/crate/freezer/food, @@ -2668,6 +2951,11 @@ }, /turf/open/floor/iron/dark, /area/awaymission/museum) +"xO" = ( +/obj/structure/table, +/obj/item/reagent_containers/cup/soda_cans/canned_laughter, +/turf/open/floor/iron/cafeteria, +/area/awaymission/museum/cafeteria) "xP" = ( /obj/structure/closet/crate/cardboard, /obj/item/storage/toolbox/artistic, @@ -2704,10 +2992,10 @@ /turf/open/chasm/true/no_smooth, /area/awaymission/museum) "yi" = ( +/mob/living/basic/mothroach, /obj/structure/chair/comfy/beige{ dir = 1 }, -/mob/living/basic/mothroach, /obj/effect/mapping_helpers/mob_buckler, /turf/open/floor/wood/large, /area/awaymission/museum) @@ -2731,9 +3019,9 @@ /turf/open/floor/holofloor/hyperspace/ns, /area/awaymission/museum) "yr" = ( +/mob/living/basic/mothroach, /obj/structure/chair/comfy, /obj/effect/mapping_helpers/mob_buckler, -/mob/living/basic/mothroach, /turf/open/floor/wood/large, /area/awaymission/museum) "yu" = ( @@ -2855,14 +3143,14 @@ /turf/closed/indestructible/rock, /area/awaymission/museum) "zG" = ( -/obj/structure/chair/office{ - dir = 8 - }, -/obj/effect/turf_decal/siding/red, /mob/living/basic/statue/mannequin{ dir = 8; hat = /obj/item/clothing/head/fedora }, +/obj/structure/chair/office{ + dir = 8 + }, +/obj/effect/turf_decal/siding/red, /obj/effect/decal/cleanable/dirt/dust, /turf/open/floor/iron/smooth_half, /area/awaymission/museum) @@ -2891,13 +3179,13 @@ pixel_y = 12 }, /obj/item/stamp/granted{ - pixel_y = 12; - pixel_x = 8 + pixel_x = 8; + pixel_y = 12 }, /obj/effect/spawner/random/bureaucracy/paper{ - spawn_random_offset = 12; + spawn_loot_count = 8; spawn_scatter_radius = 1; - spawn_loot_count = 8 + spawn_random_offset = 12 }, /turf/open/floor/iron, /area/awaymission/museum) @@ -3043,8 +3331,8 @@ teleport_y_offset = -30 }, /turf/open/mirage{ - target_turf_y = -29; - dir = 1 + dir = 1; + target_turf_y = -29 }, /area/awaymission/museum) "AP" = ( @@ -3054,6 +3342,13 @@ /obj/effect/decal/cleanable/dirt/dust, /turf/open/indestructible/plating, /area/awaymission/museum) +"AQ" = ( +/obj/machinery/door/airlock{ + name = "Restroom Cabin 4"; + id_tag = "museum_toilet4" + }, +/turf/open/floor/iron/white/small, +/area/awaymission/museum) "AR" = ( /obj/structure/railing{ dir = 8 @@ -3217,9 +3512,9 @@ "Cy" = ( /obj/structure/table/wood, /obj/effect/spawner/random/food_or_drink/booze{ - loot = list(/obj/item/reagent_containers/cup/glass/bottle/beer = 10, /obj/item/reagent_containers/cup/glass/bottle/ale = 10, /obj/item/reagent_containers/cup/glass/bottle/beer/light = 5, /obj/item/reagent_containers/cup/glass/bottle/maltliquor = 5, /obj/item/reagent_containers/cup/glass/bottle/whiskey = 5, /obj/item/reagent_containers/cup/glass/bottle/gin = 5, /obj/item/reagent_containers/cup/glass/bottle/vodka = 5, /obj/item/reagent_containers/cup/glass/bottle/tequila = 5, /obj/item/reagent_containers/cup/glass/bottle/rum = 5, /obj/item/reagent_containers/cup/glass/bottle/vermouth = 5, /obj/item/reagent_containers/cup/glass/bottle/cognac = 5, /obj/item/reagent_containers/cup/glass/bottle/wine = 5, /obj/item/reagent_containers/cup/glass/bottle/kahlua = 5, /obj/item/reagent_containers/cup/glass/bottle/amaretto = 5, /obj/item/reagent_containers/cup/glass/bottle/hcider = 5, /obj/item/reagent_containers/cup/glass/bottle/absinthe = 5, /obj/item/reagent_containers/cup/glass/bottle/sake = 5, /obj/item/reagent_containers/cup/glass/bottle/grappa = 5, /obj/item/reagent_containers/cup/glass/bottle/applejack = 5, /obj/item/reagent_containers/cup/glass/bottle/wine_voltaic = 5, /obj/item/reagent_containers/cup/bottle/ethanol = 2, /obj/item/reagent_containers/cup/glass/bottle/fernet = 2, /obj/item/reagent_containers/cup/glass/bottle/champagne = 2, /obj/item/reagent_containers/cup/glass/bottle/absinthe/premium = 2, /obj/item/reagent_containers/cup/glass/bottle/goldschlager = 2, /obj/item/reagent_containers/cup/glass/bottle/patron = 1, /obj/item/reagent_containers/cup/glass/bottle/kong = 1, /obj/item/reagent_containers/cup/glass/bottle/lizardwine = 1, /obj/item/reagent_containers/cup/glass/bottle/vodka/badminka = 1, /obj/item/reagent_containers/cup/glass/bottle/trappist = 1); - spawn_random_offset = 2; - spawn_loot_count = 2 + loot = list(/obj/item/reagent_containers/cup/glass/bottle/beer=10, /obj/item/reagent_containers/cup/glass/bottle/ale=10, /obj/item/reagent_containers/cup/glass/bottle/beer/light=5, /obj/item/reagent_containers/cup/glass/bottle/maltliquor=5, /obj/item/reagent_containers/cup/glass/bottle/whiskey=5, /obj/item/reagent_containers/cup/glass/bottle/gin=5, /obj/item/reagent_containers/cup/glass/bottle/vodka=5, /obj/item/reagent_containers/cup/glass/bottle/tequila=5, /obj/item/reagent_containers/cup/glass/bottle/rum=5, /obj/item/reagent_containers/cup/glass/bottle/vermouth=5, /obj/item/reagent_containers/cup/glass/bottle/cognac=5, /obj/item/reagent_containers/cup/glass/bottle/wine=5, /obj/item/reagent_containers/cup/glass/bottle/kahlua=5, /obj/item/reagent_containers/cup/glass/bottle/amaretto=5, /obj/item/reagent_containers/cup/glass/bottle/hcider=5, /obj/item/reagent_containers/cup/glass/bottle/absinthe=5, /obj/item/reagent_containers/cup/glass/bottle/sake=5, /obj/item/reagent_containers/cup/glass/bottle/grappa=5, /obj/item/reagent_containers/cup/glass/bottle/applejack=5, /obj/item/reagent_containers/cup/glass/bottle/wine_voltaic=5, /obj/item/reagent_containers/cup/bottle/ethanol=2, /obj/item/reagent_containers/cup/glass/bottle/fernet=2, /obj/item/reagent_containers/cup/glass/bottle/champagne=2, /obj/item/reagent_containers/cup/glass/bottle/absinthe/premium=2, /obj/item/reagent_containers/cup/glass/bottle/goldschlager=2, /obj/item/reagent_containers/cup/glass/bottle/patron=1, /obj/item/reagent_containers/cup/glass/bottle/kong=1, /obj/item/reagent_containers/cup/glass/bottle/lizardwine=1, /obj/item/reagent_containers/cup/glass/bottle/vodka/badminka=1, /obj/item/reagent_containers/cup/glass/bottle/trappist=1); + spawn_loot_count = 2; + spawn_random_offset = 2 }, /obj/machinery/light/warm/directional/west, /turf/open/floor/wood/large, @@ -3255,6 +3550,11 @@ }, /turf/open/floor/iron/dark, /area/awaymission/museum) +"CG" = ( +/obj/structure/mirror/directional/east, +/obj/structure/sink/directional/west, +/turf/open/floor/iron/white/small, +/area/awaymission/museum) "CI" = ( /obj/effect/turf_decal/caution, /obj/effect/decal/cleanable/dirt/dust, @@ -3293,6 +3593,18 @@ }, /turf/open/floor/iron/dark, /area/awaymission/museum) +"Db" = ( +/obj/item/maneki_neko{ + pixel_y = 4 + }, +/obj/structure/table, +/obj/machinery/status_display/random_message{ + pixel_y = 32; + firstline_to_secondline = list(ACCEPTING="DONATIONS") + }, +/obj/structure/fluff/fake_vent, +/turf/open/floor/iron, +/area/awaymission/museum/cafeteria) "De" = ( /obj/effect/oneway{ dir = 8 @@ -3383,6 +3695,11 @@ /obj/machinery/light/floor, /turf/open/floor/iron/dark, /area/awaymission/museum) +"DX" = ( +/obj/structure/reagent_dispensers/water_cooler, +/obj/machinery/light/warm/directional/west, +/turf/open/floor/iron/cafeteria, +/area/awaymission/museum/cafeteria) "DY" = ( /turf/closed/indestructible/reinforced/titanium, /area/awaymission/museum) @@ -3400,8 +3717,8 @@ /obj/machinery/computer/old{ name = "replica computer"; dir = 4; - icon_keyboard = "rd_key"; - icon_screen = "rdcomp" + icon_screen = "rdcomp"; + icon_keyboard = "rd_key" }, /turf/open/floor/iron/smooth_large, /area/awaymission/museum) @@ -3421,8 +3738,8 @@ dir = 4 }, /obj/structure/fluff/wallsign/directional/south{ - dir = 4; - name = "Oddities" + name = "Oddities"; + dir = 4 }, /turf/open/floor/iron/dark, /area/awaymission/museum) @@ -3435,12 +3752,17 @@ /turf/open/indestructible/plating, /area/awaymission/museum) "Er" = ( -/obj/structure/chair/comfy/beige, /mob/living/basic/mothroach, +/obj/structure/chair/comfy/beige, /obj/effect/mapping_helpers/mob_buckler, /obj/machinery/light/warm/directional/west, /turf/open/floor/wood/large, /area/awaymission/museum) +"Es" = ( +/obj/structure/table, +/obj/effect/spawner/random/food_or_drink/donkpockets, +/turf/open/floor/iron/cafeteria, +/area/awaymission/museum/cafeteria) "EA" = ( /obj/machinery/door/airlock/shuttle/glass, /obj/effect/turf_decal/siding/dark_blue, @@ -3460,9 +3782,9 @@ /area/awaymission/museum) "EG" = ( /obj/item/flashlight/flare{ - start_on = 1; icon_state = "flare-on"; - light_range = 4 + light_range = 4; + start_on = 1 }, /obj/effect/decal/cleanable/dirt/dust, /turf/open/indestructible/plating, @@ -3476,9 +3798,9 @@ "EM" = ( /obj/structure/table/wood, /obj/effect/spawner/random/food_or_drink/booze{ - loot = list(/obj/item/reagent_containers/cup/glass/bottle/beer = 10, /obj/item/reagent_containers/cup/glass/bottle/ale = 10, /obj/item/reagent_containers/cup/glass/bottle/beer/light = 5, /obj/item/reagent_containers/cup/glass/bottle/maltliquor = 5, /obj/item/reagent_containers/cup/glass/bottle/whiskey = 5, /obj/item/reagent_containers/cup/glass/bottle/gin = 5, /obj/item/reagent_containers/cup/glass/bottle/vodka = 5, /obj/item/reagent_containers/cup/glass/bottle/tequila = 5, /obj/item/reagent_containers/cup/glass/bottle/rum = 5, /obj/item/reagent_containers/cup/glass/bottle/vermouth = 5, /obj/item/reagent_containers/cup/glass/bottle/cognac = 5, /obj/item/reagent_containers/cup/glass/bottle/wine = 5, /obj/item/reagent_containers/cup/glass/bottle/kahlua = 5, /obj/item/reagent_containers/cup/glass/bottle/amaretto = 5, /obj/item/reagent_containers/cup/glass/bottle/hcider = 5, /obj/item/reagent_containers/cup/glass/bottle/absinthe = 5, /obj/item/reagent_containers/cup/glass/bottle/sake = 5, /obj/item/reagent_containers/cup/glass/bottle/grappa = 5, /obj/item/reagent_containers/cup/glass/bottle/applejack = 5, /obj/item/reagent_containers/cup/glass/bottle/wine_voltaic = 5, /obj/item/reagent_containers/cup/bottle/ethanol = 2, /obj/item/reagent_containers/cup/glass/bottle/fernet = 2, /obj/item/reagent_containers/cup/glass/bottle/champagne = 2, /obj/item/reagent_containers/cup/glass/bottle/absinthe/premium = 2, /obj/item/reagent_containers/cup/glass/bottle/goldschlager = 2, /obj/item/reagent_containers/cup/glass/bottle/patron = 1, /obj/item/reagent_containers/cup/glass/bottle/kong = 1, /obj/item/reagent_containers/cup/glass/bottle/lizardwine = 1, /obj/item/reagent_containers/cup/glass/bottle/vodka/badminka = 1, /obj/item/reagent_containers/cup/glass/bottle/trappist = 1); - spawn_random_offset = 2; - spawn_loot_count = 2 + loot = list(/obj/item/reagent_containers/cup/glass/bottle/beer=10, /obj/item/reagent_containers/cup/glass/bottle/ale=10, /obj/item/reagent_containers/cup/glass/bottle/beer/light=5, /obj/item/reagent_containers/cup/glass/bottle/maltliquor=5, /obj/item/reagent_containers/cup/glass/bottle/whiskey=5, /obj/item/reagent_containers/cup/glass/bottle/gin=5, /obj/item/reagent_containers/cup/glass/bottle/vodka=5, /obj/item/reagent_containers/cup/glass/bottle/tequila=5, /obj/item/reagent_containers/cup/glass/bottle/rum=5, /obj/item/reagent_containers/cup/glass/bottle/vermouth=5, /obj/item/reagent_containers/cup/glass/bottle/cognac=5, /obj/item/reagent_containers/cup/glass/bottle/wine=5, /obj/item/reagent_containers/cup/glass/bottle/kahlua=5, /obj/item/reagent_containers/cup/glass/bottle/amaretto=5, /obj/item/reagent_containers/cup/glass/bottle/hcider=5, /obj/item/reagent_containers/cup/glass/bottle/absinthe=5, /obj/item/reagent_containers/cup/glass/bottle/sake=5, /obj/item/reagent_containers/cup/glass/bottle/grappa=5, /obj/item/reagent_containers/cup/glass/bottle/applejack=5, /obj/item/reagent_containers/cup/glass/bottle/wine_voltaic=5, /obj/item/reagent_containers/cup/bottle/ethanol=2, /obj/item/reagent_containers/cup/glass/bottle/fernet=2, /obj/item/reagent_containers/cup/glass/bottle/champagne=2, /obj/item/reagent_containers/cup/glass/bottle/absinthe/premium=2, /obj/item/reagent_containers/cup/glass/bottle/goldschlager=2, /obj/item/reagent_containers/cup/glass/bottle/patron=1, /obj/item/reagent_containers/cup/glass/bottle/kong=1, /obj/item/reagent_containers/cup/glass/bottle/lizardwine=1, /obj/item/reagent_containers/cup/glass/bottle/vodka/badminka=1, /obj/item/reagent_containers/cup/glass/bottle/trappist=1); + spawn_loot_count = 2; + spawn_random_offset = 2 }, /turf/open/floor/wood/large, /area/awaymission/museum) @@ -3502,15 +3824,15 @@ /turf/open/floor/circuit/green, /area/awaymission/museum) "ET" = ( +/mob/living/basic/statue/mannequin{ + dir = 1 + }, /obj/structure/chair/stool/directional/north, /obj/effect/turf_decal/tile/green/opposingcorners, /obj/effect/decal/cleanable/dirt/dust, /obj/effect/turf_decal/siding/green{ dir = 1 }, -/mob/living/basic/statue/mannequin{ - dir = 1 - }, /turf/open/floor/iron, /area/awaymission/museum) "EU" = ( @@ -3520,8 +3842,8 @@ dir = 4 }, /obj/structure/fluff/wallsign/directional/north{ - dir = 4; - name = "Oddities" + name = "Oddities"; + dir = 4 }, /turf/open/floor/iron/dark, /area/awaymission/museum) @@ -3594,8 +3916,8 @@ /area/awaymission/museum) "Fw" = ( /obj/effect/decal/cleanable/blood/tracks{ - should_dry = 0; - name = "replica blood" + name = "replica blood"; + should_dry = 0 }, /obj/effect/mapping_helpers/burnt_floor, /obj/effect/decal/cleanable/dirt/dust, @@ -3604,8 +3926,8 @@ "FA" = ( /obj/structure/table/reinforced, /obj/item/circuitboard{ - icon_state = "printer"; - name = "fancy replica tech" + name = "fancy replica tech"; + icon_state = "printer" }, /turf/open/floor/iron/smooth_large, /area/awaymission/museum) @@ -3642,6 +3964,32 @@ /obj/structure/sign/departments/restroom/directional/south, /turf/open/floor/wood/large, /area/awaymission/museum) +"FO" = ( +/obj/effect/decal/cleanable/crayon/puzzle/pin{ + puzzle_id = "museum_r_wing_puzzle" + }, +/turf/closed/indestructible/reinforced, +/area/awaymission/museum) +"FU" = ( +/obj/effect/turf_decal/siding/dark_blue{ + dir = 1 + }, +/obj/effect/turf_decal/tile/neutral/opposingcorners, +/obj/structure/fluff/wallsign/directional/south{ + name = "Cafeteria"; + dir = 4 + }, +/turf/open/floor/iron/dark, +/area/awaymission/museum) +"FY" = ( +/obj/structure/chair/sofa/bench/left, +/turf/open/floor/iron/cafeteria, +/area/awaymission/museum/cafeteria) +"Ga" = ( +/obj/effect/decal/cleanable/dirt/dust, +/obj/machinery/door/airlock/grunge, +/turf/open/floor/iron/white/small, +/area/awaymission/museum) "Gh" = ( /obj/effect/turf_decal/tile/neutral/opposingcorners, /obj/effect/turf_decal/siding/dark_blue{ @@ -3655,6 +4003,9 @@ /obj/structure/closet/crate/miningcar, /turf/open/floor/tram/plate, /area/awaymission/museum) +"Gn" = ( +/turf/open/floor/iron/white/small, +/area/awaymission/museum) "Gv" = ( /obj/effect/decal/cleanable/crayon{ icon_state = "l"; @@ -3675,20 +4026,27 @@ /obj/effect/turf_decal/bot, /turf/open/floor/iron, /area/awaymission/museum) +"GB" = ( +/obj/structure/table, +/obj/item/reagent_containers/cup/soda_cans/thirteenloko{ + pixel_y = 7 + }, +/turf/open/floor/iron/cafeteria, +/area/awaymission/museum/cafeteria) "GE" = ( /obj/structure/plaque/static_plaque/golden/commission/meta, /turf/open/floor/mineral/gold, /area/awaymission/museum) "GG" = ( +/mob/living/basic/statue/mannequin{ + dir = 4 + }, /obj/structure/chair/office{ dir = 4 }, /obj/effect/turf_decal/siding/wood{ dir = 1 }, -/mob/living/basic/statue/mannequin{ - dir = 4 - }, /turf/open/floor/wood/tile, /area/awaymission/museum) "GO" = ( @@ -3762,8 +4120,8 @@ /area/awaymission/museum) "Hn" = ( /mob/living/basic/statue/mannequin{ - hat = /obj/item/clothing/head/costume/kitty; - dir = 8 + dir = 8; + hat = /obj/item/clothing/head/costume/kitty }, /obj/effect/turf_decal/trimline/yellow, /obj/effect/turf_decal/trimline/yellow/corner{ @@ -3797,7 +4155,7 @@ /area/awaymission/museum) "HA" = ( /obj/machinery/status_display/random_message{ - firstline_to_secondline = list("NO" = "LITTERING","YOU ARE" = "BEING WATCHED", "DO NOT TOUCH" = "THE EXHIBITS") + firstline_to_secondline = list(NO="LITTERING", "YOU ARE"="BEING WATCHED", "DO NOT TOUCH"="THE EXHIBITS") }, /turf/closed/indestructible/reinforced, /area/awaymission/museum) @@ -3806,7 +4164,7 @@ /obj/effect/turf_decal/siding/dark_blue, /obj/machinery/door/poddoor/shutters/indestructible{ dir = 8; - id = "nothing" + id = "museum_secret" }, /turf/open/floor/iron/dark, /area/awaymission/museum) @@ -3838,6 +4196,9 @@ "HP" = ( /turf/open/floor/iron/freezer, /area/awaymission/museum) +"HQ" = ( +/turf/open/floor/iron/cafeteria, +/area/awaymission/museum/cafeteria) "HU" = ( /obj/structure/railing{ dir = 4 @@ -3848,6 +4209,19 @@ /obj/effect/decal/cleanable/dirt/dust, /turf/open/indestructible/plating, /area/awaymission/museum) +"HW" = ( +/obj/machinery/button/door/directional/north{ + name = "Lock Control"; + id = "museum_toilet1"; + specialfunctions = 4; + normaldoorcontrol = 1 + }, +/obj/structure/toilet/museum{ + dir = 4 + }, +/obj/machinery/light/small/dim/directional/west, +/turf/open/floor/iron/white/small, +/area/awaymission/museum) "HY" = ( /obj/machinery/light/floor, /obj/effect/decal/cleanable/dirt/dust, @@ -3857,6 +4231,12 @@ /obj/machinery/light/warm/dim/directional/north, /turf/open/floor/carpet, /area/awaymission/museum) +"Id" = ( +/obj/effect/decal/cleanable/crayon/puzzle/pin{ + puzzle_id = "museum_r_wing_puzzle" + }, +/turf/closed/indestructible/wood, +/area/awaymission/museum) "Ij" = ( /obj/machinery/door/airlock/external, /obj/effect/mapping_helpers/airlock/locked, @@ -3871,6 +4251,9 @@ /obj/structure/holosign/barrier/engineering, /turf/open/chasm/true/no_smooth, /area/awaymission/museum) +"Ir" = ( +/turf/closed/indestructible/fakedoor, +/area/awaymission/museum) "Iu" = ( /turf/open/floor/mineral/titanium/blue, /area/awaymission/museum) @@ -3898,6 +4281,12 @@ /obj/item/food/grilled_beef_gyro, /turf/open/floor/wood/tile, /area/awaymission/museum) +"IG" = ( +/obj/structure/fluff/fake_camera{ + dir = 9 + }, +/turf/open/floor/iron/white/small, +/area/awaymission/museum) "IH" = ( /obj/machinery/portable_atmospherics/canister/water_vapor, /obj/effect/decal/cleanable/dirt/dust, @@ -3914,11 +4303,22 @@ /obj/effect/turf_decal/stripes, /turf/open/floor/iron/smooth_large, /area/awaymission/museum) +"IX" = ( +/mob/living/basic/statue/mannequin{ + name = "cafeteria patron"; + held_item = /obj/item/knife + }, +/obj/structure/chair/sofa/bench{ + dir = 1 + }, +/obj/effect/mapping_helpers/mob_buckler, +/turf/open/floor/iron/cafeteria, +/area/awaymission/museum/cafeteria) "IZ" = ( +/mob/living/basic/mothroach, /obj/structure/chair/comfy/beige{ dir = 4 }, -/mob/living/basic/mothroach, /obj/effect/mapping_helpers/mob_buckler, /turf/open/floor/wood/large, /area/awaymission/museum) @@ -3959,6 +4359,13 @@ /obj/machinery/light/small/dim/directional/west, /turf/open/floor/carpet/executive, /area/awaymission/museum) +"Jl" = ( +/obj/machinery/status_display/random_message{ + pixel_x = 32; + firstline_to_secondline = list(CAFETERIA="YUMMY", CAFETERIA="HOTDOGS", ENJOY="YOUR MEAL") + }, +/turf/open/floor/iron/cafeteria, +/area/awaymission/museum/cafeteria) "Jn" = ( /obj/structure/table/reinforced, /obj/effect/spawner/random/entertainment/toy, @@ -3967,6 +4374,13 @@ /obj/effect/turf_decal/siding/dark_blue, /turf/open/floor/mineral/titanium/blue, /area/awaymission/museum) +"Jp" = ( +/obj/machinery/door/airlock{ + name = "Restroom Cabin 1"; + id_tag = "museum_toilet1" + }, +/turf/open/floor/iron, +/area/awaymission/museum) "Js" = ( /obj/effect/turf_decal/tile/neutral/opposingcorners, /obj/effect/turf_decal/siding/dark_blue{ @@ -4077,11 +4491,24 @@ /turf/open/floor/catwalk_floor, /area/awaymission/museum) "Kx" = ( -/obj/effect/decal/cleanable/dirt/dust, /mob/living/basic/skeleton, +/obj/effect/decal/cleanable/dirt/dust, /obj/effect/spawner/random/maintenance/three, /turf/open/indestructible/plating, /area/awaymission/museum) +"Kz" = ( +/obj/structure/sign/warning/no_smoking/directional/west, +/obj/machinery/computer/terminal/museum{ + name = "extinguisher manual terminal"; + dir = 4; + content = list("Instructions; stand upright; remove safety clip; aim noozle at base of fire... the rest is up to you.") + }, +/turf/open/floor/iron/white/small, +/area/awaymission/museum) +"KB" = ( +/obj/structure/sign/warning/no_smoking/circle/directional/east, +/turf/open/floor/iron/cafeteria, +/area/awaymission/museum/cafeteria) "KI" = ( /turf/open/floor/iron/dark/side{ dir = 10 @@ -4112,7 +4539,7 @@ /area/awaymission/museum) "Lp" = ( /obj/machinery/status_display/random_message{ - firstline_to_secondline = list("NO" = "LITTERING","YOU ARE" = "BEING WATCHED", "DO NOT TOUCH" = "THE EXHIBITS") + firstline_to_secondline = list(NO="LITTERING", "YOU ARE"="BEING WATCHED", "DO NOT TOUCH"="THE EXHIBITS") }, /turf/closed/indestructible/reinforced/titanium/nodiagonal, /area/awaymission/museum) @@ -4162,6 +4589,12 @@ }, /turf/open/floor/iron/dark, /area/awaymission/museum) +"LK" = ( +/obj/structure/table, +/obj/item/piggy_bank/museum, +/obj/machinery/light/warm/directional/north, +/turf/open/floor/iron, +/area/awaymission/museum/cafeteria) "LN" = ( /obj/effect/decal/cleanable/glass/titanium, /turf/open/floor/iron/dark/textured_large, @@ -4197,6 +4630,11 @@ "Ma" = ( /turf/open/chasm/true/no_smooth, /area/awaymission/museum) +"Mb" = ( +/obj/effect/turf_decal/siding/dark_blue, +/obj/effect/turf_decal/tile/neutral/opposingcorners, +/turf/open/floor/iron/dark, +/area/awaymission/museum) "Mg" = ( /obj/structure/plaque/static_plaque/golden/commission/tram, /turf/closed/indestructible/reinforced, @@ -4215,9 +4653,9 @@ /area/awaymission/museum) "Mv" = ( /mob/living/basic/statue/mannequin{ + name = "Michael Trasen"; dir = 4; - held_item = /obj/item/wrench; - name = "Michael Trasen" + held_item = /obj/item/wrench }, /obj/effect/turf_decal/stripes{ dir = 4 @@ -4300,10 +4738,16 @@ /obj/structure/plaque/static_plaque/golden/commission/birdboat, /turf/closed/indestructible/reinforced, /area/awaymission/museum) +"Nn" = ( +/obj/machinery/door/airlock/public{ + name = "Restrooms" + }, +/turf/open/floor/iron/white/small, +/area/awaymission/museum) "Ns" = ( /obj/structure/table/wood, /obj/effect/spawner/random/food_or_drink/booze{ - loot = list(/obj/item/reagent_containers/cup/glass/bottle/beer = 10, /obj/item/reagent_containers/cup/glass/bottle/ale = 10, /obj/item/reagent_containers/cup/glass/bottle/beer/light = 5, /obj/item/reagent_containers/cup/glass/bottle/maltliquor = 5, /obj/item/reagent_containers/cup/glass/bottle/whiskey = 5, /obj/item/reagent_containers/cup/glass/bottle/gin = 5, /obj/item/reagent_containers/cup/glass/bottle/vodka = 5, /obj/item/reagent_containers/cup/glass/bottle/tequila = 5, /obj/item/reagent_containers/cup/glass/bottle/rum = 5, /obj/item/reagent_containers/cup/glass/bottle/vermouth = 5, /obj/item/reagent_containers/cup/glass/bottle/cognac = 5, /obj/item/reagent_containers/cup/glass/bottle/wine = 5, /obj/item/reagent_containers/cup/glass/bottle/kahlua = 5, /obj/item/reagent_containers/cup/glass/bottle/amaretto = 5, /obj/item/reagent_containers/cup/glass/bottle/hcider = 5, /obj/item/reagent_containers/cup/glass/bottle/absinthe = 5, /obj/item/reagent_containers/cup/glass/bottle/sake = 5, /obj/item/reagent_containers/cup/glass/bottle/grappa = 5, /obj/item/reagent_containers/cup/glass/bottle/applejack = 5, /obj/item/reagent_containers/cup/glass/bottle/wine_voltaic = 5, /obj/item/reagent_containers/cup/bottle/ethanol = 2, /obj/item/reagent_containers/cup/glass/bottle/fernet = 2, /obj/item/reagent_containers/cup/glass/bottle/champagne = 2, /obj/item/reagent_containers/cup/glass/bottle/absinthe/premium = 2, /obj/item/reagent_containers/cup/glass/bottle/goldschlager = 2, /obj/item/reagent_containers/cup/glass/bottle/patron = 1, /obj/item/reagent_containers/cup/glass/bottle/kong = 1, /obj/item/reagent_containers/cup/glass/bottle/lizardwine = 1, /obj/item/reagent_containers/cup/glass/bottle/vodka/badminka = 1, /obj/item/reagent_containers/cup/glass/bottle/trappist = 1); + loot = list(/obj/item/reagent_containers/cup/glass/bottle/beer=10, /obj/item/reagent_containers/cup/glass/bottle/ale=10, /obj/item/reagent_containers/cup/glass/bottle/beer/light=5, /obj/item/reagent_containers/cup/glass/bottle/maltliquor=5, /obj/item/reagent_containers/cup/glass/bottle/whiskey=5, /obj/item/reagent_containers/cup/glass/bottle/gin=5, /obj/item/reagent_containers/cup/glass/bottle/vodka=5, /obj/item/reagent_containers/cup/glass/bottle/tequila=5, /obj/item/reagent_containers/cup/glass/bottle/rum=5, /obj/item/reagent_containers/cup/glass/bottle/vermouth=5, /obj/item/reagent_containers/cup/glass/bottle/cognac=5, /obj/item/reagent_containers/cup/glass/bottle/wine=5, /obj/item/reagent_containers/cup/glass/bottle/kahlua=5, /obj/item/reagent_containers/cup/glass/bottle/amaretto=5, /obj/item/reagent_containers/cup/glass/bottle/hcider=5, /obj/item/reagent_containers/cup/glass/bottle/absinthe=5, /obj/item/reagent_containers/cup/glass/bottle/sake=5, /obj/item/reagent_containers/cup/glass/bottle/grappa=5, /obj/item/reagent_containers/cup/glass/bottle/applejack=5, /obj/item/reagent_containers/cup/glass/bottle/wine_voltaic=5, /obj/item/reagent_containers/cup/bottle/ethanol=2, /obj/item/reagent_containers/cup/glass/bottle/fernet=2, /obj/item/reagent_containers/cup/glass/bottle/champagne=2, /obj/item/reagent_containers/cup/glass/bottle/absinthe/premium=2, /obj/item/reagent_containers/cup/glass/bottle/goldschlager=2, /obj/item/reagent_containers/cup/glass/bottle/patron=1, /obj/item/reagent_containers/cup/glass/bottle/kong=1, /obj/item/reagent_containers/cup/glass/bottle/lizardwine=1, /obj/item/reagent_containers/cup/glass/bottle/vodka/badminka=1, /obj/item/reagent_containers/cup/glass/bottle/trappist=1); spawn_random_offset = 2 }, /turf/open/floor/wood/large, @@ -4324,8 +4768,8 @@ /obj/structure/railing, /obj/structure/table, /obj/item/clothing/mask/cigarette/cigar{ - lit = 1; - icon_state = "cigaron" + icon_state = "cigaron"; + lit = 1 }, /turf/open/chasm/true/no_smooth, /area/awaymission/museum) @@ -4431,11 +4875,11 @@ /turf/open/floor/iron, /area/awaymission/museum) "OS" = ( +/mob/living/basic/mothroach, /obj/structure/chair/stool/bar/directional/east{ can_buckle = 1 }, /obj/effect/mapping_helpers/mob_buckler, -/mob/living/basic/mothroach, /turf/open/floor/wood/large, /area/awaymission/museum) "OT" = ( @@ -4481,6 +4925,9 @@ /obj/item/food/kebab/pineapple_skewer, /turf/open/floor/iron/freezer, /area/awaymission/museum) +"Ph" = ( +/turf/closed/indestructible/reinforced, +/area/awaymission/museum/cafeteria) "Pi" = ( /obj/effect/turf_decal/tile/neutral/opposingcorners, /obj/effect/turf_decal/siding/dark_blue/corner{ @@ -4584,8 +5031,8 @@ "PZ" = ( /obj/effect/mapping_helpers/broken_floor, /obj/item/flashlight/flare{ - start_on = 1; - icon_state = "flare-on" + icon_state = "flare-on"; + start_on = 1 }, /turf/open/indestructible/plating, /area/awaymission/museum) @@ -4756,9 +5203,9 @@ }, /obj/structure/fluff{ name = "replica prototype autolathe"; + desc = "A non-functional replica of a prototype Autolathe."; icon = 'icons/obj/machines/lathes.dmi'; - icon_state = "autolathe"; - desc = "A non-functional replica of a prototype Autolathe." + icon_state = "autolathe" }, /turf/open/floor/iron/smooth_corner{ dir = 4 @@ -4803,6 +5250,18 @@ /obj/effect/decal/cleanable/dirt/dust, /turf/open/floor/iron/white, /area/awaymission/museum) +"RQ" = ( +/obj/effect/turf_decal/tile/neutral/opposingcorners, +/obj/effect/turf_decal/siding/dark_blue{ + dir = 1 + }, +/obj/structure/fluff/fake_camera, +/obj/effect/decal/puzzle_dots{ + pixel_y = -32; + id = "museum_r_wing_puzzle" + }, +/turf/open/floor/iron/dark, +/area/awaymission/museum) "RR" = ( /obj/machinery/suit_storage_unit/open, /obj/effect/turf_decal/box, @@ -4829,8 +5288,8 @@ /turf/open/floor/bluespace, /area/awaymission/museum) "Se" = ( -/obj/structure/chair/comfy/beige, /mob/living/basic/mothroach, +/obj/structure/chair/comfy/beige, /obj/effect/mapping_helpers/mob_buckler, /turf/open/floor/wood/large, /area/awaymission/museum) @@ -4839,6 +5298,11 @@ /obj/structure/railing, /turf/open/floor/holofloor/asteroid, /area/awaymission/museum) +"Sm" = ( +/obj/effect/decal/cleanable/dirt/dust, +/obj/structure/fluff/fake_scrubber, +/turf/open/floor/iron/white/small, +/area/awaymission/museum) "So" = ( /obj/machinery/shower/directional/east, /turf/open/floor/iron/white/textured_large, @@ -4849,7 +5313,7 @@ /area/awaymission/museum) "Sv" = ( /obj/machinery/status_display/random_message{ - firstline_to_secondline = list("SOUVENIR" = "SHOP") + firstline_to_secondline = list(SOUVENIR="SHOP") }, /turf/closed/indestructible/reinforced, /area/awaymission/museum) @@ -4880,7 +5344,11 @@ }, /obj/machinery/door/poddoor/shutters/indestructible{ dir = 8; - id = "nothing" + id = "museum_secret" + }, +/obj/machinery/puzzle/password/pin/directional/south{ + id = "museum_r_wing_puzzle"; + late_initialize_pop = 1 }, /turf/open/floor/iron/dark, /area/awaymission/museum) @@ -4889,6 +5357,14 @@ /obj/item/stack/spacecash/c1000, /turf/open/indestructible/plating, /area/awaymission/museum) +"Ta" = ( +/obj/machinery/light/directional/west, +/obj/effect/decal/cleanable/crayon/puzzle/pin{ + pixel_x = -32; + puzzle_id = "museum_r_wing_puzzle" + }, +/turf/open/floor/iron/white/small, +/area/awaymission/museum) "Tr" = ( /obj/structure/plaque/static_plaque/golden/commission/kilo, /obj/machinery/light/floor, @@ -4923,6 +5399,13 @@ }, /turf/open/indestructible/plating, /area/awaymission/museum) +"TC" = ( +/obj/machinery/door/airlock/multi_tile/public/glass{ + name = "Cafeteria"; + dir = 4 + }, +/turf/open/floor/iron, +/area/awaymission/museum/cafeteria) "TF" = ( /turf/open/floor/iron/stairs/right{ dir = 4 @@ -4998,8 +5481,8 @@ dir = 8 }, /obj/structure/fluff/wallsign/directional/east{ - dir = 2; - name = "Exit" + name = "Exit"; + dir = 2 }, /turf/open/floor/iron/dark, /area/awaymission/museum) @@ -5037,8 +5520,8 @@ /obj/effect/turf_decal/tile/neutral/opposingcorners, /obj/structure/table, /obj/item/computer_disk{ - icon_state = "datadisk_hydro"; - name = "plant data disk" + name = "plant data disk"; + icon_state = "datadisk_hydro" }, /turf/open/floor/iron/dark, /area/awaymission/museum) @@ -5066,6 +5549,12 @@ /mob/living/basic/mothroach, /turf/open/misc/beach/sand, /area/awaymission/museum/mothroachvoid) +"UH" = ( +/obj/structure/mirror/broken/directional/east, +/obj/structure/sink/directional/west, +/obj/effect/decal/cleanable/oil/slippery, +/turf/open/floor/iron/white/small, +/area/awaymission/museum) "UI" = ( /obj/effect/turf_decal/tile/green/opposingcorners, /obj/effect/decal/cleanable/dirt/dust, @@ -5106,8 +5595,8 @@ /area/awaymission/museum) "UT" = ( /obj/machinery/status_display/random_message{ - firstline_to_secondline = list("NO" = "LITTERING","YOU ARE" = "BEING WATCHED", "DO NOT TOUCH" = "THE EXHIBITS"); - pixel_x = 32 + pixel_x = 32; + firstline_to_secondline = list(NO="LITTERING", "YOU ARE"="BEING WATCHED", "DO NOT TOUCH"="THE EXHIBITS") }, /turf/open/floor/carpet, /area/awaymission/museum) @@ -5129,6 +5618,14 @@ /obj/effect/decal/cleanable/dirt/dust, /turf/open/floor/iron/smooth_half, /area/awaymission/museum) +"Vb" = ( +/obj/effect/replica_spawner{ + obvious_replica = 0; + pixel_y = 30; + target_path = /obj/structure/sign/painting/eldritch/weeping + }, +/turf/open/floor/iron/cafeteria, +/area/awaymission/museum/cafeteria) "Vc" = ( /obj/machinery/light/warm/directional/east, /obj/effect/turf_decal/tile/neutral/opposingcorners, @@ -5380,6 +5877,25 @@ }, /turf/open/floor/iron/dark, /area/awaymission/museum) +"WY" = ( +/obj/machinery/button/door/directional/north{ + name = "Lock Control"; + id = "museum_toilet2"; + specialfunctions = 4; + normaldoorcontrol = 1 + }, +/obj/structure/toilet/museum{ + dir = 4 + }, +/obj/machinery/light/small/dim/directional/west, +/turf/open/floor/iron/white/small, +/area/awaymission/museum) +"WZ" = ( +/obj/structure/chair/sofa/bench{ + dir = 1 + }, +/turf/open/floor/iron/cafeteria, +/area/awaymission/museum/cafeteria) "Xa" = ( /obj/structure/broken_flooring/corner/always_floorplane{ dir = 2 @@ -5402,6 +5918,10 @@ "Xh" = ( /turf/closed/indestructible/fakedoor/maintenance, /area/awaymission/museum) +"Xi" = ( +/obj/structure/chair/sofa/bench/right, +/turf/open/floor/iron/cafeteria, +/area/awaymission/museum/cafeteria) "Xo" = ( /obj/structure/lattice/catwalk/mining, /obj/structure/railing, @@ -5502,8 +6022,8 @@ /turf/closed/indestructible/reinforced/titanium/nodiagonal, /area/awaymission/museum) "Yg" = ( -/obj/effect/decal/cleanable/dirt/dust, /mob/living/basic/cockroach, +/obj/effect/decal/cleanable/dirt/dust, /turf/open/indestructible/plating, /area/awaymission/museum) "Yk" = ( @@ -5512,6 +6032,12 @@ }, /turf/open/floor/iron, /area/awaymission/museum) +"Yn" = ( +/obj/machinery/light/warm/directional/east, +/obj/effect/decal/cleanable/dirt/dust, +/obj/structure/fluff/fake_camera, +/turf/open/floor/iron/white/small, +/area/awaymission/museum) "Yr" = ( /obj/effect/turf_decal/tile/neutral/opposingcorners, /obj/structure/table/reinforced, @@ -5521,13 +6047,21 @@ /obj/item/reagent_containers/cup/glass/mug/nanotrasen, /turf/open/floor/iron/dark, /area/awaymission/museum) +"Yy" = ( +/obj/machinery/computer/terminal/museum{ + name = "donation info terminal"; + dir = 8; + content = list("We're once again asking for your financial support; We love our job, but love alone can only get us so far. Please consider leaving a donation to help keep the musuem running. Thank you.") + }, +/turf/open/floor/iron/cafeteria, +/area/awaymission/museum/cafeteria) "Yz" = ( -/obj/effect/turf_decal/siding, /mob/living/basic/statue/mannequin{ dir = 8; held_item = /obj/item/pickaxe; hat = /obj/item/clothing/suit/hooded/explorer }, +/obj/effect/turf_decal/siding, /obj/structure/railing, /turf/open/floor/holofloor/asteroid, /area/awaymission/museum) @@ -5571,8 +6105,15 @@ /obj/item/reagent_containers/cup/glass/coffee/no_lid{ pixel_x = 12 }, +/obj/item/paper/fluff/museum/numbers_on_walls, /turf/open/floor/iron, /area/awaymission/museum) +"Za" = ( +/obj/structure/chair/sofa/bench/right{ + dir = 1 + }, +/turf/open/floor/iron/cafeteria, +/area/awaymission/museum/cafeteria) "Zf" = ( /obj/structure/plaque/static_plaque/golden/commission/donut, /turf/closed/indestructible/reinforced, @@ -5589,6 +6130,11 @@ /obj/structure/lattice, /turf/open/chasm/true/no_smooth, /area/awaymission/museum) +"Zo" = ( +/obj/structure/table, +/obj/effect/spawner/random/food_or_drink/snack, +/turf/open/floor/iron/cafeteria, +/area/awaymission/museum/cafeteria) "Zp" = ( /obj/structure/plaque/static_plaque/golden/commission/icebox, /turf/closed/indestructible/reinforced, @@ -5613,6 +6159,16 @@ }, /turf/open/floor/iron/dark, /area/awaymission/museum) +"Zx" = ( +/obj/structure/chair/sofa/bench, +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/iron/cafeteria, +/area/awaymission/museum/cafeteria) +"Zz" = ( +/obj/effect/mapping_helpers/turn_off_lights_with_lightswitch, +/obj/machinery/light_switch/directional/west, +/turf/open/floor/iron/cafeteria, +/area/awaymission/museum/cafeteria) "ZB" = ( /obj/machinery/door/airlock/maintenance_hatch, /obj/structure/broken_flooring/side/always_floorplane/directional/east, @@ -5644,6 +6200,13 @@ }, /turf/open/floor/iron/dark, /area/awaymission/museum) +"ZO" = ( +/obj/structure/sink/directional/south{ + pixel_y = 6 + }, +/obj/structure/mirror/directional/north, +/turf/open/floor/iron/white/small, +/area/awaymission/museum) "ZP" = ( /obj/structure/statue/gold/ce{ anchored = 1 @@ -26150,7 +26713,7 @@ re re re re -re +Uq re re re @@ -26403,12 +26966,12 @@ re re re re -re -re -re -re -re -re +FK +FK +FK +FK +FK +Uq re re re @@ -26660,11 +27223,11 @@ re re re re -re -re -re -re -re +FK +kZ +FK +oD +FK re re re @@ -26915,13 +27478,13 @@ Wc FK re re -re -re -re -re -re -re -re +FK +FO +FK +ta +FK +AQ +FK re re re @@ -27172,13 +27735,13 @@ fy FK re re -re -re -re -re -re -re -re +FK +jO +ry +Gn +Ta +Gn +FK re re re @@ -27429,13 +27992,13 @@ tD FK re re -re -re -re -re -re -re -re +FK +FK +FO +IG +Gn +ax +FK re re re @@ -27687,12 +28250,12 @@ FK re re re -re -re -re -re -re -re +FK +ZO +Gn +Gn +Gn +FK re re re @@ -27947,7 +28510,7 @@ FK FK FK FK -FK +Nn FK FK Uq @@ -29699,7 +30262,7 @@ aW MF MF MF -MF +Id Re PZ Ma @@ -34375,7 +34938,7 @@ FK FK FK FK -FK +FO FK FK FK @@ -35113,7 +35676,7 @@ re re re re -FK +FO qw XK PP @@ -35916,7 +36479,7 @@ FK FK FK Yd -FK +FO NO dZ mn @@ -35958,6 +36521,9 @@ nu FK FK FK +FK +FK +FK Uq re re @@ -35995,9 +36561,6 @@ re re re re -re -re -re "} (119,1,1) = {" re @@ -36214,10 +36777,10 @@ qQ xI gT Qb -FK -re -re -re +Ga +gg +iJ +FO re re re @@ -36472,6 +37035,9 @@ xI xd ns FK +FK +FK +FK re re re @@ -36509,9 +37075,6 @@ re re re re -re -re -re "} (121,1,1) = {" re @@ -36731,7 +37294,7 @@ BO FK re re -re +Uq re re re @@ -36986,7 +37549,7 @@ Nc FK FK FK -Uq +re re re re @@ -37461,7 +38024,7 @@ FK FK FK PB -FK +FO Ma Ma Ma @@ -40781,7 +41344,7 @@ FK FK FK FK -lb +eW uY rQ FK @@ -42582,7 +43145,7 @@ FK FK lb uY -qX +RQ FK FK FK @@ -43085,19 +43648,19 @@ re re re re +FK +FK +FK +FK +FK +FK +FK re -re -re -re -re -re -re -re -Uq -re -re -re -Uq +FK +aa +uY +ci +jC re re re @@ -43342,19 +43905,19 @@ re re re re -re -re -re -re -re -re -re -re -re -re -re -re -re +FK +aO +FK +WY +FK +HW +FK +FK +FK +Mb +TM +wV +FK re re re @@ -43599,19 +44162,19 @@ re re re re -re -re -re -re -re -re -re -re -re -re -re -re -re +FK +wg +FK +us +FK +Jp +FK +um +FK +Mb +uY +wV +FK re re re @@ -43856,19 +44419,19 @@ re re re re -re -re -re -re -re -re -re -re -re -re -re -re -re +FK +Gn +Gn +Gn +Sm +Gn +Kz +Gn +FK +ju +uY +ci +Ir re re re @@ -44113,19 +44676,19 @@ re re re re -re -re -re -re -re -re -re -re -re -re -re -re -re +FK +nY +Gn +Gn +Gn +Gn +Gn +Gn +kx +uY +uY +wV +FK re re re @@ -44370,19 +44933,19 @@ re re re re -re -re -re -re -re -re -re -re -re -re -re -re -re +FK +ut +UH +gE +CG +Gn +CG +Yn +FK +RC +TM +FU +FK re re re @@ -44627,20 +45190,20 @@ re re re re -re -re -re -re -re -re -re -re -re -re -re -re -re -re +FK +FK +FK +FK +FK +FK +FK +FK +FK +Mb +uY +wV +FK +Uq re re re @@ -44892,11 +45455,11 @@ re re re re -re -re -re -re -re +FK +pN +uY +hS +oP re re re @@ -45149,11 +45712,11 @@ re re re re -re -re -re -re -re +FK +FK +pz +kL +FK re re re @@ -45403,16 +45966,16 @@ re re re re -re -re -re -re -re -re -re -re -re -re +Ph +Ph +Ph +Ph +Ph +ms +TC +Ph +Ph +Ph re re re @@ -45660,16 +46223,16 @@ re re re re -re -re -re -re -re -re -re -re -re -re +Ph +DX +HQ +fl +Zz +HQ +HQ +HQ +ac +Ph re re re @@ -45917,16 +46480,16 @@ re re re re -re -re -re -re -re -re -re -re -re -re +Ph +qK +HQ +HQ +HQ +HQ +HQ +HQ +HQ +vG re re re @@ -46174,16 +46737,16 @@ re re re re -re -re -re -re -re -re -re -re -re -re +Ph +uH +HQ +Xi +xp +nZ +Xi +Es +nZ +Ph re re re @@ -46431,17 +46994,17 @@ re re re re -re -re -re -re -re -re -re -re -re -re -re +Ph +Vb +HQ +Zx +hm +WZ +ql +xp +WZ +Ph +Uq re re re @@ -46688,16 +47251,16 @@ re re re re -re -re -re -re -re -re -re -re -re -re +Ph +HQ +HQ +ql +Zo +WZ +ql +GB +IX +Ph re re re @@ -46945,16 +47508,16 @@ re re re re -re -re -re -re -re -re -re -re -re -re +Ph +Db +HQ +FY +xO +Za +FY +xp +Za +Ph re re re @@ -47202,16 +47765,16 @@ re re re re -re -re -re -re -re -re -re -re -re -re +Ph +LK +Yy +HQ +HQ +KB +Jl +HQ +cY +Ph re re re @@ -47459,16 +48022,16 @@ re re re re -re -re -re -re -re -re -re -re -re -re +Ph +Ph +Ph +Ph +Ph +Ph +Ph +Ph +Ph +Ph re re re diff --git a/_maps/map_files/Birdshot/birdshot.dmm b/_maps/map_files/Birdshot/birdshot.dmm index 2c22062c16fb8ef..149c2e0420a5ab8 100644 --- a/_maps/map_files/Birdshot/birdshot.dmm +++ b/_maps/map_files/Birdshot/birdshot.dmm @@ -144,14 +144,6 @@ "aed" = ( /turf/open/floor/plating, /area/station/engineering/atmos/project) -"aei" = ( -/obj/structure/disposalpipe/segment, -/obj/effect/turf_decal/siding/wood{ - dir = 9 - }, -/obj/effect/decal/cleanable/cobweb, -/turf/open/floor/grass, -/area/station/service/chapel) "aem" = ( /obj/effect/decal/cleanable/dirt, /turf/open/floor/plating/rust, @@ -223,6 +215,13 @@ }, /turf/open/floor/plating, /area/station/engineering/atmos/project) +"aeH" = ( +/obj/structure/disposalpipe/segment, +/obj/effect/turf_decal/siding/wood/corner{ + dir = 1 + }, +/turf/open/floor/grass, +/area/station/service/chapel) "aeN" = ( /obj/structure/cable, /obj/structure/disposalpipe/segment{ @@ -631,14 +630,6 @@ /obj/machinery/power/apc/worn_out/directional/west, /turf/open/floor/iron, /area/station/maintenance/hallway/abandoned_recreation) -"amn" = ( -/obj/effect/landmark/start/assistant, -/obj/effect/landmark/start/assistant, -/obj/structure/chair/sofa/bamboo/left{ - dir = 1 - }, -/turf/open/floor/wood/large, -/area/station/service/chapel) "amp" = ( /obj/structure/lattice/catwalk, /obj/structure/railing, @@ -781,13 +772,6 @@ /obj/item/storage/lockbox/medal, /turf/open/floor/carpet/executive, /area/station/command/heads_quarters/captain/private) -"aoJ" = ( -/obj/effect/turf_decal/siding/wood{ - dir = 4 - }, -/obj/structure/flora/tree/jungle/small/style_random, -/turf/open/floor/grass, -/area/station/service/chapel) "aoT" = ( /obj/machinery/atmospherics/pipe/smart/simple/yellow/visible, /obj/effect/decal/cleanable/dirt, @@ -1430,6 +1414,13 @@ }, /turf/open/floor/iron, /area/station/engineering/storage/tech) +"aCG" = ( +/obj/effect/turf_decal/siding/wood{ + dir = 4 + }, +/obj/structure/flora/tree/jungle/small/style_random, +/turf/open/floor/grass, +/area/station/service/chapel) "aCM" = ( /obj/effect/spawner/random/structure/crate_abandoned, /obj/structure/alien/weeds, @@ -2139,6 +2130,10 @@ /obj/effect/decal/cleanable/dirt, /turf/open/floor/iron/dark/small, /area/station/ai_monitored/security/armory) +"aRr" = ( +/obj/effect/spawner/xmastree, +/turf/open/floor/grass, +/area/station/service/chapel) "aRv" = ( /obj/structure/sign/warning/electric_shock, /turf/closed/wall/r_wall, @@ -2323,15 +2318,6 @@ /obj/machinery/recharger, /turf/open/floor/iron/smooth, /area/station/security/checkpoint/escape) -"aUy" = ( -/obj/structure/cable, -/obj/effect/decal/cleanable/dirt, -/obj/effect/mapping_helpers/broken_floor, -/obj/effect/decal/cleanable/glass/plastitanium, -/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/greater) "aUA" = ( /obj/effect/decal/cleanable/dirt, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -2635,16 +2621,6 @@ /obj/machinery/door/firedoor, /turf/open/floor/iron/white/small, /area/station/medical/medbay/lobby) -"bcH" = ( -/obj/structure/bed{ - dir = 4 - }, -/obj/effect/spawner/random/bedsheet{ - dir = 4 - }, -/obj/machinery/light/small/directional/west, -/turf/open/floor/carpet/purple, -/area/station/commons/dorms) "bcR" = ( /obj/machinery/atmospherics/components/unary/portables_connector/visible{ dir = 8 @@ -3133,6 +3109,10 @@ /mob/living/basic/bot/medbot/autopatrol, /turf/open/floor/iron/white, /area/station/medical/medbay/lobby) +"bmD" = ( +/obj/structure/flora/bush/flowers_yw/style_random, +/turf/open/floor/grass, +/area/station/service/chapel) "bmM" = ( /obj/structure/cable, /obj/structure/disposalpipe/segment, @@ -3400,6 +3380,10 @@ }, /turf/open/floor/iron, /area/station/hallway/primary/aft) +"brG" = ( +/obj/structure/flora/tree/jungle/small/style_random, +/turf/open/floor/grass, +/area/station/service/chapel) "brZ" = ( /obj/machinery/door/airlock{ name = "Maintenance" @@ -4081,9 +4065,6 @@ }, /turf/open/floor/iron, /area/station/cargo/sorting) -"bDh" = ( -/turf/open/floor/grass, -/area/station/service/chapel) "bDj" = ( /obj/effect/landmark/start/medical_doctor, /obj/machinery/atmospherics/components/unary/vent_pump/on/layer4, @@ -4202,6 +4183,14 @@ }, /turf/open/floor/iron/smooth, /area/station/engineering/supermatter/room) +"bEI" = ( +/obj/structure/disposalpipe/segment, +/obj/effect/turf_decal/siding/wood, +/obj/structure/chair/sofa/bamboo/left{ + dir = 1 + }, +/turf/open/floor/wood/large, +/area/station/service/chapel) "bEN" = ( /obj/structure/chair/sofa/bench/left{ dir = 4 @@ -4426,13 +4415,6 @@ /obj/structure/chair/stool/directional/south, /turf/open/floor/iron, /area/station/security/prison/workout) -"bKn" = ( -/obj/effect/turf_decal/siding/wood{ - dir = 1 - }, -/obj/structure/flora/bush/flowers_br/style_random, -/turf/open/floor/grass, -/area/station/service/chapel) "bKu" = ( /obj/effect/spawner/random/trash, /turf/open/floor/plating, @@ -4851,13 +4833,6 @@ /obj/effect/turf_decal/tile/yellow/opposingcorners, /turf/open/floor/iron, /area/station/engineering/atmospherics_engine) -"bTw" = ( -/obj/effect/decal/cleanable/dirt, -/obj/structure/reagent_dispensers/plumbed{ - dir = 4 - }, -/turf/open/floor/plating, -/area/station/maintenance/central/greater) "bTN" = ( /obj/effect/turf_decal/tile/yellow/opposingcorners, /turf/open/floor/iron, @@ -5423,14 +5398,6 @@ dir = 8 }, /area/station/maintenance/disposal/incinerator) -"cdC" = ( -/obj/structure/disposalpipe/segment, -/obj/effect/turf_decal/siding/wood, -/obj/structure/chair/sofa/bamboo/left{ - dir = 1 - }, -/turf/open/floor/wood/large, -/area/station/service/chapel) "cdW" = ( /obj/structure/cable, /turf/open/floor/catwalk_floor/iron_smooth, @@ -5483,13 +5450,6 @@ }, /turf/closed/wall/rust, /area/station/ai_monitored/turret_protected/ai) -"cfi" = ( -/obj/structure/disposalpipe/segment, -/obj/effect/turf_decal/siding/wood{ - dir = 1 - }, -/turf/open/floor/wood/large, -/area/station/service/chapel) "cfk" = ( /obj/machinery/atmospherics/pipe/smart/simple/green/visible{ dir = 4 @@ -5520,12 +5480,6 @@ /obj/structure/sign/poster/official/random/directional/north, /turf/open/floor/iron/smooth_large, /area/station/science/auxlab/firing_range) -"cgG" = ( -/obj/effect/turf_decal/siding/wood{ - dir = 8 - }, -/turf/open/floor/grass, -/area/station/service/chapel) "cgM" = ( /turf/open/misc/asteroid, /area/station/maintenance/starboard/greater) @@ -5606,11 +5560,6 @@ /obj/effect/spawner/random/techstorage/command_all, /turf/open/floor/iron, /area/station/engineering/storage/tech) -"ciT" = ( -/obj/structure/table/glass, -/obj/item/radio/intercom/directional/east, -/turf/open/floor/iron/white, -/area/station/science/auxlab/firing_range) "cjm" = ( /obj/structure/closet/firecloset, /obj/machinery/status_display/evac/directional/south, @@ -6062,10 +6011,6 @@ /obj/structure/window/spawner/directional/north, /turf/open/space/basic, /area/space/nearstation) -"crG" = ( -/obj/structure/flora/bush/flowers_yw/style_random, -/turf/open/floor/grass, -/area/station/service/chapel) "crJ" = ( /obj/effect/turf_decal/siding/red{ dir = 6 @@ -6325,6 +6270,13 @@ /obj/effect/spawner/structure/window/survival_pod, /turf/open/floor/engine, /area/station/ai_monitored/turret_protected/ai) +"cxl" = ( +/obj/effect/turf_decal/siding/wood{ + dir = 1 + }, +/obj/effect/landmark/start/chaplain, +/turf/open/floor/wood/large, +/area/station/service/chapel) "cxr" = ( /obj/effect/decal/cleanable/dirt, /obj/structure/closet/emcloset, @@ -7134,10 +7086,6 @@ }, /turf/open/floor/iron/dark/small, /area/station/science/xenobiology) -"cLX" = ( -/obj/structure/flora/tree/jungle/small/style_random, -/turf/open/floor/grass, -/area/station/service/chapel) "cLY" = ( /obj/machinery/computer/security{ dir = 4 @@ -7553,6 +7501,13 @@ /obj/machinery/portable_atmospherics/canister/oxygen, /turf/open/floor/iron, /area/station/engineering/atmos) +"cUm" = ( +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/effect/turf_decal/siding/wood{ + dir = 5 + }, +/turf/open/floor/grass, +/area/station/service/chapel) "cUE" = ( /obj/structure/cable, /obj/effect/turf_decal/stripes/line{ @@ -7734,14 +7689,6 @@ /obj/effect/turf_decal/tile/neutral, /turf/open/floor/iron, /area/station/hallway/primary/fore) -"cXT" = ( -/obj/structure/rack, -/obj/item/clothing/gloves/boxing/yellow, -/obj/item/clothing/gloves/boxing/green{ - pixel_y = 4 - }, -/turf/open/floor/plating, -/area/station/maintenance/fore/greater) "cXU" = ( /obj/effect/turf_decal/stripes/line{ dir = 10 @@ -7866,12 +7813,6 @@ /obj/machinery/firealarm/directional/north, /turf/open/floor/iron/dark, /area/station/engineering/main) -"dab" = ( -/obj/structure/cable, -/obj/effect/decal/cleanable/dirt, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/turf/open/floor/plating, -/area/station/maintenance/fore/greater) "dah" = ( /obj/structure/disposalpipe/segment, /obj/effect/turf_decal/tile/dark_red/half/contrasted{ @@ -7895,10 +7836,6 @@ dir = 1 }, /area/station/science/lower) -"daR" = ( -/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4, -/turf/open/floor/wood/large, -/area/station/service/chapel) "dba" = ( /obj/structure/chair/sofa/bench/left{ dir = 4 @@ -8160,13 +8097,6 @@ }, /turf/open/floor/iron, /area/station/engineering/atmos) -"dfH" = ( -/obj/structure/disposalpipe/segment, -/obj/effect/turf_decal/siding/wood/corner{ - dir = 1 - }, -/turf/open/floor/grass, -/area/station/service/chapel) "dfN" = ( /obj/structure/window/spawner/directional/west, /obj/structure/window/spawner/directional/south, @@ -8179,14 +8109,6 @@ /obj/machinery/light/small/directional/south, /turf/open/floor/wood/parquet, /area/station/service/library) -"dgm" = ( -/obj/machinery/door/airlock/command{ - name = "Centcom Dock" - }, -/obj/effect/mapping_helpers/airlock/access/any/command/general, -/obj/effect/mapping_helpers/airlock/access/any/admin/general, -/turf/open/floor/iron/textured_half, -/area/station/command/corporate_dock) "dgn" = ( /obj/structure/cable, /obj/structure/disposalpipe/segment{ @@ -8233,14 +8155,6 @@ }, /turf/open/floor/circuit/red, /area/station/ai_monitored/turret_protected/ai) -"dhp" = ( -/obj/effect/turf_decal/siding/wood{ - dir = 8 - }, -/obj/structure/flora/bush/flowers_yw/style_random, -/obj/effect/landmark/start/hangover, -/turf/open/floor/grass, -/area/station/service/chapel) "dhw" = ( /obj/effect/turf_decal/tile/yellow, /obj/structure/cable, @@ -8278,13 +8192,6 @@ }, /turf/open/floor/iron/dark, /area/station/medical/pharmacy) -"dio" = ( -/obj/effect/turf_decal/siding/wood{ - dir = 5 - }, -/obj/machinery/light/directional/east, -/turf/open/floor/grass, -/area/station/service/chapel) "dis" = ( /obj/structure/cable, /obj/structure/disposalpipe/segment{ @@ -9058,10 +8965,11 @@ /obj/effect/spawner/random/trash, /turf/open/floor/plating, /area/station/maintenance/department/engine/atmos) -"dvZ" = ( +"dvY" = ( /obj/effect/turf_decal/siding/wood{ - dir = 1 + dir = 5 }, +/obj/structure/flora/bush/sunny/style_random, /turf/open/floor/grass, /area/station/service/chapel) "dwa" = ( @@ -9070,11 +8978,6 @@ /obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2, /turf/open/floor/iron, /area/station/security/tram) -"dwf" = ( -/obj/effect/turf_decal/siding/wood, -/obj/structure/flora/bush/flowers_pp/style_random, -/turf/open/floor/grass, -/area/station/service/chapel) "dwh" = ( /obj/structure/cable, /obj/structure/disposalpipe/segment, @@ -9402,13 +9305,12 @@ /obj/machinery/duct, /turf/open/floor/plating, /area/station/maintenance/department/medical/central) -"dBD" = ( -/obj/effect/turf_decal/siding/wood{ - dir = 4 - }, +"dBA" = ( +/obj/structure/bed, +/obj/effect/spawner/random/bedsheet, /obj/machinery/light/small/directional/east, -/turf/open/floor/grass, -/area/station/service/chapel) +/turf/open/floor/carpet/royalblack, +/area/station/commons/dorms) "dBH" = ( /turf/open/floor/iron/white/corner{ dir = 1 @@ -9579,13 +9481,6 @@ }, /turf/open/floor/tram, /area/station/security/tram) -"dEN" = ( -/obj/effect/turf_decal/siding/wood{ - dir = 5 - }, -/obj/machinery/airalarm/directional/north, -/turf/open/floor/grass, -/area/station/service/chapel) "dER" = ( /obj/machinery/power/emitter, /obj/effect/turf_decal/stripes/white/line{ @@ -9629,6 +9524,10 @@ }, /turf/closed/wall/r_wall, /area/station/engineering/atmos/pumproom) +"dGM" = ( +/obj/machinery/light/floor, +/turf/open/floor/wood/large, +/area/station/service/chapel) "dGO" = ( /obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2{ dir = 1 @@ -10108,10 +10007,6 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/open/floor/iron/dark, /area/station/security/interrogation) -"dPv" = ( -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/turf/open/floor/wood/large, -/area/station/service/chapel) "dPz" = ( /turf/open/floor/iron/diagonal, /area/station/maintenance/department/engine/atmos) @@ -10222,12 +10117,6 @@ /obj/effect/turf_decal/tile/yellow/opposingcorners, /turf/open/floor/iron, /area/station/maintenance/department/engine/atmos) -"dRK" = ( -/obj/effect/turf_decal/siding/wood/corner{ - dir = 4 - }, -/turf/open/floor/grass, -/area/station/service/chapel) "dSb" = ( /obj/machinery/atmospherics/pipe/smart/simple/general/visible{ dir = 4 @@ -10280,15 +10169,6 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/plating, /area/station/maintenance/department/engine) -"dSF" = ( -/obj/effect/turf_decal/siding/wood{ - dir = 9 - }, -/obj/item/storage/fancy/candle_box, -/obj/machinery/light_switch/directional/west, -/obj/structure/rack/skeletal, -/turf/open/floor/iron/grimy, -/area/station/service/library) "dSM" = ( /obj/machinery/atmospherics/pipe/smart/simple/green/visible, /obj/effect/spawner/structure/window/reinforced, @@ -10500,11 +10380,6 @@ /obj/machinery/portable_atmospherics/canister/oxygen, /turf/open/floor/plating, /area/station/engineering/atmos/storage/gas) -"dWE" = ( -/obj/structure/flora/bush/flowers_pp/style_random, -/obj/effect/landmark/event_spawn, -/turf/open/floor/grass, -/area/station/service/chapel) "dWI" = ( /obj/machinery/atmospherics/pipe/smart/simple/yellow/visible, /obj/structure/disposalpipe/segment{ @@ -11042,16 +10917,6 @@ dir = 4 }, /area/station/science/xenobiology) -"eey" = ( -/obj/structure/cable, -/obj/effect/decal/cleanable/dirt, -/obj/effect/spawner/random/trash, -/obj/effect/decal/cleanable/dirt, -/obj/effect/mapping_helpers/broken_floor, -/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/greater) "eeD" = ( /obj/structure/showcase/cyborg/old{ pixel_y = 20 @@ -11181,14 +11046,6 @@ /obj/effect/spawner/structure/window/reinforced/tinted, /turf/open/floor/plating, /area/station/maintenance/fore/lesser) -"ehr" = ( -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/effect/turf_decal/siding/wood{ - dir = 9 - }, -/turf/open/floor/grass, -/area/station/service/chapel) "ehB" = ( /obj/machinery/light_switch/directional/north, /obj/effect/turf_decal/delivery, @@ -11198,14 +11055,6 @@ }, /turf/open/floor/iron/dark, /area/station/engineering/atmos) -"ehL" = ( -/obj/effect/landmark/start/hangover, -/obj/effect/turf_decal/siding/wood, -/obj/structure/chair/sofa/bamboo/left{ - dir = 1 - }, -/turf/open/floor/wood/large, -/area/station/service/chapel) "ehV" = ( /obj/structure/cable, /obj/structure/chair/sofa/right{ @@ -11226,6 +11075,16 @@ /obj/structure/broken_flooring/singular/directional/south, /turf/open/floor/plating, /area/station/maintenance/department/medical/central) +"ein" = ( +/obj/structure/bed{ + dir = 4 + }, +/obj/effect/spawner/random/bedsheet{ + dir = 4 + }, +/obj/machinery/light/small/directional/west, +/turf/open/floor/carpet/purple, +/area/station/commons/dorms) "eip" = ( /obj/machinery/power/port_gen/pacman, /obj/machinery/power/terminal{ @@ -11495,6 +11354,13 @@ /obj/effect/mapping_helpers/broken_floor, /turf/open/floor/plating, /area/station/maintenance/starboard/aft) +"ena" = ( +/obj/effect/decal/cleanable/dirt, +/obj/structure/reagent_dispensers/plumbed{ + dir = 1 + }, +/turf/open/floor/iron, +/area/station/maintenance/department/medical/central) "enb" = ( /obj/structure/cable, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -11594,6 +11460,12 @@ dir = 4 }, /area/station/maintenance/disposal/incinerator) +"eoH" = ( +/obj/effect/turf_decal/siding/wood{ + dir = 9 + }, +/turf/open/floor/grass, +/area/station/service/chapel) "eoK" = ( /obj/machinery/atmospherics/pipe/bridge_pipe/green/visible, /obj/machinery/atmospherics/pipe/bridge_pipe/yellow/visible{ @@ -12075,12 +11947,6 @@ /obj/effect/decal/cleanable/dirt, /turf/open/floor/plating, /area/station/engineering/break_room) -"ewh" = ( -/obj/effect/turf_decal/siding/wood/corner{ - dir = 1 - }, -/turf/open/floor/grass, -/area/station/service/chapel) "ewi" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/machinery/light/cold/directional/west, @@ -12226,13 +12092,6 @@ /obj/structure/chair/stool/directional/west, /turf/open/floor/iron/cafeteria, /area/station/security/prison/mess) -"ezt" = ( -/obj/effect/decal/cleanable/dirt, -/obj/structure/reagent_dispensers/plumbed{ - dir = 1 - }, -/turf/open/floor/iron, -/area/station/maintenance/department/medical/central) "ezw" = ( /obj/structure/cable, /obj/effect/landmark/start/hangover, @@ -12549,15 +12408,6 @@ /obj/machinery/camera/directional/west, /turf/open/floor/iron/smooth, /area/station/commons/storage/tools) -"eEy" = ( -/obj/effect/turf_decal/siding/wood{ - dir = 1 - }, -/obj/structure/flora/bush/flowers_br/style_random, -/obj/machinery/camera/autoname/directional/north, -/obj/machinery/light/small/directional/north, -/turf/open/floor/grass, -/area/station/service/chapel) "eFc" = ( /obj/effect/turf_decal/tile/blue, /obj/machinery/firealarm/directional/west, @@ -12775,12 +12625,6 @@ /obj/structure/holosign/barrier/atmos/tram, /turf/open/floor/plating, /area/station/maintenance/port/aft) -"eHK" = ( -/obj/effect/turf_decal/siding/wood{ - dir = 6 - }, -/turf/open/floor/grass, -/area/station/service/chapel) "eHN" = ( /obj/structure/cable, /turf/open/floor/wood/tile, @@ -12917,6 +12761,12 @@ /obj/machinery/light/small/directional/north, /turf/open/floor/iron/kitchen/small, /area/station/maintenance/aft) +"eKn" = ( +/obj/effect/turf_decal/siding/wood{ + dir = 1 + }, +/turf/open/floor/wood/large, +/area/station/service/chapel) "eKs" = ( /obj/structure/chair/comfy/brown{ dir = 8 @@ -13148,6 +12998,14 @@ /obj/item/stock_parts/cell/high, /turf/open/floor/circuit, /area/station/maintenance/port/aft) +"ePm" = ( +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/effect/turf_decal/siding/wood{ + dir = 9 + }, +/turf/open/floor/grass, +/area/station/service/chapel) "ePn" = ( /obj/structure/disposalpipe/segment, /obj/machinery/light/small/directional/south, @@ -13180,12 +13038,6 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/iron/smooth, /area/station/engineering/break_room) -"ePQ" = ( -/obj/structure/disposalpipe/segment, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/machinery/light/floor, -/turf/open/floor/wood/large, -/area/station/service/chapel) "ePV" = ( /obj/structure/cable, /obj/structure/window/reinforced/spawner/directional/west, @@ -13633,12 +13485,6 @@ }, /turf/open/floor/stone, /area/station/maintenance/aft) -"eXP" = ( -/obj/structure/cable, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/machinery/duct, -/turf/open/floor/iron/kitchen/small, -/area/station/security/prison/mess) "eXW" = ( /obj/structure/cable, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -14281,6 +14127,15 @@ }, /turf/open/floor/iron/dark, /area/station/security/interrogation) +"fls" = ( +/obj/structure/cable, +/obj/effect/decal/cleanable/dirt, +/obj/effect/mapping_helpers/broken_floor, +/obj/effect/decal/cleanable/glass/plastitanium, +/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/greater) "flM" = ( /obj/structure/cable, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -14616,6 +14471,12 @@ /obj/machinery/door/window/brigdoor/right/directional/north, /turf/open/floor/iron/textured_large, /area/station/security/checkpoint/customs) +"frV" = ( +/obj/effect/turf_decal/siding/wood{ + dir = 8 + }, +/turf/open/floor/grass, +/area/station/service/chapel) "fsf" = ( /obj/structure/table/reinforced/titaniumglass, /obj/structure/railing{ @@ -14679,12 +14540,6 @@ /obj/effect/decal/cleanable/dirt, /turf/open/floor/circuit, /area/station/tcommsat/server) -"fsU" = ( -/obj/structure/bed, -/obj/effect/spawner/random/bedsheet, -/obj/machinery/light/small/directional/east, -/turf/open/floor/carpet/royalblack, -/area/station/commons/dorms) "fsV" = ( /obj/structure/cable, /obj/structure/window/reinforced/spawner/directional/east, @@ -15141,6 +14996,13 @@ }, /turf/open/floor/iron/white, /area/station/medical/virology) +"fzw" = ( +/obj/effect/turf_decal/siding/wood{ + dir = 1 + }, +/obj/structure/flora/bush/flowers_br/style_random, +/turf/open/floor/grass, +/area/station/service/chapel) "fzx" = ( /obj/structure/cable, /obj/structure/disposalpipe/segment{ @@ -15529,10 +15391,6 @@ "fEC" = ( /turf/closed/wall, /area/station/maintenance/port/lesser) -"fEE" = ( -/obj/effect/spawner/xmastree, -/turf/open/floor/grass, -/area/station/service/chapel) "fEV" = ( /obj/machinery/porta_turret/ai, /obj/machinery/computer/security/telescreen/minisat{ @@ -15752,6 +15610,12 @@ /obj/effect/turf_decal/tile/yellow, /turf/open/floor/iron, /area/station/hallway/primary/fore) +"fJa" = ( +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/structure/flora/bush/flowers_yw/style_random, +/turf/open/floor/grass, +/area/station/service/chapel) "fJl" = ( /obj/effect/turf_decal/stripes/line{ dir = 9 @@ -15759,6 +15623,14 @@ /obj/item/kirbyplants/random, /turf/open/floor/iron, /area/station/science/xenobiology) +"fJr" = ( +/obj/structure/flora/bush/flowers_pp/style_random, +/obj/effect/landmark/start/hangover, +/obj/effect/turf_decal/siding/wood{ + dir = 8 + }, +/turf/open/floor/grass, +/area/station/service/chapel) "fJs" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -15828,6 +15700,14 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/open/space/basic, /area/space/nearstation) +"fKC" = ( +/obj/effect/landmark/start/hangover, +/obj/effect/turf_decal/siding/wood, +/obj/structure/chair/sofa/bamboo/left{ + dir = 1 + }, +/turf/open/floor/wood/large, +/area/station/service/chapel) "fKO" = ( /obj/structure/disposalpipe/segment, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -16241,6 +16121,12 @@ /obj/machinery/airalarm/directional/west, /turf/open/floor/iron/white, /area/station/medical/medbay/central) +"fRZ" = ( +/obj/structure/cable, +/obj/effect/decal/cleanable/dirt, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/turf/open/floor/plating, +/area/station/maintenance/fore/greater) "fSe" = ( /turf/closed/wall/rust, /area/station/cargo/miningfoundry) @@ -17023,6 +16909,13 @@ }, /turf/open/floor/engine, /area/station/science/explab) +"ggQ" = ( +/obj/effect/turf_decal/siding/wood{ + dir = 10 + }, +/obj/structure/flora/bush/sunny/style_random, +/turf/open/floor/grass, +/area/station/service/chapel) "ggW" = ( /obj/structure/cable, /obj/structure/disposalpipe/segment, @@ -17497,12 +17390,23 @@ /obj/item/radio/intercom/directional/south, /turf/open/floor/iron, /area/station/command/heads_quarters/ce) +"gpq" = ( +/obj/effect/turf_decal/siding/wood{ + dir = 6 + }, +/obj/structure/flora/tree/jungle/small/style_random, +/turf/open/floor/grass, +/area/station/service/chapel) "gpu" = ( /obj/structure/cable, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/plating, /area/station/maintenance/department/medical/central) +"gpx" = ( +/obj/structure/disposalpipe/segment, +/turf/open/floor/wood/large, +/area/station/service/chapel) "gpy" = ( /obj/effect/decal/cleanable/dirt, /obj/item/toy/plush/slimeplushie{ @@ -17994,6 +17898,15 @@ /obj/effect/decal/cleanable/dirt, /turf/open/floor/iron/smooth, /area/station/hallway/secondary/command) +"gxZ" = ( +/obj/structure/cable, +/obj/effect/decal/cleanable/dirt, +/obj/effect/mapping_helpers/broken_floor, +/obj/machinery/power/apc/auto_name/directional/west, +/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/greater) "gyd" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /obj/structure/window/spawner/directional/east, @@ -18289,6 +18202,14 @@ /obj/machinery/portable_atmospherics/canister/plasma, /turf/open/floor/plating, /area/station/engineering/atmos/storage/gas) +"gDO" = ( +/obj/effect/turf_decal/siding/wood{ + dir = 8 + }, +/obj/structure/flora/bush/sunny/style_random, +/obj/machinery/light/small/directional/west, +/turf/open/floor/grass, +/area/station/service/chapel) "gEc" = ( /obj/structure/closet/emcloset, /turf/open/floor/plating, @@ -18634,6 +18555,18 @@ /obj/structure/reagent_dispensers/fueltank, /turf/open/floor/plating, /area/station/maintenance/department/medical/central) +"gKK" = ( +/obj/structure/cable, +/obj/structure/disposalpipe/segment, +/obj/machinery/door/airlock/maintenance{ + name = "Maintenance" + }, +/obj/effect/mapping_helpers/airlock/unres{ + dir = 1 + }, +/obj/effect/mapping_helpers/airlock/access/any/supply/maintenance, +/turf/open/floor/plating, +/area/station/maintenance/port/fore) "gKL" = ( /turf/closed/wall/r_wall, /area/station/engineering/break_room) @@ -19473,6 +19406,15 @@ /obj/effect/turf_decal/tile/neutral, /turf/open/floor/iron, /area/station/hallway/primary/port) +"gYL" = ( +/obj/structure/cable, +/obj/effect/turf_decal/siding/wood{ + dir = 4 + }, +/obj/structure/flora/bush/flowers_pp/style_random, +/obj/machinery/firealarm/directional/east, +/turf/open/floor/grass, +/area/station/service/chapel) "gZf" = ( /obj/machinery/atmospherics/components/unary/portables_connector/visible{ dir = 4 @@ -19782,6 +19724,15 @@ /obj/effect/spawner/structure/window/reinforced/plasma, /turf/open/floor/plating, /area/station/engineering/supermatter/room) +"hee" = ( +/obj/effect/turf_decal/siding/wood{ + dir = 9 + }, +/obj/item/storage/fancy/candle_box, +/obj/machinery/light_switch/directional/west, +/obj/structure/rack/skeletal, +/turf/open/floor/iron/grimy, +/area/station/service/library) "hei" = ( /obj/structure/cable, /obj/effect/spawner/structure/window/reinforced, @@ -19978,13 +19929,6 @@ }, /turf/open/floor/iron/white, /area/station/medical/virology) -"hgj" = ( -/obj/effect/turf_decal/siding/wood{ - dir = 6 - }, -/obj/structure/flora/tree/jungle/small/style_random, -/turf/open/floor/grass, -/area/station/service/chapel) "hgn" = ( /obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2, /turf/open/floor/iron/dark/side{ @@ -20142,6 +20086,13 @@ /obj/effect/spawner/structure/window/reinforced, /turf/open/floor/engine, /area/station/science/cytology) +"hjh" = ( +/obj/effect/turf_decal/siding/wood/corner{ + dir = 4 + }, +/obj/structure/flora/bush/flowers_yw/style_random, +/turf/open/floor/grass, +/area/station/service/chapel) "hji" = ( /obj/structure/window/reinforced/spawner/directional/east, /obj/machinery/status_display/door_timer{ @@ -20302,14 +20253,6 @@ /obj/machinery/meter, /turf/open/floor/iron/smooth, /area/station/engineering/supermatter/room) -"hlC" = ( -/obj/structure/flora/bush/flowers_pp/style_random, -/obj/effect/landmark/start/hangover, -/obj/effect/turf_decal/siding/wood{ - dir = 8 - }, -/turf/open/floor/grass, -/area/station/service/chapel) "hlJ" = ( /obj/machinery/atmospherics/pipe/smart/simple/dark/visible{ dir = 4 @@ -20577,11 +20520,6 @@ dir = 8 }, /area/station/science/lobby) -"hqk" = ( -/obj/effect/turf_decal/siding/wood/corner, -/obj/structure/flora/tree/jungle/small/style_random, -/turf/open/floor/grass, -/area/station/service/chapel) "hqB" = ( /obj/effect/decal/cleanable/dirt, /turf/open/floor/iron/dark, @@ -21392,6 +21330,9 @@ }, /turf/open/floor/plating, /area/station/ai_monitored/command/storage/eva) +"hDI" = ( +/turf/open/floor/wood/large, +/area/station/service/chapel) "hDN" = ( /obj/effect/spawner/structure/window/reinforced/tinted, /turf/open/floor/plating, @@ -21616,6 +21557,11 @@ /obj/effect/decal/cleanable/dirt, /turf/open/floor/iron, /area/station/security/prison/garden) +"hJI" = ( +/obj/structure/disposalpipe/segment, +/obj/machinery/light/floor, +/turf/open/floor/wood/large, +/area/station/service/chapel) "hJO" = ( /obj/structure/cable, /obj/structure/disposalpipe/segment{ @@ -21903,12 +21849,6 @@ /obj/effect/mapping_helpers/broken_floor, /turf/open/floor/iron/smooth, /area/station/maintenance/solars/port/aft) -"hPc" = ( -/obj/structure/bed, -/obj/effect/spawner/random/bedsheet, -/obj/machinery/light/small/directional/east, -/turf/open/floor/carpet/red, -/area/station/commons/dorms) "hPd" = ( /obj/structure/hedge, /obj/effect/turf_decal/tile/brown{ @@ -22399,6 +22339,18 @@ }, /turf/open/floor/iron/dark/smooth_large, /area/station/command/meeting_room) +"hZe" = ( +/obj/structure/disposalpipe/segment{ + dir = 4 + }, +/obj/effect/mapping_helpers/broken_floor, +/obj/structure/sign/poster/random/directional/east, +/obj/machinery/conveyor{ + id = "mining" + }, +/obj/machinery/brm, +/turf/open/floor/iron, +/area/station/cargo/miningfoundry) "hZP" = ( /obj/structure/cable, /obj/structure/sign/poster/official/random/directional/north, @@ -23620,12 +23572,6 @@ /obj/structure/sign/poster/official/random/directional/south, /turf/open/floor/iron/smooth, /area/station/commons/storage/tools) -"ivu" = ( -/obj/structure/cable, -/obj/effect/decal/cleanable/dirt, -/obj/machinery/duct, -/turf/open/floor/iron/kitchen/small, -/area/station/security/prison/mess) "ivx" = ( /obj/machinery/atmospherics/pipe/smart/simple/cyan/visible{ dir = 6 @@ -23962,13 +23908,6 @@ }, /turf/open/floor/carpet/royalblue, /area/station/command/heads_quarters/captain) -"iCj" = ( -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/effect/turf_decal/siding/wood{ - dir = 5 - }, -/turf/open/floor/grass, -/area/station/service/chapel) "iCw" = ( /obj/structure/hedge, /obj/effect/turf_decal/tile/yellow{ @@ -23988,6 +23927,12 @@ }, /turf/open/floor/wood/tile, /area/station/command/meeting_room) +"iDq" = ( +/obj/effect/turf_decal/siding/wood, +/obj/machinery/light/small/directional/south, +/obj/structure/flora/tree/jungle/small/style_random, +/turf/open/floor/grass, +/area/station/service/chapel) "iDt" = ( /obj/effect/mapping_helpers/airlock/access/any/security/general, /obj/machinery/door/airlock/security{ @@ -24107,10 +24052,6 @@ }, /turf/open/floor/plating, /area/station/maintenance/fore/lesser) -"iFH" = ( -/obj/machinery/light/floor, -/turf/open/floor/wood/large, -/area/station/service/chapel) "iFP" = ( /obj/item/kirbyplants/random/fullysynthetic, /turf/open/floor/plating/rust, @@ -24787,10 +24728,6 @@ "iSr" = ( /turf/open/floor/iron, /area/station/security/execution/transfer) -"iSu" = ( -/obj/structure/flora/bush/sunny/style_random, -/turf/open/floor/grass, -/area/station/service/chapel) "iSK" = ( /obj/structure/cable, /obj/structure/disposalpipe/segment{ @@ -24799,6 +24736,14 @@ /obj/structure/sign/warning/pods/directional/west, /turf/open/floor/iron/checker, /area/station/security/breakroom) +"iSW" = ( +/obj/structure/rack, +/obj/item/clothing/gloves/boxing/yellow, +/obj/item/clothing/gloves/boxing/green{ + pixel_y = 4 + }, +/turf/open/floor/plating, +/area/station/maintenance/fore/greater) "iTn" = ( /obj/machinery/firealarm/directional/north, /obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2{ @@ -24869,6 +24814,10 @@ /obj/machinery/light/small/directional/west, /turf/open/floor/plating, /area/station/engineering/atmos) +"iUy" = ( +/obj/structure/reagent_dispensers/plumbed, +/turf/open/floor/plating, +/area/station/maintenance/fore/greater) "iUz" = ( /obj/structure/falsewall, /turf/open/floor/iron, @@ -25260,6 +25209,10 @@ }, /turf/open/floor/circuit, /area/station/tcommsat/server) +"jau" = ( +/obj/structure/altar_of_gods, +/turf/open/floor/wood/large, +/area/station/service/chapel) "jax" = ( /obj/structure/disposalpipe/segment, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -25269,6 +25222,10 @@ /obj/effect/turf_decal/tile/neutral, /turf/open/floor/iron, /area/station/hallway/primary/fore) +"jaA" = ( +/obj/effect/turf_decal/siding/wood, +/turf/open/floor/grass, +/area/station/service/chapel) "jaD" = ( /obj/effect/turf_decal/siding/thinplating_new/terracotta{ dir = 1 @@ -25321,6 +25278,14 @@ "jaQ" = ( /turf/open/floor/catwalk_floor/iron_dark, /area/station/security/processing) +"jaW" = ( +/obj/effect/turf_decal/siding/wood{ + dir = 4 + }, +/obj/structure/flora/bush/flowers_yw/style_random, +/obj/machinery/light/small/directional/east, +/turf/open/floor/grass, +/area/station/service/chapel) "jbb" = ( /obj/effect/mapping_helpers/broken_floor, /turf/open/floor/plating, @@ -25580,6 +25545,10 @@ /obj/machinery/airalarm/directional/west, /turf/open/floor/iron, /area/station/maintenance/port/fore) +"jhz" = ( +/obj/structure/disposalpipe/segment, +/turf/open/floor/grass, +/area/station/service/chapel) "jhA" = ( /obj/machinery/vending/boozeomat, /obj/effect/mapping_helpers/broken_floor, @@ -26554,6 +26523,13 @@ /obj/structure/broken_flooring/singular/directional/south, /turf/open/floor/iron, /area/station/hallway/secondary/dock) +"jzO" = ( +/obj/effect/landmark/start/assistant, +/obj/structure/chair/sofa/bamboo/right{ + dir = 1 + }, +/turf/open/floor/wood/large, +/area/station/service/chapel) "jAb" = ( /obj/structure/cable, /turf/open/floor/iron/stairs{ @@ -27528,6 +27504,14 @@ /obj/effect/spawner/structure/window/reinforced/tinted, /turf/open/floor/plating, /area/station/maintenance/fore/greater) +"jPr" = ( +/obj/structure/cable, +/obj/effect/decal/cleanable/dirt, +/obj/effect/mapping_helpers/broken_floor, +/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/greater) "jQo" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/machinery/door/airlock/research/glass{ @@ -27696,12 +27680,6 @@ /obj/machinery/camera/autoname/directional/north, /turf/open/floor/iron, /area/station/cargo/storage) -"jTP" = ( -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/effect/turf_decal/siding/wood, -/turf/open/floor/grass, -/area/station/service/chapel) "jTU" = ( /obj/structure/disposalpipe/segment{ dir = 4 @@ -27861,6 +27839,12 @@ /obj/machinery/holopad/secure, /turf/open/floor/iron/smooth, /area/station/hallway/secondary/command) +"jXg" = ( +/obj/effect/turf_decal/siding/wood{ + dir = 4 + }, +/turf/open/floor/grass, +/area/station/service/chapel) "jXi" = ( /obj/structure/cable, /obj/machinery/door/airlock{ @@ -28280,18 +28264,6 @@ "kev" = ( /turf/closed/wall, /area/station/hallway/secondary/spacebridge) -"keI" = ( -/obj/structure/cable, -/obj/structure/disposalpipe/segment, -/obj/machinery/door/airlock/maintenance{ - name = "Maintenance" - }, -/obj/effect/mapping_helpers/airlock/unres{ - dir = 1 - }, -/obj/effect/mapping_helpers/airlock/access/any/supply/maintenance, -/turf/open/floor/plating, -/area/station/maintenance/port/fore) "keZ" = ( /obj/structure/cable, /obj/structure/disposalpipe/segment{ @@ -28344,13 +28316,6 @@ /obj/effect/turf_decal/tile/neutral, /turf/open/floor/iron, /area/station/hallway/primary/central/fore) -"kge" = ( -/obj/effect/turf_decal/siding/wood{ - dir = 4 - }, -/obj/structure/flora/bush/flowers_br/style_random, -/turf/open/floor/grass, -/area/station/service/chapel) "kgh" = ( /obj/structure/cable, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -28421,6 +28386,14 @@ /obj/structure/tram, /turf/open/floor/tram, /area/station/security/tram) +"khu" = ( +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/effect/turf_decal/siding/wood{ + dir = 8 + }, +/turf/open/floor/grass, +/area/station/service/chapel) "khD" = ( /obj/effect/decal/cleanable/dirt, /obj/structure/reagent_dispensers/watertank, @@ -28659,6 +28632,12 @@ /obj/item/storage/backpack/duffelbag, /turf/open/floor/plating, /area/station/maintenance/fore/greater) +"kld" = ( +/obj/structure/cable, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/duct, +/turf/open/floor/iron/kitchen/small, +/area/station/security/prison/mess) "klf" = ( /obj/effect/decal/cleanable/dirt, /obj/structure/chair{ @@ -29843,10 +29822,6 @@ /obj/effect/mapping_helpers/broken_floor, /turf/open/floor/iron/dark/smooth_large, /area/station/command/meeting_room) -"kGO" = ( -/obj/structure/flora/bush/flowers_br/style_random, -/turf/open/floor/grass, -/area/station/service/chapel) "kGS" = ( /turf/open/floor/iron/white, /area/station/maintenance/central/greater) @@ -30022,10 +29997,6 @@ /obj/effect/turf_decal/tile/neutral, /turf/open/floor/iron, /area/station/hallway/primary/central/fore) -"kJl" = ( -/obj/effect/turf_decal/siding/wood, -/turf/open/floor/grass, -/area/station/service/chapel) "kJp" = ( /obj/effect/turf_decal/stripes/line{ dir = 8 @@ -30374,14 +30345,6 @@ "kQt" = ( /turf/closed/wall/r_wall, /area/station/maintenance/starboard/aft) -"kQv" = ( -/obj/structure/cable, -/obj/effect/decal/cleanable/dirt, -/obj/effect/mapping_helpers/broken_floor, -/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/greater) "kQA" = ( /obj/structure/table, /obj/machinery/microwave{ @@ -30581,14 +30544,6 @@ /obj/effect/decal/cleanable/dirt, /turf/open/floor/iron/dark, /area/station/security/office) -"kUx" = ( -/obj/structure/cable, -/obj/effect/turf_decal/siding/wood{ - dir = 4 - }, -/obj/machinery/power/apc/auto_name/directional/east, -/turf/open/floor/grass, -/area/station/service/chapel) "kUy" = ( /obj/effect/decal/cleanable/dirt, /obj/machinery/atmospherics/components/trinary/filter/flipped/critical{ @@ -30806,6 +30761,16 @@ /obj/item/modular_computer/laptop, /turf/open/floor/iron/grimy, /area/station/science/cubicle) +"kZo" = ( +/obj/structure/cable, +/obj/effect/decal/cleanable/dirt, +/obj/effect/spawner/random/trash, +/obj/effect/decal/cleanable/dirt, +/obj/effect/mapping_helpers/broken_floor, +/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/greater) "kZx" = ( /obj/machinery/button/door/directional/north{ id = "main_surgery"; @@ -30890,13 +30855,6 @@ /obj/machinery/light/small/directional/north, /turf/open/floor/wood, /area/station/service/abandoned_gambling_den) -"lbz" = ( -/obj/effect/landmark/start/assistant, -/obj/structure/chair/sofa/bamboo/right{ - dir = 1 - }, -/turf/open/floor/wood/large, -/area/station/service/chapel) "lbF" = ( /obj/effect/turf_decal/siding/thinplating_new/dark{ dir = 1 @@ -31543,6 +31501,14 @@ /obj/structure/window/reinforced/spawner/directional/west, /turf/open/floor/iron, /area/station/maintenance/fore/greater) +"lja" = ( +/obj/effect/turf_decal/siding/wood{ + dir = 8 + }, +/obj/structure/flora/bush/flowers_yw/style_random, +/obj/effect/landmark/start/hangover, +/turf/open/floor/grass, +/area/station/service/chapel) "ljk" = ( /obj/effect/turf_decal/stripes/line{ dir = 8 @@ -31796,6 +31762,12 @@ /obj/item/kirbyplants/random, /turf/open/floor/iron/grimy, /area/station/command/heads_quarters/qm) +"lmB" = ( +/obj/effect/turf_decal/siding/wood, +/obj/structure/flora/bush/sunny/style_random, +/obj/machinery/newscaster/directional/south, +/turf/open/floor/grass, +/area/station/service/chapel) "lmG" = ( /obj/effect/turf_decal/sand/plating, /obj/effect/decal/cleanable/dirt, @@ -31997,14 +31969,6 @@ }, /turf/open/floor/iron/dark, /area/station/security/office) -"lsz" = ( -/obj/effect/turf_decal/siding/wood{ - dir = 9 - }, -/obj/structure/flora/tree/jungle/small/style_random, -/obj/structure/flora/bush/flowers_pp/style_random, -/turf/open/floor/grass, -/area/station/service/chapel) "lsJ" = ( /obj/structure/window/spawner/directional/north, /obj/effect/turf_decal/stripes/end{ @@ -32146,6 +32110,11 @@ /obj/machinery/door/firedoor, /turf/open/floor/iron/cafeteria, /area/station/service/kitchen) +"luX" = ( +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/light/floor, +/turf/open/floor/wood/large, +/area/station/service/chapel) "lvc" = ( /turf/open/floor/iron/smooth, /area/station/security/checkpoint/escape) @@ -32382,6 +32351,12 @@ /obj/structure/cable, /turf/open/floor/iron/textured_half, /area/station/service/janitor) +"lyC" = ( +/obj/structure/table/glass, +/obj/item/radio/intercom/directional/east, +/obj/machinery/recharger, +/turf/open/floor/iron/white, +/area/station/science/auxlab/firing_range) "lyQ" = ( /obj/structure/table, /obj/item/storage/photo_album/prison, @@ -32858,6 +32833,12 @@ /obj/structure/chair/stool/directional/south, /turf/open/floor/carpet/donk, /area/station/command/heads_quarters/qm) +"lHi" = ( +/obj/structure/cable, +/obj/effect/decal/cleanable/dirt, +/obj/machinery/duct, +/turf/open/floor/iron/kitchen/small, +/area/station/security/prison/mess) "lHk" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -34389,6 +34370,13 @@ /obj/effect/decal/cleanable/dirt, /turf/open/floor/iron/dark/smooth_edge, /area/station/maintenance/starboard/greater) +"mfD" = ( +/obj/effect/turf_decal/siding/wood/corner{ + dir = 8 + }, +/obj/structure/flora/tree/stump, +/turf/open/floor/grass, +/area/station/service/chapel) "mfK" = ( /obj/structure/window/reinforced/plasma/spawner/directional/east, /obj/effect/turf_decal/stripes/line{ @@ -34894,10 +34882,6 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/orange/hidden/layer1, /turf/open/floor/iron/small, /area/station/engineering/main) -"mpA" = ( -/obj/structure/disposalpipe/segment, -/turf/open/floor/wood/large, -/area/station/service/chapel) "mpC" = ( /obj/structure/table, /obj/item/paper_bin{ @@ -35488,14 +35472,6 @@ /obj/structure/sign/poster/official/soft_cap_pop_art/directional/north, /turf/open/floor/iron/grimy, /area/station/commons/vacant_room/office) -"mBG" = ( -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/effect/turf_decal/siding/wood{ - dir = 8 - }, -/turf/open/floor/grass, -/area/station/service/chapel) "mBQ" = ( /obj/structure/cable, /obj/structure/window/reinforced/spawner/directional/south, @@ -35623,13 +35599,6 @@ /obj/structure/cable, /turf/open/floor/iron, /area/station/security) -"mDM" = ( -/obj/effect/turf_decal/siding/wood{ - dir = 1 - }, -/obj/structure/flora/tree/jungle/small/style_random, -/turf/open/floor/grass, -/area/station/service/chapel) "mDU" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/structure/disposalpipe/segment, @@ -35770,11 +35739,6 @@ /obj/structure/cable, /turf/open/floor/eighties, /area/station/service/abandoned_gambling_den/gaming) -"mGe" = ( -/obj/structure/disposalpipe/segment, -/obj/machinery/light/floor, -/turf/open/floor/wood/large, -/area/station/service/chapel) "mGg" = ( /obj/structure/cable, /obj/structure/disposalpipe/segment{ @@ -35831,6 +35795,13 @@ /obj/effect/mapping_helpers/airlock/access/any/service/maintenance, /turf/open/floor/plating, /area/station/maintenance/fore/greater) +"mGV" = ( +/obj/effect/turf_decal/siding/wood{ + dir = 4 + }, +/obj/structure/flora/bush/flowers_br/style_random, +/turf/open/floor/grass, +/area/station/service/chapel) "mGY" = ( /obj/effect/turf_decal/stripes/line, /turf/open/floor/iron/smooth, @@ -36029,6 +36000,15 @@ /obj/effect/mapping_helpers/requests_console/assistance, /turf/open/floor/iron/stairs, /area/station/engineering/break_room) +"mKB" = ( +/obj/machinery/navbeacon{ + codes_txt = "delivery;dir=8"; + location = "QM #1" + }, +/obj/effect/turf_decal/delivery, +/mob/living/simple_animal/bot/mulebot, +/turf/open/floor/iron, +/area/station/cargo/storage) "mKD" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /obj/effect/turf_decal/tile/red{ @@ -36350,13 +36330,6 @@ }, /turf/open/floor/iron, /area/station/cargo/storage) -"mQv" = ( -/obj/effect/turf_decal/siding/wood{ - dir = 1 - }, -/obj/structure/flora/bush/flowers_pp/style_random, -/turf/open/floor/grass, -/area/station/service/chapel) "mQz" = ( /obj/effect/turf_decal/tile/neutral/fourcorners, /obj/structure/chair/office{ @@ -36685,11 +36658,6 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/plating, /area/station/maintenance/starboard/aft) -"mXn" = ( -/obj/effect/turf_decal/siding/wood, -/obj/structure/flora/bush/flowers_br/style_random, -/turf/open/floor/grass, -/area/station/service/chapel) "mXt" = ( /obj/machinery/rnd/production/techfab/department/medical, /obj/effect/turf_decal/stripes/box, @@ -36717,10 +36685,6 @@ }, /turf/open/floor/iron/smooth, /area/station/security/checkpoint/customs) -"mYk" = ( -/obj/effect/spawner/random/engineering/tracking_beacon, -/turf/open/floor/grass, -/area/station/service/chapel) "mYm" = ( /obj/effect/turf_decal/siding/thinplating_new/light{ dir = 10 @@ -36819,21 +36783,6 @@ }, /turf/open/floor/iron, /area/station/hallway/primary/central/fore) -"mZt" = ( -/obj/structure/cable, -/obj/structure/disposalpipe/segment{ - dir = 5 - }, -/obj/effect/decal/cleanable/dirt, -/obj/machinery/button/door/directional/east{ - id = "qm_warehouse_aft"; - name = "Warehouse Door Control"; - pixel_x = -24; - pixel_y = -23; - req_access = list("cargo") - }, -/turf/open/floor/plating, -/area/station/maintenance/port/fore) "mZw" = ( /obj/machinery/navbeacon{ codes_txt = "delivery;dir=4"; @@ -37335,6 +37284,14 @@ /obj/machinery/duct, /turf/open/floor/plating, /area/station/maintenance/fore/greater) +"njq" = ( +/obj/structure/disposalpipe/segment, +/obj/effect/landmark/start/assistant, +/obj/structure/chair/sofa/bamboo/left{ + dir = 1 + }, +/turf/open/floor/wood/large, +/area/station/service/chapel) "njA" = ( /obj/machinery/photocopier, /obj/structure/sign/poster/official/random/directional/north, @@ -37402,12 +37359,6 @@ /obj/effect/turf_decal/trimline/neutral/line, /turf/open/floor/iron, /area/station/hallway/primary/starboard) -"nkW" = ( -/obj/effect/turf_decal/siding/wood{ - dir = 1 - }, -/turf/open/floor/wood/large, -/area/station/service/chapel) "nkY" = ( /obj/structure/chair/sofa/bench/right{ dir = 4 @@ -37627,6 +37578,13 @@ }, /turf/open/floor/iron/dark, /area/station/ai_monitored/security/armory) +"npl" = ( +/obj/effect/turf_decal/siding/wood{ + dir = 10 + }, +/obj/structure/flora/bush/flowers_br/style_random, +/turf/open/floor/grass, +/area/station/service/chapel) "npp" = ( /obj/structure/cable, /turf/open/floor/plating, @@ -38032,6 +37990,14 @@ dir = 1 }, /area/station/hallway/secondary/dock) +"nwu" = ( +/obj/effect/turf_decal/siding/wood{ + dir = 9 + }, +/obj/structure/flora/tree/jungle/small/style_random, +/obj/structure/flora/bush/flowers_pp/style_random, +/turf/open/floor/grass, +/area/station/service/chapel) "nwN" = ( /obj/effect/turf_decal/tile/neutral{ dir = 1 @@ -38222,6 +38188,13 @@ /obj/machinery/light_switch/directional/west, /turf/open/floor/iron/dark, /area/station/medical/pharmacy) +"nzH" = ( +/obj/effect/turf_decal/siding/wood{ + dir = 5 + }, +/obj/machinery/airalarm/directional/north, +/turf/open/floor/grass, +/area/station/service/chapel) "nzK" = ( /obj/structure/cable, /obj/item/ammo_casing/spent{ @@ -38774,14 +38747,6 @@ /obj/effect/decal/cleanable/dirt, /turf/open/floor/iron/white/corner, /area/station/science/xenobiology) -"nIH" = ( -/obj/machinery/door/airlock/hatch{ - name = "Centcom Dock" - }, -/obj/effect/mapping_helpers/airlock/access/any/command/general, -/obj/effect/mapping_helpers/airlock/access/any/admin/general, -/turf/open/floor/plating, -/area/station/maintenance/department/science/xenobiology) "nIJ" = ( /obj/effect/turf_decal/stripes/line{ dir = 1 @@ -40057,6 +40022,12 @@ /obj/machinery/light/cold/directional/east, /turf/open/floor/iron/dark/small, /area/station/security/checkpoint/customs) +"ohO" = ( +/obj/structure/bed, +/obj/effect/spawner/random/bedsheet, +/obj/machinery/light/small/directional/east, +/turf/open/floor/carpet/red, +/area/station/commons/dorms) "ohQ" = ( /obj/structure/curtain/cloth, /turf/open/floor/carpet/orange, @@ -40251,6 +40222,11 @@ }, /turf/open/floor/iron/checker, /area/station/security/breakroom) +"omi" = ( +/obj/structure/disposalpipe/segment, +/obj/effect/turf_decal/siding/wood, +/turf/open/floor/grass, +/area/station/service/chapel) "omp" = ( /obj/structure/cable, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -40279,6 +40255,13 @@ /obj/structure/cable, /turf/open/floor/plating, /area/station/engineering/engine_smes) +"omM" = ( +/obj/effect/turf_decal/siding/wood{ + dir = 5 + }, +/obj/machinery/light/directional/east, +/turf/open/floor/grass, +/area/station/service/chapel) "omW" = ( /obj/structure/reagent_dispensers/watertank, /turf/open/floor/iron/white/corner, @@ -40508,10 +40491,6 @@ /obj/effect/turf_decal/tile/dark_red/half/contrasted, /turf/open/floor/iron, /area/station/security/execution/transfer) -"orv" = ( -/obj/structure/altar_of_gods, -/turf/open/floor/wood/large, -/area/station/service/chapel) "orC" = ( /obj/structure/cable, /turf/open/floor/iron/smooth, @@ -40595,6 +40574,10 @@ /obj/machinery/camera/autoname/directional/north, /turf/open/floor/iron/smooth_half, /area/station/engineering/atmos) +"osX" = ( +/obj/structure/flora/bush/sunny/style_random, +/turf/open/floor/grass, +/area/station/service/chapel) "osY" = ( /obj/effect/decal/cleanable/dirt, /obj/structure/broken_flooring/corner/directional/south, @@ -40859,10 +40842,6 @@ }, /turf/open/floor/iron/dark, /area/station/engineering/atmos) -"oxe" = ( -/obj/structure/disposalpipe/segment, -/turf/open/floor/grass, -/area/station/service/chapel) "oxw" = ( /obj/structure/disposalpipe/segment, /obj/effect/turf_decal/stripes/white/line{ @@ -41131,15 +41110,6 @@ /obj/machinery/light/floor, /turf/open/floor/iron/smooth, /area/station/hallway/secondary/command) -"oDb" = ( -/obj/structure/cable, -/obj/effect/decal/cleanable/dirt, -/obj/effect/mapping_helpers/broken_floor, -/obj/machinery/power/apc/auto_name/directional/west, -/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/greater) "oDc" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -41225,15 +41195,6 @@ }, /turf/open/floor/engine, /area/station/science/xenobiology) -"oEC" = ( -/obj/structure/cable, -/obj/effect/turf_decal/siding/wood{ - dir = 4 - }, -/obj/structure/flora/bush/flowers_pp/style_random, -/obj/machinery/firealarm/directional/east, -/turf/open/floor/grass, -/area/station/service/chapel) "oED" = ( /obj/effect/turf_decal/tile/blue{ dir = 1 @@ -41547,6 +41508,10 @@ /obj/effect/mapping_helpers/airlock/access/all/security/armory, /turf/open/floor/iron/textured_half, /area/station/security/warden) +"oKK" = ( +/obj/effect/spawner/random/engineering/tracking_beacon, +/turf/open/floor/grass, +/area/station/service/chapel) "oKP" = ( /obj/machinery/light/small/directional/east, /obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ @@ -41701,13 +41666,6 @@ /obj/effect/spawner/random/engineering/atmospherics_portable, /turf/open/floor/plating, /area/station/maintenance/starboard/fore) -"oOf" = ( -/obj/effect/turf_decal/siding/wood{ - dir = 10 - }, -/obj/structure/flora/bush/flowers_br/style_random, -/turf/open/floor/grass, -/area/station/service/chapel) "oOg" = ( /obj/effect/decal/cleanable/dirt, /obj/machinery/light/small/directional/north, @@ -42984,13 +42942,6 @@ /obj/structure/window/spawner/directional/south, /turf/open/floor/iron/showroomfloor, /area/station/command/corporate_showroom) -"pkp" = ( -/obj/effect/turf_decal/siding/wood{ - dir = 1 - }, -/obj/effect/landmark/start/chaplain, -/turf/open/floor/wood/large, -/area/station/service/chapel) "pks" = ( /obj/effect/landmark/event_spawn, /obj/effect/turf_decal/tile/green/opposingcorners{ @@ -43388,12 +43339,6 @@ /obj/item/kirbyplants/random, /turf/open/floor/iron/white, /area/station/medical/medbay/lobby) -"pqZ" = ( -/obj/structure/table/wood, -/obj/item/paper_bin, -/obj/item/pen, -/turf/open/floor/carpet/lone, -/area/station/service/chapel/office) "prf" = ( /obj/structure/cable, /obj/effect/spawner/structure/window/reinforced, @@ -43691,6 +43636,12 @@ /obj/effect/decal/cleanable/dirt, /turf/open/floor/iron/white/small, /area/station/service/hydroponics/garden) +"pwg" = ( +/obj/effect/turf_decal/siding/wood{ + dir = 1 + }, +/turf/open/floor/grass, +/area/station/service/chapel) "pwn" = ( /obj/effect/spawner/random/vending/colavend, /obj/structure/sign/departments/telecomms/directional/south, @@ -44889,9 +44840,6 @@ /obj/effect/decal/cleanable/dirt, /turf/open/floor/plating, /area/station/maintenance/starboard/fore) -"pPF" = ( -/turf/open/floor/wood/large, -/area/station/service/chapel) "pPK" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -45271,6 +45219,13 @@ /obj/machinery/firealarm/directional/west, /turf/open/floor/iron/white, /area/station/science/auxlab/firing_range) +"pVf" = ( +/obj/effect/turf_decal/siding/wood, +/obj/structure/chair/sofa/bamboo/right{ + dir = 1 + }, +/turf/open/floor/wood/large, +/area/station/service/chapel) "pVo" = ( /obj/effect/decal/cleanable/dirt, /obj/structure/girder, @@ -46146,6 +46101,13 @@ }, /turf/open/space/basic, /area/space/nearstation) +"qiu" = ( +/obj/effect/turf_decal/siding/wood{ + dir = 4 + }, +/obj/machinery/light/small/directional/east, +/turf/open/floor/grass, +/area/station/service/chapel) "qiw" = ( /obj/effect/decal/cleanable/dirt, /turf/open/floor/iron, @@ -46715,6 +46677,11 @@ /obj/effect/mapping_helpers/broken_floor, /turf/open/floor/iron, /area/station/maintenance/department/medical/central) +"qsw" = ( +/obj/effect/turf_decal/siding/wood/corner, +/obj/structure/flora/tree/jungle/small/style_random, +/turf/open/floor/grass, +/area/station/service/chapel) "qsA" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /obj/effect/turf_decal/siding/wood, @@ -46861,6 +46828,14 @@ "quU" = ( /turf/closed/wall/r_wall, /area/station/command/heads_quarters/captain) +"qvm" = ( +/obj/structure/cable, +/obj/effect/turf_decal/siding/wood{ + dir = 4 + }, +/obj/machinery/power/apc/auto_name/directional/east, +/turf/open/floor/grass, +/area/station/service/chapel) "qvr" = ( /obj/structure/closet/firecloset, /turf/open/floor/plating, @@ -47025,14 +47000,6 @@ /obj/item/restraints/handcuffs/fake, /turf/open/floor/plating, /area/station/maintenance/fore/greater) -"qxz" = ( -/obj/effect/turf_decal/siding/wood{ - dir = 4 - }, -/obj/structure/flora/bush/flowers_yw/style_random, -/obj/machinery/light/small/directional/east, -/turf/open/floor/grass, -/area/station/service/chapel) "qxN" = ( /obj/structure/disposalpipe/segment{ dir = 4 @@ -47524,18 +47491,6 @@ /obj/effect/decal/cleanable/dirt, /turf/open/floor/iron/dark, /area/station/security/processing) -"qFn" = ( -/obj/structure/disposalpipe/segment{ - dir = 4 - }, -/obj/effect/mapping_helpers/broken_floor, -/obj/structure/sign/poster/random/directional/east, -/obj/machinery/conveyor{ - id = "mining" - }, -/obj/machinery/brm, -/turf/open/floor/iron, -/area/station/cargo/miningfoundry) "qFv" = ( /obj/effect/turf_decal/tile/green{ dir = 8 @@ -48498,22 +48453,10 @@ /obj/effect/turf_decal/stripes/red/line, /turf/open/floor/iron/small, /area/station/hallway/primary/central/fore) -"qWn" = ( -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/machinery/light/floor, -/turf/open/floor/wood/large, -/area/station/service/chapel) "qWo" = ( /obj/effect/spawner/structure/window/reinforced/tinted, /turf/open/floor/plating, /area/station/medical/psychology) -"qWt" = ( -/obj/effect/turf_decal/siding/wood/corner{ - dir = 8 - }, -/obj/structure/flora/tree/stump, -/turf/open/floor/grass, -/area/station/service/chapel) "qWF" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -48816,6 +48759,10 @@ }, /turf/open/floor/tram, /area/station/security/tram) +"rat" = ( +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/turf/open/floor/wood/large, +/area/station/service/chapel) "raz" = ( /obj/machinery/door/airlock/public/glass{ name = "Lavatorie" @@ -49589,6 +49536,13 @@ /obj/effect/turf_decal/sand/plating, /turf/open/floor/wood/tile, /area/station/maintenance/port/lesser) +"row" = ( +/obj/effect/decal/cleanable/dirt, +/obj/structure/reagent_dispensers/plumbed{ + dir = 4 + }, +/turf/open/floor/plating, +/area/station/maintenance/central/greater) "roz" = ( /obj/structure/cable, /turf/open/floor/plating, @@ -50018,6 +49972,14 @@ "ruY" = ( /turf/open/floor/plating, /area/station/maintenance/fore/lesser) +"rvf" = ( +/obj/effect/landmark/start/assistant, +/obj/effect/landmark/start/assistant, +/obj/structure/chair/sofa/bamboo/left{ + dir = 1 + }, +/turf/open/floor/wood/large, +/area/station/service/chapel) "rvp" = ( /turf/closed/mineral/random/stationside, /area/station/maintenance/hallway/abandoned_command) @@ -51099,14 +51061,6 @@ /obj/effect/landmark/generic_maintenance_landmark, /turf/open/floor/iron/grimy, /area/station/commons/vacant_room/office) -"rMj" = ( -/obj/structure/disposalpipe/segment, -/obj/effect/landmark/start/assistant, -/obj/structure/chair/sofa/bamboo/left{ - dir = 1 - }, -/turf/open/floor/wood/large, -/area/station/service/chapel) "rMl" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -51163,6 +51117,9 @@ /obj/effect/decal/cleanable/dirt, /turf/open/floor/plating, /area/station/maintenance/central/greater) +"rMX" = ( +/turf/open/floor/grass, +/area/station/service/chapel) "rMY" = ( /obj/structure/cable, /obj/structure/disposalpipe/segment{ @@ -51975,13 +51932,6 @@ }, /turf/open/floor/iron, /area/station/hallway/primary/central/fore) -"rZF" = ( -/obj/effect/turf_decal/siding/wood, -/obj/structure/chair/sofa/bamboo/right{ - dir = 1 - }, -/turf/open/floor/wood/large, -/area/station/service/chapel) "rZG" = ( /obj/structure/closet/crate/trashcart, /obj/effect/spawner/random/trash/food_packaging, @@ -52225,6 +52175,11 @@ /obj/machinery/airalarm/directional/north, /turf/open/floor/iron/cafeteria, /area/station/service/kitchen) +"scM" = ( +/obj/effect/turf_decal/siding/wood, +/obj/structure/flora/bush/flowers_br/style_random, +/turf/open/floor/grass, +/area/station/service/chapel) "sdf" = ( /obj/item/kirbyplants/random/fullysynthetic, /obj/machinery/light_switch/directional/east, @@ -52284,6 +52239,12 @@ }, /turf/open/floor/iron/smooth_large, /area/station/science/auxlab/firing_range) +"seN" = ( +/obj/effect/turf_decal/siding/wood/corner{ + dir = 4 + }, +/turf/open/floor/grass, +/area/station/service/chapel) "seV" = ( /obj/structure/transit_tube/horizontal, /obj/structure/lattice/catwalk, @@ -52562,12 +52523,6 @@ /obj/effect/turf_decal/tile/neutral, /turf/open/floor/iron, /area/station/hallway/primary/central/fore) -"siH" = ( -/obj/effect/turf_decal/siding/wood{ - dir = 4 - }, -/turf/open/floor/grass, -/area/station/service/chapel) "siN" = ( /obj/machinery/hydroponics/constructable, /obj/machinery/camera/directional/west, @@ -52577,6 +52532,12 @@ /obj/machinery/atmospherics/components/unary/vent_pump/on/layer4, /turf/open/floor/wood, /area/station/service/theater) +"sjk" = ( +/obj/structure/table/wood, +/obj/item/paper_bin, +/obj/item/pen, +/turf/open/floor/carpet/lone, +/area/station/service/chapel/office) "sjp" = ( /obj/structure/cable, /obj/effect/decal/cleanable/dirt, @@ -52912,6 +52873,13 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/iron/smooth, /area/station/hallway/secondary/command) +"soR" = ( +/obj/effect/turf_decal/siding/wood{ + dir = 1 + }, +/obj/structure/flora/bush/flowers_pp/style_random, +/turf/open/floor/grass, +/area/station/service/chapel) "spg" = ( /obj/effect/mapping_helpers/airlock/access/any/security/general, /obj/machinery/door/airlock/security{ @@ -53835,6 +53803,12 @@ /obj/effect/turf_decal/delivery, /turf/open/floor/iron/kitchen/small, /area/station/hallway/secondary/service) +"sDR" = ( +/obj/effect/turf_decal/siding/wood/corner{ + dir = 1 + }, +/turf/open/floor/grass, +/area/station/service/chapel) "sDT" = ( /obj/machinery/firealarm/directional/north, /obj/structure/cable, @@ -53862,6 +53836,13 @@ }, /turf/open/floor/engine, /area/station/science/cytology) +"sEs" = ( +/obj/structure/cable, +/obj/effect/turf_decal/siding/wood{ + dir = 4 + }, +/turf/open/floor/grass, +/area/station/service/chapel) "sEz" = ( /obj/structure/cable, /obj/effect/mapping_helpers/broken_floor, @@ -54370,14 +54351,6 @@ /obj/effect/mapping_helpers/broken_floor, /turf/open/floor/plating, /area/station/maintenance/port/fore) -"sNR" = ( -/obj/structure/cable, -/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ - dir = 8 - }, -/obj/machinery/duct, -/turf/open/floor/iron/kitchen/small, -/area/station/security/prison/mess) "sNW" = ( /obj/structure/rack, /obj/effect/spawner/random/maintenance, @@ -54498,6 +54471,12 @@ /obj/machinery/duct, /turf/open/floor/iron/freezer, /area/station/service/kitchen/coldroom) +"sPZ" = ( +/obj/structure/disposalpipe/segment, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/light/floor, +/turf/open/floor/wood/large, +/area/station/service/chapel) "sQb" = ( /obj/effect/spawner/structure/window, /turf/open/floor/plating, @@ -54919,10 +54898,6 @@ /obj/effect/decal/cleanable/dirt, /turf/open/floor/iron, /area/station/hallway/secondary/recreation) -"sXg" = ( -/obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2, -/turf/open/floor/wood/large, -/area/station/service/chapel) "sXi" = ( /obj/structure/disposalpipe/segment, /turf/open/floor/iron/white, @@ -55007,11 +54982,6 @@ /obj/machinery/light/small/directional/east, /turf/open/floor/engine, /area/station/science/cytology) -"sYh" = ( -/obj/structure/table/wood, -/obj/item/book/bible, -/turf/open/floor/wood/large, -/area/station/service/chapel) "sYo" = ( /obj/effect/spawner/random/entertainment/arcade, /obj/machinery/airalarm/directional/north, @@ -56009,6 +55979,13 @@ /obj/machinery/light/small/directional/south, /turf/open/floor/iron/dark/small, /area/station/medical/morgue) +"tqv" = ( +/obj/structure/disposalpipe/segment, +/obj/effect/turf_decal/siding/wood{ + dir = 1 + }, +/turf/open/floor/wood/large, +/area/station/service/chapel) "tqz" = ( /obj/structure/sign/poster/official/random/directional/north, /obj/effect/turf_decal/tile/green/diagonal_centre, @@ -56093,6 +56070,13 @@ "trp" = ( /turf/closed/wall, /area/station/maintenance/port/aft) +"trv" = ( +/obj/effect/turf_decal/siding/wood{ + dir = 1 + }, +/obj/structure/flora/bush/flowers_yw/style_random, +/turf/open/floor/grass, +/area/station/service/chapel) "trz" = ( /obj/structure/disposalpipe/segment, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -56359,16 +56343,6 @@ /obj/structure/disposalpipe/segment, /turf/open/floor/plating, /area/station/maintenance/department/medical/central) -"twI" = ( -/obj/structure/bed{ - dir = 4 - }, -/obj/effect/spawner/random/bedsheet{ - dir = 4 - }, -/obj/machinery/light/small/directional/west, -/turf/open/floor/carpet/orange, -/area/station/commons/dorms) "twJ" = ( /obj/structure/disposalpipe/segment{ dir = 4 @@ -56674,12 +56648,6 @@ /obj/effect/decal/cleanable/cobweb/cobweb2, /turf/open/floor/iron, /area/station/security/courtroom) -"tBk" = ( -/obj/effect/turf_decal/siding/wood, -/obj/machinery/light/small/directional/south, -/obj/structure/flora/tree/jungle/small/style_random, -/turf/open/floor/grass, -/area/station/service/chapel) "tBm" = ( /obj/machinery/hydroponics/soil, /turf/open/floor/grass, @@ -56838,12 +56806,6 @@ /obj/effect/mapping_helpers/broken_floor, /turf/open/floor/wood/parquet, /area/station/service/theater) -"tEf" = ( -/obj/effect/turf_decal/siding/wood{ - dir = 9 - }, -/turf/open/floor/grass, -/area/station/service/chapel) "tEg" = ( /obj/structure/transport/linear/tram, /obj/effect/turf_decal/stripes/white/line{ @@ -57326,11 +57288,6 @@ }, /turf/open/floor/iron, /area/station/hallway/primary/starboard) -"tMI" = ( -/obj/structure/disposalpipe/segment, -/obj/effect/turf_decal/siding/wood, -/turf/open/floor/grass, -/area/station/service/chapel) "tMR" = ( /obj/structure/disposalpipe/segment{ dir = 5 @@ -57866,13 +57823,6 @@ }, /turf/open/floor/plating, /area/station/science/robotics/lab) -"tVF" = ( -/obj/structure/cable, -/obj/effect/turf_decal/siding/wood{ - dir = 4 - }, -/turf/open/floor/grass, -/area/station/service/chapel) "tVR" = ( /obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ dir = 1 @@ -57942,6 +57892,13 @@ dir = 1 }, /area/station/hallway/secondary/exit/departure_lounge) +"tXd" = ( +/obj/effect/turf_decal/siding/wood{ + dir = 1 + }, +/obj/structure/flora/tree/jungle/small/style_random, +/turf/open/floor/grass, +/area/station/service/chapel) "tXl" = ( /obj/effect/turf_decal/sand/plating, /obj/structure/table/bronze, @@ -58307,6 +58264,11 @@ }, /turf/open/floor/wood, /area/station/service/chapel/funeral) +"ucQ" = ( +/obj/structure/flora/bush/flowers_pp/style_random, +/obj/effect/landmark/event_spawn, +/turf/open/floor/grass, +/area/station/service/chapel) "ucR" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/machinery/door/airlock{ @@ -59327,6 +59289,16 @@ }, /turf/open/floor/glass, /area/station/hallway/secondary/spacebridge) +"uuy" = ( +/obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2, +/turf/open/floor/wood/large, +/area/station/service/chapel) +"uuD" = ( +/obj/effect/turf_decal/siding/wood{ + dir = 6 + }, +/turf/open/floor/grass, +/area/station/service/chapel) "uuN" = ( /obj/structure/disposalpipe/segment{ dir = 4 @@ -61286,6 +61258,21 @@ dir = 1 }, /area/station/command/heads_quarters/hop) +"vdl" = ( +/obj/structure/cable, +/obj/structure/disposalpipe/segment{ + dir = 5 + }, +/obj/effect/decal/cleanable/dirt, +/obj/machinery/button/door/directional/east{ + id = "qm_warehouse_aft"; + name = "Warehouse Door Control"; + pixel_x = -24; + pixel_y = -23; + req_access = list("cargo") + }, +/turf/open/floor/plating, +/area/station/maintenance/port/fore) "vdm" = ( /obj/effect/decal/cleanable/dirt, /obj/structure/broken_flooring/pile/directional/east, @@ -62259,10 +62246,6 @@ }, /turf/open/floor/iron, /area/station/hallway/primary/central/fore) -"vrL" = ( -/obj/structure/reagent_dispensers/plumbed, -/turf/open/floor/plating, -/area/station/maintenance/fore/greater) "vrO" = ( /obj/machinery/door/firedoor, /obj/machinery/door/airlock/grunge{ @@ -62769,6 +62752,14 @@ }, /turf/open/floor/iron, /area/station/security/tram) +"vzX" = ( +/obj/machinery/door/airlock/command{ + name = "Centcom Dock" + }, +/obj/effect/mapping_helpers/airlock/access/any/command/general, +/obj/effect/mapping_helpers/airlock/access/any/admin/general, +/turf/open/floor/iron/textured_half, +/area/station/command/corporate_dock) "vzY" = ( /obj/effect/turf_decal/tile/dark_red/half/contrasted{ dir = 1 @@ -62968,6 +62959,14 @@ /obj/machinery/griddle, /turf/open/floor/iron/kitchen/small, /area/station/security/prison/mess) +"vEb" = ( +/obj/structure/cable, +/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ + dir = 8 + }, +/obj/machinery/duct, +/turf/open/floor/iron/kitchen/small, +/area/station/security/prison/mess) "vEe" = ( /obj/effect/mapping_helpers/broken_floor, /obj/machinery/light/small/directional/north, @@ -63290,6 +63289,12 @@ }, /turf/open/floor/iron/dark/herringbone, /area/station/security/courtroom) +"vJk" = ( +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/effect/turf_decal/siding/wood, +/turf/open/floor/grass, +/area/station/service/chapel) "vJn" = ( /obj/structure/closet/crate/coffin, /obj/structure/window/spawner/directional/west, @@ -63825,6 +63830,10 @@ /obj/effect/mapping_helpers/airlock/access/all/engineering/general, /turf/open/floor/catwalk_floor/iron_smooth, /area/station/maintenance/department/engine) +"vSr" = ( +/obj/structure/flora/bush/flowers_br/style_random, +/turf/open/floor/grass, +/area/station/service/chapel) "vSu" = ( /obj/structure/chair{ dir = 8 @@ -64396,6 +64405,15 @@ }, /turf/open/floor/iron/dark, /area/station/engineering/atmos) +"vZQ" = ( +/obj/effect/turf_decal/siding/wood{ + dir = 1 + }, +/obj/structure/flora/bush/flowers_br/style_random, +/obj/machinery/camera/autoname/directional/north, +/obj/machinery/light/small/directional/north, +/turf/open/floor/grass, +/area/station/service/chapel) "vZW" = ( /obj/structure/chair/sofa/bench/right{ dir = 4 @@ -65265,6 +65283,10 @@ /obj/structure/flora/bush/flowers_pp/style_random, /turf/open/misc/sandy_dirt, /area/station/medical/medbay/lobby) +"wpr" = ( +/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4, +/turf/open/floor/wood/large, +/area/station/service/chapel) "wpw" = ( /obj/structure/cable, /obj/item/kirbyplants/random, @@ -65975,13 +65997,6 @@ }, /turf/open/floor/iron/kitchen/small, /area/station/security/breakroom) -"wAh" = ( -/obj/effect/turf_decal/siding/wood{ - dir = 10 - }, -/obj/structure/flora/bush/sunny/style_random, -/turf/open/floor/grass, -/area/station/service/chapel) "wAj" = ( /obj/structure/table/wood, /obj/machinery/computer/records/medical/laptop{ @@ -66449,6 +66464,14 @@ dir = 1 }, /area/station/science/xenobiology) +"wIm" = ( +/obj/machinery/door/airlock/hatch{ + name = "Centcom Dock" + }, +/obj/effect/mapping_helpers/airlock/access/any/command/general, +/obj/effect/mapping_helpers/airlock/access/any/admin/general, +/turf/open/floor/plating, +/area/station/maintenance/department/science/xenobiology) "wIp" = ( /obj/structure/window/reinforced/spawner/directional/north, /turf/open/space/basic, @@ -66709,6 +66732,11 @@ "wMm" = ( /turf/closed/wall/rust, /area/station/engineering/break_room) +"wMr" = ( +/obj/structure/table/wood, +/obj/item/book/bible, +/turf/open/floor/wood/large, +/area/station/service/chapel) "wMA" = ( /obj/machinery/camera/directional/west, /obj/structure/bookcase/random/religion, @@ -68721,12 +68749,6 @@ }, /turf/open/floor/iron, /area/station/hallway/primary/fore) -"xmU" = ( -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/structure/flora/bush/flowers_yw/style_random, -/turf/open/floor/grass, -/area/station/service/chapel) "xmX" = ( /obj/effect/mapping_helpers/broken_floor, /obj/machinery/light/small/directional/east, @@ -69359,6 +69381,11 @@ "xvF" = ( /turf/open/floor/catwalk_floor/iron_dark, /area/station/science/xenobiology) +"xvI" = ( +/obj/effect/turf_decal/siding/wood, +/obj/structure/flora/bush/flowers_pp/style_random, +/turf/open/floor/grass, +/area/station/service/chapel) "xvJ" = ( /obj/structure/disposalpipe/segment{ dir = 4 @@ -69840,13 +69867,6 @@ }, /turf/open/floor/iron/small, /area/station/hallway/secondary/exit/departure_lounge) -"xCk" = ( -/obj/effect/turf_decal/siding/wood/corner{ - dir = 4 - }, -/obj/structure/flora/bush/flowers_yw/style_random, -/turf/open/floor/grass, -/area/station/service/chapel) "xCl" = ( /obj/structure/disposalpipe/segment, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -70057,14 +70077,6 @@ /obj/effect/mapping_helpers/airlock/access/all/science/ordnance, /turf/open/floor/iron/dark, /area/station/science/ordnance/freezerchamber) -"xFK" = ( -/obj/effect/turf_decal/siding/wood{ - dir = 8 - }, -/obj/structure/flora/bush/sunny/style_random, -/obj/machinery/light/small/directional/west, -/turf/open/floor/grass, -/area/station/service/chapel) "xFL" = ( /obj/machinery/atmospherics/components/unary/portables_connector/visible{ dir = 1 @@ -70114,6 +70126,16 @@ /obj/effect/decal/cleanable/dirt, /turf/open/floor/iron/smooth, /area/station/service/greenroom) +"xGe" = ( +/obj/structure/bed{ + dir = 4 + }, +/obj/effect/spawner/random/bedsheet{ + dir = 4 + }, +/obj/machinery/light/small/directional/west, +/turf/open/floor/carpet/orange, +/area/station/commons/dorms) "xGl" = ( /obj/machinery/door/airlock/external{ name = "External Docking Port" @@ -70228,13 +70250,6 @@ /obj/item/radio/intercom/directional/south, /turf/open/floor/iron, /area/station/security/tram) -"xIh" = ( -/obj/effect/turf_decal/siding/wood{ - dir = 1 - }, -/obj/structure/flora/bush/flowers_yw/style_random, -/turf/open/floor/grass, -/area/station/service/chapel) "xIj" = ( /obj/structure/cable, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -70639,13 +70654,6 @@ }, /turf/open/floor/iron, /area/station/security/brig/entrance) -"xNM" = ( -/obj/effect/turf_decal/siding/wood{ - dir = 5 - }, -/obj/structure/flora/bush/sunny/style_random, -/turf/open/floor/grass, -/area/station/service/chapel) "xNS" = ( /obj/effect/mapping_helpers/broken_floor, /turf/open/floor/plating, @@ -71569,12 +71577,6 @@ "xYO" = ( /turf/closed/wall/r_wall, /area/station/maintenance/department/bridge) -"xYY" = ( -/obj/effect/turf_decal/siding/wood, -/obj/structure/flora/bush/sunny/style_random, -/obj/machinery/newscaster/directional/south, -/turf/open/floor/grass, -/area/station/service/chapel) "xZd" = ( /obj/machinery/portable_atmospherics/canister/air, /obj/effect/decal/cleanable/dirt, @@ -71900,15 +71902,14 @@ }, /turf/open/floor/engine, /area/station/science/cytology) -"ydR" = ( -/obj/machinery/navbeacon{ - codes_txt = "delivery;dir=8"; - location = "QM #1" +"ydT" = ( +/obj/structure/disposalpipe/segment, +/obj/effect/turf_decal/siding/wood{ + dir = 9 }, -/obj/effect/turf_decal/delivery, -/mob/living/simple_animal/bot/mulebot, -/turf/open/floor/iron, -/area/station/cargo/storage) +/obj/effect/decal/cleanable/cobweb, +/turf/open/floor/grass, +/area/station/service/chapel) "yea" = ( /turf/closed/wall, /area/station/service/chapel/office) @@ -83963,7 +83964,7 @@ ovQ oRr poM uzJ -ydR +mKB npA nFh riV @@ -84232,11 +84233,11 @@ mhk mhk mhk mhk -lsz -cgG -cgG -cgG -wAh +nwu +frV +frV +frV +ggQ wBm wXk xKG @@ -84485,15 +84486,15 @@ ozn ozn sqe mhk -tEf -dhp -cgG -xFK -ewh -bDh -cLX -crG -kJl +eoH +lja +frV +gDO +sDR +rMX +brG +bmD +jaA wBm wXk oOy @@ -84742,15 +84743,15 @@ udt rXw sqz mhk -dvZ -bDh -hqk -kge -siH -xCk -dWE -bDh -tBk +pwg +rMX +qsw +mGV +jXg +hjh +ucQ +rMX +iDq wAW hDT glM @@ -84999,15 +85000,15 @@ xLO mhk mhk mhk -mQv -siH -eHK -pPF -daR -iCj -siH -bDh -kJl +soR +jXg +uuD +hDI +wpr +cUm +jXg +rMX +jaA wBm wXk jte @@ -85255,16 +85256,16 @@ srn uSM rYv srn -aei -dfH -cfi -mGe -mpA -rMj -ePQ -cdC -oxe -tMI +ydT +aeH +tqv +hJI +gpx +njq +sPZ +bEI +jhz +omi wzk tDJ blq @@ -85512,16 +85513,16 @@ mhk tKf rYD mhk -mDM -bDh -pkp -orv -pPF -lbz -dPv -rZF -fEE -xYY +tXd +rMX +cxl +jau +hDI +jzO +rat +pVf +aRr +lmB wAW wXk xiF @@ -85769,16 +85770,16 @@ mhk xmI pbu mhk -eEy -bDh -nkW -sYh -pPF -amn -dPv -ehL -mYk -kJl +vZQ +rMX +eKn +wMr +hDI +rvf +rat +fKC +oKK +jaA wAW iLK glM @@ -86026,16 +86027,16 @@ mhk mhk xLO mhk -dEN -dRK -nkW -iFH -pPF -lbz -qWn -rZF -bDh -dwf +nzH +seN +eKn +dGM +hDI +jzO +luX +pVf +rMX +xvI wBm wXk glM @@ -86284,15 +86285,15 @@ tYL pbu mhk mhk -xIh -hlC -oOf -pPF -sXg -ehr -mBG -xmU -jTP +trv +fJr +npl +hDI +uuy +ePm +khu +fJa +vJk ntw vuR xgA @@ -86541,15 +86542,15 @@ sNW rYD xLO mhk -xNM -dRK -qWt -cgG -cgG -ewh -kGO -bDh -kJl +dvY +seN +mfD +frV +frV +sDR +vSr +rMX +jaA wAZ wXk xgN @@ -86558,7 +86559,7 @@ kar vnr vIh wfb -pqZ +sjk xfU xjU fEC @@ -86799,14 +86800,14 @@ xYJ pbu mhk mhk -bKn -bDh -bDh -bDh -cLX -bDh -iSu -mXn +fzw +rMX +rMX +rMX +brG +rMX +osX +scM wBm wXk bVv @@ -87056,14 +87057,14 @@ sqz xLO xLO mhk -dio -aoJ -qxz -kUx -oEC -tVF -dBD -hgj +omM +aCG +jaW +qvm +gYL +sEs +qiu +gpq wAW mdU xhe @@ -88057,7 +88058,7 @@ slY ohl xwz pjG -qFn +hZe bOY rzL xwz @@ -88573,7 +88574,7 @@ pJQ wZF pqv wZF -mZt +vdl slY ueX rVQ @@ -89337,7 +89338,7 @@ dDB dDB ueX mGu -keI +gKK gPW hau oPF @@ -89990,7 +89991,7 @@ qeP lrE oPV pId -eXP +kld qRM vSx eGL @@ -90247,7 +90248,7 @@ qeP lrE oPV eHf -sNR +vEb eHf qsR eGL @@ -90504,7 +90505,7 @@ lub tBA oPV iNz -ivu +lHi jDe tSB eGL @@ -92706,7 +92707,7 @@ yfH jVM wzj nvo -bTw +row jVM puD pQe @@ -97324,7 +97325,7 @@ oGJ wQB wix xeO -dSF +hee mbK mqz jVM @@ -98422,7 +98423,7 @@ gQR uKM raE dBy -ezt +ena gKE tzs eOJ @@ -103498,9 +103499,9 @@ pUO rRy xIW ylJ -hPc +ohO rqw -fsU +dBA sAB dWW qUt @@ -104526,9 +104527,9 @@ mvJ nfD xcF ylJ -twI +xGe rqw -bcH +ein sAB umM nnE @@ -108399,11 +108400,11 @@ iOq nhZ ufF xMr -dgm +vzX vyR vyR vyR -nIH +wIm roz xzZ xQI @@ -109393,7 +109394,7 @@ bqy bqy tIE kGz -eey +kZo nFW lLv sJR @@ -109650,7 +109651,7 @@ bqy bqy doX yec -aUy +fls nFW nFW nFW @@ -109907,8 +109908,8 @@ bqy bqy tIE kGz -kQv -oDb +jPr +gxZ dxz kXJ xwy @@ -110164,8 +110165,8 @@ aJN aJN tIE nFW -cXT -dab +iSW +fRZ liR jQL uwH @@ -110421,7 +110422,7 @@ jIb pyt nvS nFW -vrL +iUy hnF iKN jRb @@ -119954,7 +119955,7 @@ utm jXR dZp urm -ciT +lyC xok dex bxT diff --git a/_maps/map_files/Deathmatch/meatower.dmm b/_maps/map_files/Deathmatch/meatower.dmm index 47613f8988554cf..fb2359fa28879d1 100644 --- a/_maps/map_files/Deathmatch/meatower.dmm +++ b/_maps/map_files/Deathmatch/meatower.dmm @@ -198,7 +198,7 @@ /obj/machinery/conveyor/auto{ dir = 4 }, -/obj/item/pizzabox/margherita/robo, +/obj/item/pizzabox/margherita, /obj/effect/turf_decal/siding/dark{ dir = 1 }, diff --git a/_maps/map_files/Deathmatch/mech_madness.dmm b/_maps/map_files/Deathmatch/mech_madness.dmm index d36ccfb16cc2006..3f804d2ee5452d0 100644 --- a/_maps/map_files/Deathmatch/mech_madness.dmm +++ b/_maps/map_files/Deathmatch/mech_madness.dmm @@ -664,7 +664,7 @@ /area/deathmatch) "ot" = ( /obj/structure/mop_bucket/janitorialcart{ - dir = 4 + dir = 4 }, /turf/open/floor/engine, /area/deathmatch) diff --git a/_maps/map_files/Deathmatch/starwars.dmm b/_maps/map_files/Deathmatch/starwars.dmm index c1f005461073af6..c7654810360e1fd 100644 --- a/_maps/map_files/Deathmatch/starwars.dmm +++ b/_maps/map_files/Deathmatch/starwars.dmm @@ -1142,9 +1142,6 @@ }, /turf/open/indestructible/large, /area/deathmatch) -"US" = ( -/turf/closed/indestructible/reinforced, -/area/deathmatch) "Ve" = ( /obj/effect/turf_decal/tile/red/full, /obj/structure/barricade/security/murderdome, @@ -1320,7 +1317,7 @@ tV tV IC IC -US +KX Vz sZ sZ diff --git a/_maps/map_files/Deltastation/DeltaStation2.dmm b/_maps/map_files/Deltastation/DeltaStation2.dmm index aeed0284808a590..c22d9964080eb78 100644 --- a/_maps/map_files/Deltastation/DeltaStation2.dmm +++ b/_maps/map_files/Deltastation/DeltaStation2.dmm @@ -7620,6 +7620,17 @@ /obj/machinery/newscaster/directional/south, /turf/open/floor/plating, /area/station/service/abandoned_gambling_den) +"bQC" = ( +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/structure/cable, +/obj/effect/turf_decal/tile/neutral{ + dir = 1 + }, +/turf/open/floor/iron/dark/corner{ + dir = 1 + }, +/area/station/hallway/secondary/exit/departure_lounge) "bQN" = ( /obj/item/radio/intercom/directional/east, /obj/effect/decal/cleanable/dirt, @@ -8721,17 +8732,6 @@ /obj/effect/turf_decal/tile/yellow/opposingcorners, /turf/open/floor/iron, /area/station/engineering/supermatter/room) -"cdJ" = ( -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/effect/turf_decal/tile/neutral{ - dir = 1 - }, -/obj/structure/cable, -/turf/open/floor/iron/dark/corner{ - dir = 1 - }, -/area/station/hallway/secondary/exit/departure_lounge) "cdN" = ( /obj/effect/spawner/random/structure/girder, /obj/effect/spawner/random/structure/grille, @@ -10421,13 +10421,6 @@ /obj/structure/extinguisher_cabinet/directional/east, /turf/open/floor/iron, /area/station/hallway/secondary/entry) -"czF" = ( -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/machinery/newscaster/directional/west, -/obj/structure/cable, -/turf/open/floor/iron, -/area/station/hallway/secondary/exit/departure_lounge) "czL" = ( /obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ dir = 1 @@ -15737,6 +15730,17 @@ "dPR" = ( /turf/closed/wall/r_wall, /area/station/maintenance/solars/port/aft) +"dPX" = ( +/obj/machinery/door/airlock/grunge{ + name = "Morgue" + }, +/obj/effect/turf_decal/stripes/line, +/obj/effect/turf_decal/stripes/line{ + dir = 1 + }, +/obj/effect/mapping_helpers/airlock/access/all/medical/morgue, +/turf/open/floor/iron, +/area/station/maintenance/department/medical/morgue) "dPY" = ( /obj/effect/turf_decal/bot_white/left, /obj/effect/turf_decal/tile/neutral{ @@ -30039,6 +30043,15 @@ /obj/effect/mapping_helpers/airlock/access/any/engineering/maintenance/departmental, /turf/open/floor/iron, /area/station/maintenance/port/fore) +"htK" = ( +/obj/machinery/navbeacon{ + codes_txt = "delivery;dir=4"; + location = "QM #1" + }, +/obj/effect/turf_decal/delivery, +/mob/living/simple_animal/bot/mulebot, +/turf/open/floor/iron, +/area/station/cargo/storage) "htQ" = ( /obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ dir = 8 @@ -36969,18 +36982,6 @@ }, /turf/open/floor/iron, /area/station/security/prison/garden) -"jgl" = ( -/obj/machinery/door/firedoor, -/obj/machinery/door/airlock/grunge{ - name = "Morgue" - }, -/obj/effect/turf_decal/stripes/line, -/obj/effect/turf_decal/stripes/line{ - dir = 1 - }, -/obj/effect/mapping_helpers/airlock/access/all/medical/morgue, -/turf/open/floor/iron, -/area/station/maintenance/department/medical/morgue) "jgq" = ( /obj/structure/chair/office{ dir = 1 @@ -54300,6 +54301,18 @@ /obj/effect/turf_decal/tile/neutral/fourcorners, /turf/open/floor/iron/dark, /area/station/ai_monitored/aisat/exterior) +"nBB" = ( +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/newscaster/directional/west, +/obj/structure/cable, +/obj/effect/turf_decal/tile/neutral{ + dir = 1 + }, +/turf/open/floor/iron/dark/corner{ + dir = 1 + }, +/area/station/hallway/secondary/exit/departure_lounge) "nBC" = ( /obj/item/kirbyplants/random, /obj/machinery/light/small/directional/north, @@ -65369,19 +65382,6 @@ }, /turf/open/floor/iron/textured, /area/station/medical/virology) -"qpu" = ( -/obj/machinery/navbeacon{ - codes_txt = "delivery;dir=4"; - location = "QM #4" - }, -/obj/effect/turf_decal/delivery, -/obj/machinery/button/door/directional/west{ - id = "warehouse_shutters"; - name = "warehouse shutters control" - }, -/mob/living/simple_animal/bot/mulebot, -/turf/open/floor/iron, -/area/station/cargo/storage) "qpz" = ( /obj/structure/cable, /obj/effect/turf_decal/tile/neutral/fourcorners, @@ -74338,15 +74338,6 @@ /obj/effect/decal/cleanable/cobweb/cobweb2, /turf/open/floor/iron/smooth, /area/station/maintenance/department/science/xenobiology) -"sAj" = ( -/obj/machinery/navbeacon{ - codes_txt = "delivery;dir=4"; - location = "QM #1" - }, -/obj/effect/turf_decal/delivery, -/mob/living/simple_animal/bot/mulebot, -/turf/open/floor/iron, -/area/station/cargo/storage) "sAm" = ( /obj/effect/decal/cleanable/dirt, /obj/effect/mapping_helpers/broken_floor, @@ -81530,6 +81521,19 @@ /obj/effect/turf_decal/tile/neutral/fourcorners, /turf/open/floor/iron/dark, /area/station/ai_monitored/turret_protected/aisat_interior) +"upv" = ( +/obj/machinery/navbeacon{ + codes_txt = "delivery;dir=4"; + location = "QM #4" + }, +/obj/effect/turf_decal/delivery, +/obj/machinery/button/door/directional/west{ + id = "warehouse_shutters"; + name = "warehouse shutters control" + }, +/mob/living/simple_animal/bot/mulebot, +/turf/open/floor/iron, +/area/station/cargo/storage) "upB" = ( /obj/structure/cable, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -136343,7 +136347,7 @@ rhp tPm nJQ tGj -jgl +dPX xBc grq oQa @@ -138655,10 +138659,10 @@ yho lvZ tOv iEN -czF +nBB fPw sYf -cdJ +bQC rrt qRF qRF @@ -140084,10 +140088,10 @@ jdL aix wHa mIA -sAj +htK tfy tuZ -qpu +upv dgU nZK hey diff --git a/_maps/map_files/IceBoxStation/IceBoxStation.dmm b/_maps/map_files/IceBoxStation/IceBoxStation.dmm index f1b944a8cc5afa0..71e4807de3600c5 100644 --- a/_maps/map_files/IceBoxStation/IceBoxStation.dmm +++ b/_maps/map_files/IceBoxStation/IceBoxStation.dmm @@ -6935,6 +6935,19 @@ /obj/effect/turf_decal/tile/yellow/opposingcorners, /turf/open/floor/iron/dark, /area/station/engineering/atmos/project) +"ccp" = ( +/obj/structure/bed, +/obj/effect/spawner/random/bedsheet, +/obj/effect/landmark/start/hangover, +/obj/machinery/button/door/directional/south{ + id = "Dorm5"; + name = "Cabin Bolt Control"; + normaldoorcontrol = 1; + specialfunctions = 4 + }, +/obj/item/pillow/random, +/turf/open/floor/wood, +/area/station/commons/dorms) "ccr" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -8389,13 +8402,6 @@ /obj/effect/spawner/structure/window/reinforced, /turf/open/floor/plating, /area/station/science/xenobiology) -"cyo" = ( -/obj/machinery/stasis{ - dir = 4 - }, -/obj/effect/turf_decal/tile/blue/full, -/turf/open/floor/iron/large, -/area/station/medical/treatment_center) "cyA" = ( /obj/machinery/door/airlock/maintenance, /obj/effect/mapping_helpers/airlock/unres{ @@ -9394,12 +9400,6 @@ }, /turf/open/floor/iron, /area/station/hallway/primary/starboard) -"cMh" = ( -/obj/structure/bed/pod, -/obj/effect/spawner/random/bedsheet/any, -/obj/effect/mapping_helpers/broken_floor, -/turf/open/floor/wood, -/area/station/maintenance/port/fore) "cMj" = ( /obj/structure/stairs/west, /obj/structure/railing{ @@ -10048,6 +10048,12 @@ }, /turf/open/floor/iron, /area/station/cargo/office) +"cXp" = ( +/obj/structure/bed/pod, +/obj/effect/spawner/random/bedsheet/any, +/obj/effect/mapping_helpers/broken_floor, +/turf/open/floor/wood, +/area/station/maintenance/port/fore) "cXu" = ( /obj/machinery/firealarm/directional/north, /obj/effect/turf_decal/trimline/blue/filled/line{ @@ -10404,6 +10410,19 @@ /obj/structure/cable, /turf/open/floor/carpet/red, /area/station/security/prison/work) +"dcq" = ( +/obj/structure/bed, +/obj/machinery/airalarm/directional/north, +/obj/effect/spawner/random/bedsheet, +/obj/machinery/button/door/directional/east{ + id = "Dorm3"; + name = "Dorm Bolt Control"; + normaldoorcontrol = 1; + specialfunctions = 4 + }, +/obj/item/pillow/random, +/turf/open/floor/wood, +/area/station/commons/dorms) "dcr" = ( /obj/machinery/chem_master, /obj/structure/window/reinforced/spawner/directional/south, @@ -14206,19 +14225,6 @@ "elw" = ( /turf/closed/wall/r_wall, /area/station/maintenance/starboard/upper) -"elD" = ( -/obj/effect/turf_decal/trimline/red/filled/line{ - dir = 9 - }, -/obj/structure/bed{ - dir = 1 - }, -/obj/effect/spawner/random/bedsheet{ - dir = 1 - }, -/obj/effect/spawner/random/contraband/permabrig_gear, -/turf/open/floor/iron/white, -/area/station/security/prison/safe) "elT" = ( /obj/machinery/atmospherics/components/unary/vent_scrubber/layer2{ dir = 8 @@ -17363,19 +17369,6 @@ /obj/machinery/plumbing/sender, /turf/open/floor/plating, /area/station/medical/chemistry) -"fmz" = ( -/obj/structure/bed, -/obj/machinery/airalarm/directional/north, -/obj/effect/spawner/random/bedsheet, -/obj/machinery/button/door/directional/east{ - id = "Dorm3"; - name = "Dorm Bolt Control"; - normaldoorcontrol = 1; - specialfunctions = 4 - }, -/obj/item/pillow/random, -/turf/open/floor/wood, -/area/station/commons/dorms) "fmA" = ( /obj/structure/cable, /obj/effect/turf_decal/trimline/dark_blue/line{ @@ -20589,16 +20582,6 @@ "gmW" = ( /turf/closed/wall, /area/station/commons/fitness) -"gnb" = ( -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/structure/cable, -/obj/effect/turf_decal/trimline/blue/filled/corner, -/obj/effect/turf_decal/trimline/blue/filled/corner{ - dir = 8 - }, -/turf/open/floor/iron/white, -/area/station/medical/medbay/central) "gnh" = ( /turf/closed/wall/r_wall, /area/station/maintenance/department/cargo) @@ -21522,6 +21505,15 @@ /obj/effect/mapping_helpers/burnt_floor, /turf/open/floor/plating, /area/station/maintenance/fore) +"gDE" = ( +/obj/machinery/defibrillator_mount/directional/north, +/obj/effect/turf_decal/tile/blue/full, +/obj/machinery/light/cold/directional/north, +/obj/machinery/stasis{ + dir = 4 + }, +/turf/open/floor/iron/large, +/area/station/medical/treatment_center) "gDN" = ( /obj/effect/turf_decal/tile/brown/half/contrasted{ dir = 1 @@ -21989,19 +21981,6 @@ "gKQ" = ( /turf/closed/wall, /area/station/security/courtroom) -"gKR" = ( -/obj/machinery/conveyor{ - dir = 6; - id = "mining_internal" - }, -/obj/effect/turf_decal/stripes/line{ - dir = 5 - }, -/obj/machinery/power/apc/auto_name/directional/north, -/obj/structure/cable, -/obj/machinery/brm, -/turf/open/floor/iron, -/area/mine/production) "gLj" = ( /obj/structure/window/reinforced/spawner/directional/south, /turf/open/floor/engine, @@ -25394,20 +25373,6 @@ /obj/machinery/door/firedoor, /turf/open/floor/wood, /area/station/security/prison/rec) -"hPp" = ( -/obj/structure/bed{ - dir = 1 - }, -/obj/effect/spawner/random/bedsheet{ - dir = 1 - }, -/obj/effect/turf_decal/trimline/red/filled/line{ - dir = 10 - }, -/turf/open/floor/iron/dark/side{ - dir = 10 - }, -/area/station/security/prison/safe) "hPs" = ( /turf/closed/wall/r_wall, /area/station/security/prison/work) @@ -28608,20 +28573,6 @@ /obj/effect/turf_decal/tile/neutral/fourcorners, /turf/open/floor/iron/dark, /area/station/engineering/atmos/mix) -"iPf" = ( -/obj/structure/bed, -/obj/machinery/airalarm/directional/north, -/obj/effect/spawner/random/bedsheet, -/obj/effect/landmark/start/hangover, -/obj/machinery/button/door/directional/east{ - id = "Dorm4"; - name = "Dorm Bolt Control"; - normaldoorcontrol = 1; - specialfunctions = 4 - }, -/obj/item/pillow/random, -/turf/open/floor/carpet, -/area/station/commons/dorms) "iPm" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -29902,6 +29853,14 @@ /obj/machinery/atmospherics/components/tank, /turf/open/floor/iron/dark, /area/station/science/ordnance) +"jln" = ( +/obj/structure/cable, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/effect/turf_decal/trimline/blue/filled/line, +/obj/machinery/airalarm/directional/south, +/turf/open/floor/iron/white, +/area/station/medical/medbay/central) "jlu" = ( /obj/structure/railing/corner, /turf/open/lava/plasma/ice_moon, @@ -32222,6 +32181,13 @@ /obj/effect/turf_decal/box/white, /turf/open/floor/engine, /area/station/engineering/atmos/hfr_room) +"jVH" = ( +/obj/structure/cable, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/effect/turf_decal/trimline/blue/filled/corner, +/turf/open/floor/iron/white, +/area/station/medical/medbay/central) "jVL" = ( /obj/structure/cable, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -32855,19 +32821,6 @@ }, /turf/open/floor/iron/dark, /area/station/service/chapel) -"kfp" = ( -/obj/structure/bed, -/obj/effect/spawner/random/bedsheet, -/obj/effect/landmark/start/hangover, -/obj/machinery/button/door/directional/south{ - id = "Dorm5"; - name = "Cabin Bolt Control"; - normaldoorcontrol = 1; - specialfunctions = 4 - }, -/obj/item/pillow/random, -/turf/open/floor/wood, -/area/station/commons/dorms) "kfs" = ( /turf/closed/wall/r_wall, /area/station/engineering/atmos) @@ -33427,19 +33380,6 @@ /obj/machinery/light/directional/west, /turf/open/floor/iron, /area/station/maintenance/disposal/incinerator) -"kmG" = ( -/obj/structure/table/glass, -/obj/item/reagent_containers/cup/bottle/epinephrine, -/obj/item/reagent_containers/cup/bottle/multiver{ - pixel_x = 6 - }, -/obj/item/reagent_containers/syringe, -/obj/machinery/defibrillator_mount/directional/north, -/obj/item/radio/intercom/directional/west, -/obj/effect/turf_decal/tile/blue/full, -/obj/machinery/light/cold/directional/north, -/turf/open/floor/iron/large, -/area/station/medical/treatment_center) "kmH" = ( /obj/effect/spawner/random/entertainment/cigar, /obj/structure/table, @@ -33603,15 +33543,6 @@ }, /turf/open/floor/iron, /area/mine/laborcamp) -"kpO" = ( -/obj/effect/turf_decal/trimline/blue/filled/warning{ - dir = 8 - }, -/obj/effect/turf_decal/trimline/blue/filled/corner{ - dir = 4 - }, -/turf/open/floor/iron/white, -/area/station/medical/treatment_center) "kpX" = ( /obj/structure/bed/medical{ dir = 4 @@ -34316,6 +34247,11 @@ /obj/effect/decal/cleanable/dirt, /turf/open/floor/iron, /area/station/hallway/secondary/service) +"kzv" = ( +/obj/structure/bed, +/obj/effect/spawner/random/bedsheet/any, +/turf/open/floor/plating, +/area/station/maintenance/department/medical/morgue) "kzw" = ( /turf/closed/wall/r_wall, /area/station/security/medical) @@ -34812,18 +34748,6 @@ dir = 1 }, /area/station/commons/storage/art) -"kGN" = ( -/obj/structure/bed, -/obj/effect/spawner/random/bedsheet, -/obj/machinery/button/door/directional/south{ - id = "Dorm6"; - name = "Cabin Bolt Control"; - normaldoorcontrol = 1; - specialfunctions = 4 - }, -/obj/item/pillow/random, -/turf/open/floor/carpet, -/area/station/commons/dorms) "kGP" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /obj/effect/turf_decal/tile/red{ @@ -38673,19 +38597,6 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/open/floor/wood, /area/station/commons/dorms) -"lOG" = ( -/obj/structure/bed, -/obj/machinery/airalarm/directional/north, -/obj/effect/spawner/random/bedsheet, -/obj/machinery/button/door/directional/east{ - id = "Dorm2"; - name = "Dorm Bolt Control"; - normaldoorcontrol = 1; - specialfunctions = 4 - }, -/obj/item/pillow/random, -/turf/open/floor/carpet, -/area/station/commons/dorms) "lOI" = ( /obj/machinery/atmospherics/pipe/smart/simple/dark/visible/layer1{ dir = 5 @@ -41304,6 +41215,19 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/general/visible, /turf/open/floor/iron/dark, /area/station/science/explab) +"mHe" = ( +/obj/machinery/conveyor{ + dir = 6; + id = "mining_internal" + }, +/obj/effect/turf_decal/stripes/line{ + dir = 5 + }, +/obj/machinery/power/apc/auto_name/directional/north, +/obj/structure/cable, +/obj/machinery/brm, +/turf/open/floor/iron, +/area/mine/production) "mHu" = ( /obj/machinery/atmospherics/components/tank, /turf/open/floor/iron/dark, @@ -41425,6 +41349,19 @@ }, /turf/open/floor/iron/white, /area/station/medical/medbay/lobby) +"mJO" = ( +/obj/structure/bed, +/obj/machinery/airalarm/directional/north, +/obj/effect/spawner/random/bedsheet, +/obj/machinery/button/door/directional/east{ + id = "Dorm2"; + name = "Dorm Bolt Control"; + normaldoorcontrol = 1; + specialfunctions = 4 + }, +/obj/item/pillow/random, +/turf/open/floor/carpet, +/area/station/commons/dorms) "mJX" = ( /obj/structure/cable, /obj/effect/spawner/structure/window/hollow/reinforced/middle, @@ -45277,6 +45214,20 @@ /obj/structure/sign/poster/contraband/random/directional/east, /turf/open/floor/wood, /area/station/maintenance/port/aft) +"nOl" = ( +/obj/structure/bed, +/obj/machinery/airalarm/directional/north, +/obj/effect/spawner/random/bedsheet, +/obj/effect/landmark/start/hangover, +/obj/machinery/button/door/directional/east{ + id = "Dorm4"; + name = "Dorm Bolt Control"; + normaldoorcontrol = 1; + specialfunctions = 4 + }, +/obj/item/pillow/random, +/turf/open/floor/carpet, +/area/station/commons/dorms) "nOx" = ( /obj/effect/decal/cleanable/dirt, /turf/open/floor/iron, @@ -45408,13 +45359,6 @@ }, /turf/open/floor/iron/white, /area/station/medical/chemistry) -"nRd" = ( -/obj/structure/cable, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/effect/turf_decal/trimline/blue/filled/corner, -/turf/open/floor/iron/white, -/area/station/medical/medbay/central) "nRm" = ( /obj/structure/cable, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -47373,7 +47317,7 @@ start_active = 1 }, /turf/open/misc/asteroid/snow/icemoon, -/area/station/ai_monitored/turret_protected/aisat/maint) +/area/icemoon/surface/outdoors/nospawn) "oxB" = ( /obj/machinery/door/airlock/maintenance, /obj/effect/mapping_helpers/airlock/abandoned, @@ -49831,6 +49775,18 @@ dir = 1 }, /area/station/hallway/primary/central) +"piC" = ( +/obj/structure/bed, +/obj/effect/spawner/random/bedsheet, +/obj/machinery/button/door/directional/south{ + id = "Dorm6"; + name = "Cabin Bolt Control"; + normaldoorcontrol = 1; + specialfunctions = 4 + }, +/obj/item/pillow/random, +/turf/open/floor/carpet, +/area/station/commons/dorms) "piD" = ( /obj/machinery/computer/security/labor, /obj/structure/cable, @@ -51303,16 +51259,6 @@ }, /turf/open/floor/iron/large, /area/station/service/hydroponics/garden) -"pEu" = ( -/obj/machinery/navbeacon{ - codes_txt = "delivery;dir=8"; - location = "QM #2" - }, -/obj/effect/turf_decal/bot, -/obj/machinery/light/small/directional/east, -/mob/living/simple_animal/bot/mulebot, -/turf/open/floor/iron, -/area/station/cargo/storage) "pEE" = ( /obj/machinery/power/apc/auto_name/directional/north, /obj/structure/cable, @@ -51970,13 +51916,6 @@ "pOL" = ( /turf/open/floor/iron/white, /area/station/science/ordnance) -"pOU" = ( -/obj/effect/turf_decal/trimline/blue/filled/line{ - dir = 6 - }, -/obj/machinery/airalarm/directional/south, -/turf/open/floor/iron/white, -/area/station/medical/medbay/central) "pOV" = ( /obj/structure/rack, /obj/item/clothing/suit/hazardvest, @@ -52517,6 +52456,17 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/open/floor/iron, /area/station/engineering/atmos) +"pYx" = ( +/obj/structure/table/glass, +/obj/item/reagent_containers/cup/bottle/epinephrine, +/obj/item/reagent_containers/cup/bottle/multiver{ + pixel_x = 6 + }, +/obj/item/reagent_containers/syringe, +/obj/effect/turf_decal/tile/blue/full, +/obj/item/radio/intercom/directional/west, +/turf/open/floor/iron/large, +/area/station/medical/treatment_center) "pYz" = ( /obj/structure/railing/corner, /obj/machinery/door/firedoor/border_only, @@ -56066,7 +56016,7 @@ start_active = 1 }, /turf/open/misc/asteroid/snow/icemoon, -/area/station/ai_monitored/turret_protected/aisat/maint) +/area/icemoon/surface/outdoors/nospawn) "rbs" = ( /obj/effect/turf_decal/tile/yellow, /obj/machinery/light/directional/east, @@ -57239,6 +57189,12 @@ }, /turf/open/floor/iron, /area/station/engineering/atmos) +"ruM" = ( +/obj/effect/turf_decal/trimline/blue/filled/line{ + dir = 9 + }, +/turf/open/floor/iron/white, +/area/station/medical/treatment_center) "ruO" = ( /obj/machinery/firealarm/directional/west, /obj/structure/disposalpipe/segment{ @@ -58794,6 +58750,16 @@ dir = 4 }, /area/station/hallway/secondary/entry) +"rUy" = ( +/obj/machinery/navbeacon{ + codes_txt = "delivery;dir=8"; + location = "QM #2" + }, +/obj/effect/turf_decal/bot, +/obj/machinery/light/small/directional/east, +/mob/living/simple_animal/bot/mulebot, +/turf/open/floor/iron, +/area/station/cargo/storage) "rUz" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/effect/decal/cleanable/dirt, @@ -63498,6 +63464,19 @@ /obj/effect/mapping_helpers/airlock/access/all/security/general, /turf/open/floor/iron/dark/textured, /area/station/security/interrogation) +"tsK" = ( +/obj/effect/turf_decal/trimline/red/filled/line{ + dir = 9 + }, +/obj/structure/bed{ + dir = 1 + }, +/obj/effect/spawner/random/bedsheet{ + dir = 1 + }, +/obj/effect/spawner/random/contraband/permabrig_gear, +/turf/open/floor/iron/white, +/area/station/security/prison/safe) "tsQ" = ( /obj/machinery/door/airlock/public/glass{ name = "Public Mining Storage" @@ -64907,11 +64886,6 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/plating, /area/station/maintenance/aft/lesser) -"tNM" = ( -/obj/structure/bed, -/obj/effect/spawner/random/bedsheet/any, -/turf/open/floor/plating, -/area/station/maintenance/department/medical/morgue) "tNY" = ( /obj/machinery/door/firedoor, /turf/open/floor/iron, @@ -66455,12 +66429,6 @@ /obj/effect/spawner/random/engineering/tracking_beacon, /turf/open/floor/iron, /area/station/command/teleporter) -"uoV" = ( -/obj/structure/cable, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/turf/open/floor/iron/white, -/area/station/medical/medbay/central) "upa" = ( /obj/structure/closet/firecloset, /turf/open/floor/plating, @@ -66645,6 +66613,20 @@ "usP" = ( /turf/open/misc/asteroid/snow/standard_air, /area/station/science/research) +"usS" = ( +/obj/structure/bed{ + dir = 1 + }, +/obj/effect/spawner/random/bedsheet{ + dir = 1 + }, +/obj/effect/turf_decal/trimline/red/filled/line{ + dir = 10 + }, +/turf/open/floor/iron/dark/side{ + dir = 10 + }, +/area/station/security/prison/safe) "utr" = ( /obj/structure/table, /obj/item/storage/toolbox/mechanical{ @@ -74275,15 +74257,6 @@ /obj/structure/cable, /turf/open/floor/iron/dark/textured, /area/station/security/processing) -"wOf" = ( -/obj/machinery/navbeacon{ - codes_txt = "delivery;dir=8"; - location = "QM #1" - }, -/obj/effect/turf_decal/bot, -/mob/living/simple_animal/bot/mulebot, -/turf/open/floor/iron, -/area/station/cargo/storage) "wOh" = ( /obj/effect/turf_decal/trimline/green/filled/line{ dir = 8 @@ -75177,6 +75150,15 @@ /obj/item/radio/intercom/directional/west, /turf/open/floor/iron, /area/station/command/heads_quarters/hop) +"xaF" = ( +/obj/machinery/navbeacon{ + codes_txt = "delivery;dir=8"; + location = "QM #1" + }, +/obj/effect/turf_decal/bot, +/mob/living/simple_animal/bot/mulebot, +/turf/open/floor/iron, +/area/station/cargo/storage) "xaH" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -79056,6 +79038,18 @@ }, /turf/open/floor/iron, /area/station/engineering/atmos/storage) +"ylS" = ( +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/structure/cable, +/obj/effect/turf_decal/trimline/blue/filled/corner{ + dir = 8 + }, +/obj/effect/turf_decal/trimline/blue/filled/line{ + dir = 4 + }, +/turf/open/floor/iron/white, +/area/station/medical/medbay/central) "ylU" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -104857,7 +104851,7 @@ tWK tWK tWK xhK -elD +tsK jGg vVH krV @@ -105123,7 +105117,7 @@ fHg eek vVH fps -hPp +usS vVH keD kqR @@ -105894,7 +105888,7 @@ fHg hnt vVH fps -hPp +usS vVH gwy ixw @@ -164572,7 +164566,7 @@ dQd nWH nWH nWH -gKR +mHe dAq adm dTF @@ -180506,7 +180500,7 @@ qMz hjM gmO sBJ -tNM +kzv nxM bYY cDh @@ -228499,7 +228493,7 @@ tCr tCr lJO gLZ -cMh +cXp xiW lJO hjI @@ -231374,8 +231368,8 @@ ppo lxb eWV kXr -wOf -pEu +xaF +rUy smx qqJ gjP @@ -240843,16 +240837,16 @@ sDl skl jOQ skl -iPf +nOl oCF ygB -fmz +dcq peb ygB -lOG +mJO oCF ygB -lOG +mJO oCF ygB lBD @@ -242643,7 +242637,7 @@ cIK jOQ skl ddr -kfp +ccp ygB kCb gya @@ -243671,7 +243665,7 @@ iHz jOQ skl pOo -kGN +piC ygB fXo aos @@ -245765,8 +245759,8 @@ sHc oGs sEz jFZ -uoV -gnb +jVH +ylS gTi whh pQL @@ -246022,8 +246016,8 @@ azw cXu frP oIJ -nRd -pOU +jln +lwQ tHr tHr bxU @@ -246281,7 +246275,7 @@ eqp cTV fHz lwQ -lwQ +pYx sEK eHg ahL @@ -246538,9 +246532,9 @@ iBj mcW sFG lwQ -kmG -cyo -kpO +gDE +ruM +lup lup aCA jDn @@ -246796,8 +246790,8 @@ mcW fPb bEL efK -evp juw +nji tkf ikz oSQ diff --git a/_maps/map_files/MetaStation/MetaStation.dmm b/_maps/map_files/MetaStation/MetaStation.dmm index c882645023a44f9..cea78227cbcecd8 100644 --- a/_maps/map_files/MetaStation/MetaStation.dmm +++ b/_maps/map_files/MetaStation/MetaStation.dmm @@ -5856,6 +5856,14 @@ }, /turf/open/floor/engine, /area/station/engineering/supermatter/room) +"cer" = ( +/obj/machinery/door/airlock/maintenance{ + name = "Surgery C Maintenance" + }, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/effect/mapping_helpers/airlock/access/all/medical/surgery, +/turf/open/floor/plating, +/area/station/maintenance/aft/greater) "ces" = ( /obj/effect/turf_decal/trimline/purple/filled/line, /obj/machinery/processor/slime, @@ -9484,6 +9492,20 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/open/floor/iron, /area/station/commons/fitness/recreation) +"dxF" = ( +/obj/machinery/door/firedoor, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/door/airlock/medical/glass{ + name = "Pharmacy" + }, +/obj/structure/disposalpipe/segment{ + dir = 4 + }, +/obj/effect/mapping_helpers/airlock/access/any/medical/pharmacy, +/obj/effect/turf_decal/tile/yellow/fourcorners, +/obj/effect/landmark/navigate_destination, +/turf/open/floor/iron/white, +/area/station/medical/pharmacy) "dxK" = ( /obj/structure/lattice/catwalk, /obj/structure/marker_beacon/purple, @@ -31010,6 +31032,23 @@ /obj/effect/mapping_helpers/airlock/access/any/supply/maintenance, /turf/open/floor/plating, /area/station/maintenance/disposal) +"lcq" = ( +/obj/structure/cable, +/obj/machinery/door/poddoor/shutters/preopen{ + dir = 8; + id = "chem_lockdown"; + name = "Chemistry Shutters" + }, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/door/airlock/medical/glass{ + name = "Chemistry" + }, +/obj/effect/mapping_helpers/airlock/access/all/medical/chemistry, +/obj/machinery/door/firedoor, +/obj/effect/turf_decal/tile/yellow/fourcorners, +/turf/open/floor/iron/white, +/area/station/medical/chemistry) "lcG" = ( /obj/effect/turf_decal/tile/neutral/fourcorners, /turf/open/floor/iron/dark, @@ -37314,6 +37353,15 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/open/floor/engine, /area/station/engineering/supermatter/room) +"nry" = ( +/obj/machinery/door/airlock/maintenance{ + name = "Pharmacy Maintenance" + }, +/obj/structure/cable, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/effect/mapping_helpers/airlock/access/any/medical/pharmacy, +/turf/open/floor/plating, +/area/station/maintenance/department/medical/central) "nrV" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/general/hidden, /turf/open/floor/iron/dark, @@ -43202,23 +43250,6 @@ }, /turf/open/floor/iron, /area/station/security/brig) -"pyM" = ( -/obj/structure/cable, -/obj/machinery/door/poddoor/shutters/preopen{ - dir = 8; - id = "chem_lockdown"; - name = "Chemistry Shutters" - }, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/machinery/door/airlock/research/glass{ - name = "Chemistry Lab" - }, -/obj/effect/mapping_helpers/airlock/access/all/medical/chemistry, -/obj/machinery/door/firedoor, -/obj/effect/turf_decal/tile/yellow/fourcorners, -/turf/open/floor/iron/white, -/area/station/medical/chemistry) "pyP" = ( /obj/effect/turf_decal/tile/neutral/fourcorners, /turf/open/floor/iron/dark, @@ -45198,16 +45229,6 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/iron, /area/station/hallway/primary/central) -"qhG" = ( -/obj/machinery/door/airlock/maintenance{ - name = "Pharmacy Maintenance" - }, -/obj/structure/cable, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/effect/mapping_helpers/airlock/access/any/medical/general, -/obj/effect/mapping_helpers/airlock/access/any/medical/pharmacy, -/turf/open/floor/plating, -/area/station/maintenance/department/medical/central) "qhI" = ( /obj/machinery/atmospherics/pipe/smart/manifold/scrubbers/visible{ dir = 8 @@ -50123,14 +50144,6 @@ /obj/effect/turf_decal/tile/neutral/fourcorners, /turf/open/floor/iron/dark, /area/station/security/evidence) -"rTF" = ( -/obj/machinery/door/airlock/maintenance{ - name = "Surgery C Maintenance" - }, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/effect/mapping_helpers/airlock/access/all/medical/general, -/turf/open/floor/plating, -/area/station/maintenance/aft/greater) "rTL" = ( /obj/machinery/door/firedoor, /obj/machinery/door/airlock/public/glass{ @@ -62649,21 +62662,6 @@ }, /turf/open/floor/iron, /area/station/hallway/secondary/command) -"whx" = ( -/obj/machinery/door/firedoor, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/machinery/door/airlock/research/glass{ - name = "Pharmacy" - }, -/obj/structure/disposalpipe/segment{ - dir = 4 - }, -/obj/effect/mapping_helpers/airlock/access/any/medical/general, -/obj/effect/mapping_helpers/airlock/access/any/medical/pharmacy, -/obj/effect/turf_decal/tile/yellow/fourcorners, -/obj/effect/landmark/navigate_destination, -/turf/open/floor/iron/white, -/area/station/medical/pharmacy) "why" = ( /obj/effect/spawner/structure/window/reinforced, /obj/machinery/door/poddoor/preopen{ @@ -87169,7 +87167,7 @@ tzE ucc tSw tSw -rTF +cer tSw tSw tSw @@ -91793,7 +91791,7 @@ yfg yfg bqX iMr -pyM +lcq oNy bqX bqX @@ -93830,7 +93828,7 @@ vLf kXD kWO rvE -whx +dxF cIK hoN eIO @@ -94351,7 +94349,7 @@ gtb fJW xWE kzj -qhG +nry iqq qWK cdk diff --git a/_maps/map_files/tramstation/tramstation.dmm b/_maps/map_files/tramstation/tramstation.dmm index 4bf29794e810a4f..2bdd5480d9d4f0c 100644 --- a/_maps/map_files/tramstation/tramstation.dmm +++ b/_maps/map_files/tramstation/tramstation.dmm @@ -4473,18 +4473,6 @@ }, /turf/open/floor/iron, /area/station/hallway/primary/tram/right) -"aEB" = ( -/obj/machinery/door/firedoor, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/structure/cable, -/obj/structure/disposalpipe/segment{ - dir = 4 - }, -/obj/effect/turf_decal/trimline/neutral/filled/line, -/obj/effect/turf_decal/stripes/white/full, -/turf/open/floor/iron, -/area/station/hallway/secondary/exit/departure_lounge) "aEE" = ( /obj/machinery/door/airlock/maintenance_hatch{ name = "Mining Maintenance Access" @@ -4553,6 +4541,12 @@ }, /turf/open/floor/iron, /area/station/security/prison) +"aFP" = ( +/obj/effect/turf_decal/trimline/neutral/filled/corner{ + dir = 4 + }, +/turf/open/floor/iron, +/area/station/hallway/secondary/exit) "aFU" = ( /obj/effect/mapping_helpers/airlock/access/all/engineering/maintenance, /obj/machinery/door/airlock/maintenance_hatch{ @@ -4575,7 +4569,7 @@ /obj/machinery/light/directional/north, /turf/open/floor/iron, /area/station/security/brig) -"aGa" = ( +"aFZ" = ( /obj/effect/spawner/random/engineering/tracking_beacon, /turf/open/floor/iron, /area/station/hallway/secondary/exit) @@ -4620,6 +4614,14 @@ /obj/effect/spawner/random/decoration/ornament, /turf/open/floor/iron/grimy, /area/station/service/lawoffice) +"aGq" = ( +/obj/machinery/vending/snack/blue, +/obj/effect/turf_decal/tile/neutral/fourcorners, +/obj/effect/turf_decal/siding/thinplating/dark{ + dir = 6 + }, +/turf/open/floor/iron/dark, +/area/station/hallway/secondary/exit) "aGs" = ( /obj/structure/chair, /obj/effect/turf_decal/trimline/neutral/filled/line{ @@ -4636,6 +4638,12 @@ /obj/effect/landmark/start/hangover, /turf/open/floor/iron, /area/station/hallway/secondary/exit/departure_lounge) +"aGw" = ( +/obj/machinery/door/firedoor, +/obj/effect/turf_decal/trimline/neutral/filled/line, +/obj/effect/turf_decal/stripes/white/full, +/turf/open/floor/iron, +/area/station/hallway/secondary/exit/departure_lounge) "aGx" = ( /obj/effect/turf_decal/trimline/neutral/line{ dir = 1 @@ -4682,18 +4690,6 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/open/floor/iron, /area/station/science/lower) -"aHa" = ( -/obj/structure/bed{ - dir = 4 - }, -/obj/effect/spawner/random/bedsheet{ - dir = 4 - }, -/obj/effect/landmark/start/assistant, -/obj/structure/sign/clock/directional/west, -/obj/item/pillow/random, -/turf/open/floor/carpet, -/area/station/commons/dorms) "aHb" = ( /obj/structure/extinguisher_cabinet/directional/south, /obj/effect/turf_decal/tile/blue/opposingcorners, @@ -6225,6 +6221,14 @@ }, /turf/open/floor/iron/dark, /area/station/engineering/supermatter/room) +"aZm" = ( +/obj/effect/turf_decal/trimline/neutral/filled/line{ + dir = 4 + }, +/obj/effect/landmark/event_spawn, +/obj/effect/landmark/start/hangover, +/turf/open/floor/iron, +/area/station/hallway/secondary/exit) "aZo" = ( /obj/effect/turf_decal/siding/thinplating/dark{ dir = 4 @@ -7252,6 +7256,19 @@ /obj/structure/sign/calendar/directional/south, /turf/open/floor/iron/dark/small, /area/station/commons/vacant_room) +"bxC" = ( +/obj/effect/turf_decal/trimline/neutral/filled/line{ + dir = 9 + }, +/obj/effect/turf_decal/trimline/red/filled/corner{ + dir = 4 + }, +/obj/effect/turf_decal/trimline/neutral/corner{ + dir = 4 + }, +/obj/machinery/firealarm/directional/north, +/turf/open/floor/iron, +/area/station/hallway/secondary/exit/departure_lounge) "bxG" = ( /obj/effect/turf_decal/trimline/purple/filled/line{ dir = 8 @@ -7378,6 +7395,17 @@ /obj/structure/cable, /turf/open/floor/iron, /area/station/tcommsat/computer) +"bzs" = ( +/obj/structure/bed{ + dir = 4 + }, +/obj/effect/spawner/random/bedsheet{ + dir = 4 + }, +/obj/structure/sign/clock/directional/west, +/obj/item/pillow/random, +/turf/open/floor/carpet, +/area/station/commons/dorms) "bzt" = ( /obj/effect/turf_decal/trimline/green/filled/line{ dir = 8 @@ -8036,14 +8064,6 @@ /obj/structure/window/reinforced/spawner/directional/south, /turf/open/floor/iron, /area/station/security/office) -"bLs" = ( -/obj/machinery/brm, -/obj/machinery/conveyor{ - dir = 8; - id = "mining" - }, -/turf/open/floor/iron, -/area/station/cargo/miningfoundry) "bLA" = ( /obj/structure/table/wood, /obj/item/folder{ @@ -8812,6 +8832,13 @@ }, /turf/open/floor/iron/white, /area/station/science/lower) +"bYa" = ( +/obj/structure/chair{ + dir = 1 + }, +/obj/effect/turf_decal/trimline/neutral/filled/line, +/turf/open/floor/iron, +/area/station/hallway/secondary/exit/departure_lounge) "bYd" = ( /obj/structure/chair/stool/bar/directional/south, /obj/effect/landmark/start/assistant, @@ -9767,6 +9794,22 @@ /obj/effect/turf_decal/tile/neutral/fourcorners, /turf/open/floor/iron/dark, /area/station/hallway/secondary/entry) +"cpK" = ( +/obj/effect/turf_decal/trimline/red/filled/corner{ + dir = 1 + }, +/obj/effect/turf_decal/trimline/red/filled/corner{ + dir = 4 + }, +/obj/effect/turf_decal/trimline/neutral/corner{ + dir = 1 + }, +/obj/effect/turf_decal/trimline/neutral/corner{ + dir = 4 + }, +/obj/effect/landmark/start/hangover, +/turf/open/floor/iron, +/area/station/hallway/secondary/exit/departure_lounge) "cpR" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/effect/decal/cleanable/dirt, @@ -10108,6 +10151,14 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/wood, /area/station/command/heads_quarters/captain) +"cvg" = ( +/obj/structure/bed/double, +/obj/effect/spawner/random/bedsheet/double, +/obj/effect/landmark/start/assistant, +/obj/structure/sign/clock/directional/north, +/obj/item/pillow/random, +/turf/open/floor/wood, +/area/station/commons/dorms) "cvz" = ( /obj/effect/turf_decal/trimline/neutral/filled/corner{ dir = 8 @@ -10417,18 +10468,6 @@ /obj/structure/thermoplastic/light, /turf/open/openspace, /area/station/hallway/primary/tram/center) -"cAc" = ( -/obj/structure/table, -/obj/item/storage/box/beakers{ - pixel_x = 3; - pixel_y = 3 - }, -/obj/machinery/camera/directional/north{ - c_tag = "Service - Hydroponics" - }, -/obj/effect/turf_decal/tile/green/fourcorners, -/turf/open/floor/iron/dark, -/area/station/service/hydroponics) "cAd" = ( /obj/structure/marker_beacon/burgundy, /turf/open/floor/plating/airless, @@ -11313,6 +11352,18 @@ /obj/machinery/light/directional/east, /turf/open/floor/noslip/tram, /area/station/hallway/primary/tram/left) +"cPK" = ( +/obj/structure/bed{ + dir = 4 + }, +/obj/effect/spawner/random/bedsheet{ + dir = 4 + }, +/obj/effect/landmark/start/assistant, +/obj/structure/sign/clock/directional/west, +/obj/item/pillow/random, +/turf/open/floor/carpet, +/area/station/commons/dorms) "cPM" = ( /turf/closed/wall, /area/station/engineering/atmos) @@ -11489,14 +11540,6 @@ "cSr" = ( /turf/closed/wall, /area/station/service/library) -"cSx" = ( -/obj/structure/bed/double, -/obj/effect/spawner/random/bedsheet/double, -/obj/effect/landmark/start/assistant, -/obj/structure/sign/clock/directional/north, -/obj/item/pillow/random, -/turf/open/floor/wood, -/area/station/commons/dorms) "cSC" = ( /obj/machinery/modular_computer/preset/id{ dir = 1 @@ -12996,6 +13039,17 @@ }, /turf/open/floor/plating/airless, /area/station/science/ordnance/bomb) +"duA" = ( +/obj/effect/turf_decal/trimline/neutral/filled/corner, +/obj/effect/turf_decal/trimline/neutral/filled/line{ + dir = 8 + }, +/obj/structure/cable, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/structure/extinguisher_cabinet/directional/west, +/turf/open/floor/iron, +/area/station/hallway/secondary/exit) "duB" = ( /turf/closed/wall/r_wall, /area/station/security/prison/garden) @@ -13337,17 +13391,6 @@ /obj/effect/spawner/structure/window/reinforced, /turf/open/floor/plating, /area/station/ai_monitored/turret_protected/aisat/foyer) -"dBL" = ( -/obj/effect/spawner/random/bedsheet/double{ - dir = 4 - }, -/obj/structure/bed/double{ - dir = 4 - }, -/obj/structure/sign/clock/directional/north, -/obj/item/pillow/random, -/turf/open/floor/carpet, -/area/station/commons/dorms) "dBM" = ( /obj/effect/decal/cleanable/dirt, /obj/effect/turf_decal/stripes/white/line{ @@ -14084,6 +14127,21 @@ }, /turf/open/floor/iron, /area/station/hallway/secondary/exit) +"dOM" = ( +/obj/effect/turf_decal/trimline/neutral/filled/line{ + dir = 1 + }, +/obj/effect/turf_decal/trimline/red/filled/corner{ + dir = 4 + }, +/obj/structure/extinguisher_cabinet/directional/north, +/obj/effect/turf_decal/trimline/neutral/corner{ + 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/hallway/secondary/exit/departure_lounge) "dPe" = ( /obj/effect/turf_decal/trimline/purple/filled/line{ dir = 8 @@ -14265,6 +14323,17 @@ /obj/effect/mapping_helpers/airlock/access/all/engineering/general, /turf/open/floor/plating/airless, /area/station/engineering/supermatter/room) +"dRz" = ( +/obj/structure/bed{ + dir = 4 + }, +/obj/effect/spawner/random/bedsheet{ + dir = 4 + }, +/obj/structure/sign/clock/directional/south, +/obj/item/pillow/random, +/turf/open/floor/carpet, +/area/station/commons/dorms) "dRJ" = ( /obj/structure/cable, /turf/open/floor/iron/cafeteria, @@ -15038,14 +15107,6 @@ /obj/machinery/status_display/ai/directional/south, /turf/open/floor/iron/dark, /area/station/ai_monitored/turret_protected/aisat_interior) -"eiC" = ( -/obj/structure/bed/double, -/obj/effect/spawner/random/bedsheet/double, -/obj/effect/landmark/start/hangover, -/obj/structure/sign/clock/directional/north, -/obj/item/pillow/random, -/turf/open/floor/wood, -/area/station/commons/dorms) "eiR" = ( /obj/structure/disposalpipe/segment{ dir = 10 @@ -16302,19 +16363,6 @@ /obj/effect/turf_decal/stripes/line, /turf/open/floor/iron/white, /area/station/science/xenobiology) -"eGR" = ( -/obj/effect/turf_decal/trimline/neutral/filled/line{ - dir = 9 - }, -/obj/effect/turf_decal/trimline/red/filled/corner{ - dir = 4 - }, -/obj/effect/turf_decal/trimline/neutral/corner{ - dir = 4 - }, -/obj/machinery/firealarm/directional/north, -/turf/open/floor/iron, -/area/station/hallway/secondary/exit/departure_lounge) "eGX" = ( /obj/structure/lattice, /obj/machinery/light/cold/dim/directional/east, @@ -16364,16 +16412,6 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/iron/white, /area/station/medical/medbay/central) -"eIj" = ( -/obj/structure/bed{ - dir = 8 - }, -/obj/effect/spawner/random/bedsheet, -/obj/effect/landmark/start/assistant, -/obj/structure/sign/clock/directional/east, -/obj/item/pillow/random, -/turf/open/floor/carpet, -/area/station/commons/dorms) "eIk" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/closed/wall/r_wall, @@ -17351,6 +17389,14 @@ /obj/structure/cable, /turf/open/floor/iron/dark, /area/station/cargo/miningdock/oresilo) +"fdc" = ( +/obj/machinery/brm, +/obj/machinery/conveyor{ + dir = 8; + id = "mining" + }, +/turf/open/floor/iron, +/area/station/cargo/miningfoundry) "fdr" = ( /obj/machinery/duct, /obj/structure/cable, @@ -18278,22 +18324,6 @@ }, /turf/open/floor/iron/dark, /area/station/security/evidence) -"fth" = ( -/obj/machinery/holopad, -/obj/structure/disposalpipe/segment{ - dir = 4 - }, -/obj/structure/cable, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/effect/turf_decal/trimline/tram/filled/line, -/obj/effect/turf_decal/trimline/tram/filled/warning, -/obj/machinery/button/transport/tram/directional/south{ - id = 2 - }, -/obj/machinery/transport/destination_sign/indicator/directional/south, -/obj/effect/landmark/observer_start, -/turf/open/floor/iron, -/area/station/hallway/primary/tram/center) "ftm" = ( /obj/effect/turf_decal/trimline/neutral/filled/corner, /obj/effect/turf_decal/trimline/neutral/filled/corner{ @@ -18354,6 +18384,10 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/iron, /area/station/cargo/storage) +"ftZ" = ( +/obj/effect/spawner/structure/window, +/turf/open/floor/plating, +/area/station/hallway/primary/tram/right) "fuj" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/open/floor/engine, @@ -19127,6 +19161,10 @@ /obj/structure/disposalpipe/segment, /turf/open/floor/iron/white, /area/station/science/lower) +"fKO" = ( +/obj/effect/spawner/structure/window, +/turf/open/floor/plating, +/area/station/command/heads_quarters/hop) "fKW" = ( /obj/structure/table/glass, /obj/item/radio/intercom/command, @@ -19339,22 +19377,6 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/catwalk_floor, /area/station/maintenance/tram/mid) -"fOk" = ( -/obj/effect/turf_decal/trimline/red/filled/corner{ - dir = 1 - }, -/obj/effect/turf_decal/trimline/red/filled/corner{ - dir = 4 - }, -/obj/effect/turf_decal/trimline/neutral/corner{ - dir = 1 - }, -/obj/effect/turf_decal/trimline/neutral/corner{ - dir = 4 - }, -/obj/effect/landmark/start/hangover, -/turf/open/floor/iron, -/area/station/hallway/secondary/exit/departure_lounge) "fOs" = ( /obj/structure/table/wood, /obj/item/flashlight/lamp, @@ -19461,13 +19483,6 @@ /obj/effect/turf_decal/trimline/yellow/arrow_ccw, /turf/open/floor/engine, /area/station/engineering/supermatter/room) -"fQO" = ( -/obj/structure/chair{ - dir = 1 - }, -/obj/effect/turf_decal/trimline/neutral/filled/line, -/turf/open/floor/iron, -/area/station/hallway/secondary/exit/departure_lounge) "fQV" = ( /obj/machinery/button/door/directional/east{ id = "offstationaccess"; @@ -19519,10 +19534,6 @@ }, /turf/open/floor/plating/airless, /area/station/science/ordnance/bomb) -"fRt" = ( -/obj/effect/spawner/structure/window, -/turf/open/floor/plating, -/area/station/command/heads_quarters/hop) "fRW" = ( /obj/machinery/newscaster/directional/east, /obj/effect/turf_decal/trimline/neutral/filled/line{ @@ -19915,17 +19926,6 @@ /obj/machinery/status_display/ai/directional/east, /turf/open/floor/circuit/green, /area/station/ai_monitored/turret_protected/ai_upload) -"fYH" = ( -/obj/effect/turf_decal/trimline/red/filled/line{ - dir = 1 - }, -/obj/effect/turf_decal/trimline/neutral/filled/warning{ - dir = 1 - }, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/turf/open/floor/iron, -/area/station/hallway/secondary/exit/departure_lounge) "fYW" = ( /obj/structure/grille, /obj/structure/lattice, @@ -20967,13 +20967,6 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/iron, /area/station/commons/fitness/recreation) -"gsS" = ( -/obj/structure/railing{ - dir = 1 - }, -/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4, -/turf/open/floor/iron, -/area/station/hallway/secondary/exit/departure_lounge) "gsT" = ( /obj/structure/easel, /obj/item/canvas/nineteen_nineteen, @@ -21135,16 +21128,6 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/open/floor/iron/freezer, /area/station/security/prison/shower) -"gvP" = ( -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/structure/cable, -/obj/structure/disposalpipe/segment{ - dir = 4 - }, -/obj/effect/turf_decal/trimline/neutral/filled/line, -/turf/open/floor/iron, -/area/station/hallway/secondary/exit/departure_lounge) "gvQ" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -21203,16 +21186,6 @@ /obj/effect/turf_decal/tile/neutral/fourcorners, /turf/open/floor/iron/dark, /area/station/ai_monitored/security/armory) -"gxg" = ( -/obj/effect/turf_decal/trimline/neutral/filled/line{ - dir = 8 - }, -/obj/structure/cable, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/machinery/firealarm/directional/west, -/turf/open/floor/iron, -/area/station/hallway/secondary/exit) "gxm" = ( /obj/effect/turf_decal/trimline/neutral/filled/corner{ dir = 8 @@ -22617,6 +22590,13 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/open/floor/iron/white, /area/station/medical/medbay/central) +"gXH" = ( +/obj/effect/turf_decal/trimline/neutral/filled/line{ + dir = 10 + }, +/obj/machinery/firealarm/directional/south, +/turf/open/floor/iron, +/area/station/hallway/secondary/exit/departure_lounge) "gYd" = ( /obj/machinery/rnd/production/techfab/department/security, /obj/effect/turf_decal/trimline/red/filled/line{ @@ -22906,6 +22886,23 @@ dir = 8 }, /area/station/ai_monitored/command/storage/eva) +"heS" = ( +/obj/machinery/holopad, +/obj/effect/turf_decal/bot, +/obj/machinery/camera/directional/east{ + c_tag = "Departures - West Main" + }, +/obj/structure/cable, +/obj/structure/disposalpipe/segment, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/effect/landmark/transport/nav_beacon/tram/nav/immovable_rod, +/obj/machinery/status_display/ai/directional/east, +/obj/effect/turf_decal/trimline/neutral/filled/line{ + dir = 4 + }, +/turf/open/floor/iron, +/area/station/hallway/secondary/exit/departure_lounge) "heY" = ( /obj/effect/turf_decal/siding/thinplating, /obj/structure/cable, @@ -22933,6 +22930,15 @@ }, /turf/open/floor/glass/reinforced, /area/station/ai_monitored/turret_protected/aisat/hallway) +"hft" = ( +/obj/structure/bed{ + dir = 8 + }, +/obj/effect/spawner/random/bedsheet, +/obj/structure/sign/clock/directional/east, +/obj/item/pillow/random, +/turf/open/floor/wood, +/area/station/commons/dorms) "hfy" = ( /obj/structure/cable, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -24707,12 +24713,6 @@ /obj/structure/cable, /turf/open/floor/iron, /area/station/security/prison) -"hQb" = ( -/obj/effect/turf_decal/trimline/neutral/filled/line{ - dir = 1 - }, -/turf/open/floor/iron, -/area/station/hallway/secondary/exit/departure_lounge) "hQk" = ( /obj/structure/transport/linear/public, /obj/effect/turf_decal/caution/stand_clear/red, @@ -24793,6 +24793,14 @@ /obj/structure/cable, /turf/open/floor/iron, /area/station/security/brig) +"hRK" = ( +/obj/structure/bed, +/obj/effect/spawner/random/bedsheet, +/obj/effect/landmark/start/hangover, +/obj/structure/sign/clock/directional/south, +/obj/item/pillow/random, +/turf/open/floor/carpet, +/area/station/commons/dorms) "hSm" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -24812,6 +24820,18 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/iron, /area/station/cargo/storage) +"hSt" = ( +/obj/effect/turf_decal/trimline/neutral/filled/line{ + dir = 8 + }, +/obj/machinery/camera/directional/west{ + c_tag = "Hallway - Central Escape Wing Entry" + }, +/obj/structure/cable, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/turf/open/floor/iron, +/area/station/hallway/secondary/exit) "hSH" = ( /obj/structure/chair{ dir = 1 @@ -24971,13 +24991,6 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/iron, /area/station/security/prison/safe) -"hVt" = ( -/obj/effect/turf_decal/trimline/neutral/filled/line{ - dir = 10 - }, -/obj/machinery/firealarm/directional/south, -/turf/open/floor/iron, -/area/station/hallway/secondary/exit/departure_lounge) "hVy" = ( /obj/machinery/portable_atmospherics/canister/nitrogen, /obj/machinery/light/floor, @@ -25021,16 +25034,6 @@ }, /turf/open/floor/iron/dark, /area/station/maintenance/radshelter/civil) -"hXq" = ( -/obj/structure/bed{ - dir = 8 - }, -/obj/effect/spawner/random/bedsheet, -/obj/effect/landmark/start/assistant, -/obj/structure/sign/clock/directional/east, -/obj/item/pillow/random, -/turf/open/floor/wood, -/area/station/commons/dorms) "hXJ" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/machinery/status_display/ai/directional/north, @@ -26206,6 +26209,15 @@ /obj/effect/turf_decal/stripes/white/full, /turf/open/floor/iron/white, /area/station/medical/medbay/central) +"iur" = ( +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/structure/cable, +/obj/structure/disposalpipe/segment{ + dir = 10 + }, +/turf/open/floor/iron, +/area/station/hallway/secondary/exit/departure_lounge) "iuz" = ( /obj/machinery/door/airlock/external{ name = "Port Docking Bay 1"; @@ -26214,6 +26226,13 @@ /obj/effect/mapping_helpers/airlock/cyclelink_helper, /turf/open/floor/plating, /area/station/hallway/secondary/entry) +"iuJ" = ( +/obj/structure/bed/double, +/obj/effect/spawner/random/bedsheet/double, +/obj/structure/sign/clock/directional/north, +/obj/item/pillow/random, +/turf/open/floor/carpet, +/area/station/commons/dorms) "iuM" = ( /obj/structure/table/wood/fancy/royalblue, /obj/machinery/door/window/left/directional/west{ @@ -26464,12 +26483,6 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/open/floor/iron/white, /area/station/medical/medbay/central) -"iyX" = ( -/obj/effect/turf_decal/trimline/neutral/filled/corner{ - dir = 4 - }, -/turf/open/floor/iron, -/area/station/hallway/secondary/exit) "izd" = ( /obj/effect/turf_decal/trimline/brown/filled/line, /obj/machinery/firealarm/directional/south, @@ -26972,14 +26985,6 @@ /obj/structure/window/reinforced/spawner/directional/south, /turf/open/floor/grass, /area/station/service/hydroponics) -"iJu" = ( -/obj/structure/bed, -/obj/effect/spawner/random/bedsheet, -/obj/effect/landmark/start/hangover, -/obj/structure/sign/clock/directional/south, -/obj/item/pillow/random, -/turf/open/floor/carpet, -/area/station/commons/dorms) "iJM" = ( /obj/machinery/light/warm/directional/north, /turf/open/floor/grass, @@ -28363,6 +28368,16 @@ }, /turf/open/floor/iron, /area/station/hallway/secondary/entry) +"jhn" = ( +/obj/effect/turf_decal/trimline/neutral/filled/line{ + dir = 8 + }, +/obj/structure/cable, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/firealarm/directional/west, +/turf/open/floor/iron, +/area/station/hallway/secondary/exit) "jhs" = ( /obj/effect/turf_decal/trimline/red/filled/line{ dir = 5 @@ -28749,6 +28764,16 @@ }, /turf/open/floor/iron, /area/station/security/checkpoint/supply) +"jnR" = ( +/obj/structure/bed{ + dir = 8 + }, +/obj/effect/spawner/random/bedsheet, +/obj/effect/landmark/start/assistant, +/obj/structure/sign/clock/directional/east, +/obj/item/pillow/random, +/turf/open/floor/carpet, +/area/station/commons/dorms) "jnY" = ( /obj/structure/table, /obj/effect/spawner/random/food_or_drink/cake_ingredients, @@ -28782,12 +28807,6 @@ }, /turf/open/floor/iron, /area/station/hallway/secondary/command) -"joy" = ( -/obj/machinery/door/firedoor, -/obj/effect/turf_decal/trimline/neutral/filled/line, -/obj/effect/turf_decal/stripes/white/full, -/turf/open/floor/iron, -/area/station/hallway/secondary/exit/departure_lounge) "joB" = ( /obj/effect/turf_decal/trimline/neutral/filled/line{ dir = 8 @@ -28953,6 +28972,18 @@ }, /turf/open/floor/iron, /area/station/hallway/secondary/service) +"jrc" = ( +/obj/effect/turf_decal/trimline/neutral/filled/line{ + dir = 4 + }, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/structure/cable, +/obj/effect/turf_decal/trimline/red/filled/corner{ + dir = 4 + }, +/turf/open/floor/iron, +/area/station/hallway/secondary/exit/departure_lounge) "jrz" = ( /obj/effect/decal/cleanable/dirt, /obj/machinery/light/small/dim/directional/north, @@ -29396,17 +29427,6 @@ "jyH" = ( /turf/closed/wall, /area/station/medical/pharmacy) -"jyN" = ( -/obj/structure/bed{ - dir = 4 - }, -/obj/effect/spawner/random/bedsheet{ - dir = 4 - }, -/obj/structure/sign/clock/directional/west, -/obj/item/pillow/random, -/turf/open/floor/carpet, -/area/station/commons/dorms) "jyQ" = ( /obj/structure/table/wood, /obj/item/folder/red, @@ -29579,6 +29599,14 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/open/floor/iron, /area/station/command/heads_quarters/qm) +"jBk" = ( +/obj/effect/turf_decal/trimline/neutral/filled/corner, +/obj/structure/cable, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/structure/disposalpipe/segment, +/turf/open/floor/iron, +/area/station/hallway/secondary/exit/departure_lounge) "jBn" = ( /obj/machinery/door/airlock/engineering/glass/critical{ heat_proof = 1; @@ -30314,14 +30342,6 @@ "jPM" = ( /turf/open/floor/iron/dark, /area/station/command/gateway) -"jPN" = ( -/obj/structure/chair{ - dir = 1 - }, -/obj/effect/turf_decal/trimline/neutral/filled/line, -/obj/effect/landmark/start/hangover, -/turf/open/floor/iron, -/area/station/hallway/secondary/exit/departure_lounge) "jPP" = ( /obj/machinery/duct, /obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2, @@ -30812,17 +30832,6 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/catwalk_floor, /area/station/maintenance/department/security) -"jYu" = ( -/obj/structure/bed{ - dir = 4 - }, -/obj/effect/spawner/random/bedsheet{ - dir = 4 - }, -/obj/structure/sign/clock/directional/west, -/obj/item/pillow/random, -/turf/open/floor/wood, -/area/station/commons/dorms) "jYz" = ( /obj/machinery/shieldgen, /obj/machinery/light/small/directional/north, @@ -30866,6 +30875,14 @@ "jYS" = ( /turf/closed/wall, /area/station/medical/chemistry) +"jYT" = ( +/obj/machinery/door/firedoor, +/obj/effect/turf_decal/trimline/neutral/filled/line{ + dir = 1 + }, +/obj/effect/turf_decal/stripes/white/full, +/turf/open/floor/iron, +/area/station/hallway/secondary/exit/departure_lounge) "jYU" = ( /obj/structure/transport/linear/public, /obj/effect/turf_decal/trimline/dark_red/warning{ @@ -30878,6 +30895,14 @@ /obj/effect/decal/cleanable/dirt, /turf/open/floor/iron/smooth, /area/station/maintenance/disposal) +"jZe" = ( +/obj/structure/chair{ + dir = 1 + }, +/obj/effect/turf_decal/trimline/neutral/filled/line, +/obj/machinery/light/directional/south, +/turf/open/floor/iron, +/area/station/hallway/secondary/exit/departure_lounge) "jZJ" = ( /obj/structure/chair/plastic, /obj/machinery/light/warm/directional/north, @@ -32360,18 +32385,6 @@ }, /turf/open/floor/iron, /area/station/commons/fitness/recreation) -"kxp" = ( -/obj/effect/turf_decal/trimline/neutral/filled/line{ - dir = 4 - }, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/structure/cable, -/obj/effect/turf_decal/trimline/red/filled/corner{ - dir = 4 - }, -/turf/open/floor/iron, -/area/station/hallway/secondary/exit/departure_lounge) "kxC" = ( /obj/effect/turf_decal/trimline/neutral/filled/line{ dir = 10 @@ -33114,18 +33127,6 @@ /obj/machinery/airalarm/directional/south, /turf/open/floor/circuit/green, /area/station/science/server) -"kJG" = ( -/obj/effect/turf_decal/trimline/neutral/filled/corner{ - dir = 8 - }, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/structure/cable, -/obj/structure/disposalpipe/segment{ - dir = 4 - }, -/turf/open/floor/iron, -/area/station/hallway/secondary/exit/departure_lounge) "kJU" = ( /obj/structure/chair/comfy/beige, /turf/open/floor/iron/grimy, @@ -33733,18 +33734,6 @@ }, /turf/open/floor/iron/white, /area/station/science/lab) -"kUg" = ( -/obj/structure/reagent_dispensers/watertank/high, -/obj/structure/railing{ - dir = 4 - }, -/obj/effect/turf_decal/trimline/yellow/warning{ - dir = 4 - }, -/obj/effect/turf_decal/tile/green/fourcorners, -/obj/machinery/newscaster/directional/south, -/turf/open/floor/iron/dark, -/area/station/service/hydroponics) "kUm" = ( /obj/structure/cable, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -35508,6 +35497,16 @@ /obj/effect/turf_decal/trimline/purple/filled/line, /turf/open/floor/iron/white, /area/station/science/xenobiology) +"lyR" = ( +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/structure/cable, +/obj/structure/disposalpipe/segment{ + dir = 4 + }, +/obj/effect/turf_decal/trimline/neutral/filled/line, +/turf/open/floor/iron, +/area/station/hallway/secondary/exit/departure_lounge) "lyV" = ( /obj/effect/turf_decal/trimline/neutral/filled/line, /obj/effect/decal/cleanable/dirt, @@ -36143,6 +36142,16 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/violet/visible, /turf/open/floor/iron, /area/station/engineering/atmos) +"lLq" = ( +/obj/structure/bed{ + dir = 8 + }, +/obj/effect/spawner/random/bedsheet, +/obj/effect/landmark/start/assistant, +/obj/structure/sign/clock/directional/east, +/obj/item/pillow/random, +/turf/open/floor/wood, +/area/station/commons/dorms) "lLx" = ( /obj/structure/railing{ dir = 4 @@ -36179,16 +36188,6 @@ dir = 8 }, /area/station/medical/medbay/central) -"lLO" = ( -/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4, -/obj/effect/decal/cleanable/dirt, -/obj/structure/closet/secure_closet/personal, -/obj/effect/spawner/random/bureaucracy/briefcase, -/obj/machinery/power/apc/auto_name/directional/north, -/obj/structure/cable, -/obj/effect/turf_decal/tile/neutral/fourcorners, -/turf/open/floor/iron/dark, -/area/station/commons/vacant_room/commissary) "lLP" = ( /obj/effect/turf_decal/trimline/blue/filled/corner{ dir = 8 @@ -36227,14 +36226,6 @@ /obj/structure/cable, /turf/open/floor/iron, /area/station/engineering/gravity_generator) -"lMi" = ( -/obj/machinery/vending/snack/blue, -/obj/effect/turf_decal/tile/neutral/fourcorners, -/obj/effect/turf_decal/siding/thinplating/dark{ - dir = 6 - }, -/turf/open/floor/iron/dark, -/area/station/hallway/secondary/exit) "lMw" = ( /obj/machinery/door/airlock{ id_tag = "Toilet3"; @@ -36546,6 +36537,12 @@ /obj/structure/ladder, /turf/open/floor/iron/smooth, /area/station/hallway/primary/tram/right) +"lRx" = ( +/obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2{ + dir = 1 + }, +/turf/open/floor/iron, +/area/station/hallway/secondary/exit/departure_lounge) "lRC" = ( /obj/effect/turf_decal/trimline/blue/filled/corner, /obj/effect/turf_decal/trimline/neutral/corner, @@ -38590,15 +38587,6 @@ }, /turf/open/floor/iron/dark, /area/station/service/hydroponics) -"mDz" = ( -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/structure/cable, -/obj/structure/disposalpipe/segment{ - dir = 10 - }, -/turf/open/floor/iron, -/area/station/hallway/secondary/exit/departure_lounge) "mDC" = ( /obj/machinery/air_sensor/carbon_tank, /turf/open/floor/engine/co2, @@ -38709,6 +38697,19 @@ }, /turf/open/floor/engine, /area/station/science/xenobiology) +"mFj" = ( +/obj/structure/reagent_dispensers/watertank/high, +/obj/structure/railing{ + dir = 4 + }, +/obj/effect/turf_decal/trimline/yellow/warning{ + dir = 4 + }, +/obj/effect/turf_decal/tile/green/fourcorners, +/obj/machinery/newscaster/directional/south, +/obj/item/reagent_containers/cup/watering_can, +/turf/open/floor/iron/dark, +/area/station/service/hydroponics) "mFo" = ( /obj/effect/turf_decal/trimline/red/filled/line{ dir = 4 @@ -39138,13 +39139,6 @@ }, /turf/open/floor/iron/dark, /area/station/medical/storage) -"mMF" = ( -/obj/effect/turf_decal/trimline/neutral/filled/line{ - dir = 4 - }, -/obj/structure/sign/departments/evac/directional/east, -/turf/open/floor/iron, -/area/station/hallway/secondary/exit) "mMK" = ( /obj/structure/cable, /obj/effect/turf_decal/sand/plating, @@ -40855,14 +40849,6 @@ }, /turf/open/floor/iron/stairs/right, /area/station/hallway/secondary/construction/engineering) -"nsA" = ( -/obj/machinery/door/firedoor, -/obj/effect/turf_decal/trimline/neutral/filled/line{ - dir = 1 - }, -/obj/effect/turf_decal/stripes/white/full, -/turf/open/floor/iron, -/area/station/hallway/secondary/exit/departure_lounge) "nsK" = ( /obj/effect/turf_decal/trimline/purple/filled/corner{ dir = 8 @@ -41589,15 +41575,6 @@ }, /turf/open/floor/iron/white, /area/station/science/ordnance/office) -"nGF" = ( -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/structure/cable, -/obj/structure/disposalpipe/segment{ - dir = 4 - }, -/turf/open/floor/iron, -/area/station/hallway/secondary/exit) "nGI" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/wood/parquet, @@ -41723,6 +41700,13 @@ /obj/effect/spawner/structure/window, /turf/open/floor/plating, /area/station/maintenance/tram/left) +"nJx" = ( +/obj/structure/railing{ + dir = 1 + }, +/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4, +/turf/open/floor/iron, +/area/station/hallway/secondary/exit/departure_lounge) "nJF" = ( /obj/structure/bookcase/random/adult, /turf/open/floor/wood/parquet, @@ -42112,6 +42096,12 @@ }, /turf/open/floor/iron, /area/station/hallway/secondary/construction/engineering) +"nQq" = ( +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/structure/cable, +/turf/open/floor/iron, +/area/station/hallway/secondary/exit/departure_lounge) "nQr" = ( /obj/effect/turf_decal/trimline/brown/filled/line{ dir = 8 @@ -43035,12 +43025,6 @@ /obj/effect/turf_decal/tile/purple/fourcorners, /turf/open/floor/iron/white, /area/station/science/auxlab/firing_range) -"ogD" = ( -/obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2{ - dir = 1 - }, -/turf/open/floor/iron, -/area/station/hallway/secondary/exit/departure_lounge) "ohd" = ( /obj/structure/table, /turf/open/floor/iron/dark, @@ -44228,6 +44212,15 @@ }, /turf/open/floor/iron, /area/station/cargo/office) +"oGG" = ( +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/structure/cable, +/obj/structure/disposalpipe/segment{ + dir = 4 + }, +/turf/open/floor/iron, +/area/station/hallway/secondary/exit) "oGJ" = ( /turf/closed/mineral/random/stationside/asteroid/porus, /area/station/medical/chemistry) @@ -44526,6 +44519,16 @@ }, /turf/open/space/openspace, /area/station/solars/port) +"oOP" = ( +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/structure/cable, +/obj/structure/disposalpipe/segment{ + dir = 4 + }, +/obj/effect/turf_decal/trimline/neutral/filled/corner, +/turf/open/floor/iron, +/area/station/hallway/secondary/exit) "oOT" = ( /obj/structure/table/wood, /obj/item/food/grown/poppy{ @@ -45342,6 +45345,17 @@ /obj/machinery/light/directional/east, /turf/open/floor/iron/showroomfloor, /area/station/security/warden) +"pfm" = ( +/obj/effect/spawner/random/bedsheet/double{ + dir = 4 + }, +/obj/structure/bed/double{ + dir = 4 + }, +/obj/structure/sign/clock/directional/north, +/obj/item/pillow/random, +/turf/open/floor/carpet, +/area/station/commons/dorms) "pfD" = ( /obj/machinery/computer/crew{ dir = 1 @@ -47367,15 +47381,6 @@ /obj/effect/landmark/navigate_destination/chapel, /turf/open/floor/carpet, /area/station/service/chapel) -"pNA" = ( -/obj/structure/bed{ - dir = 8 - }, -/obj/effect/spawner/random/bedsheet, -/obj/structure/sign/clock/directional/east, -/obj/item/pillow/random, -/turf/open/floor/wood, -/area/station/commons/dorms) "pNB" = ( /obj/structure/chair/comfy/beige, /obj/effect/landmark/start/hangover, @@ -47629,23 +47634,13 @@ /obj/effect/turf_decal/siding/thinplating/corner, /turf/open/floor/iron/dark, /area/station/science/xenobiology) -"pUb" = ( -/obj/machinery/holopad, -/obj/effect/turf_decal/bot, -/obj/machinery/camera/directional/east{ - c_tag = "Departures - West Main" - }, -/obj/structure/cable, -/obj/structure/disposalpipe/segment, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/effect/landmark/transport/nav_beacon/tram/nav/immovable_rod, -/obj/machinery/status_display/ai/directional/east, +"pTW" = ( /obj/effect/turf_decal/trimline/neutral/filled/line{ dir = 4 }, +/obj/structure/sign/departments/evac/directional/east, /turf/open/floor/iron, -/area/station/hallway/secondary/exit/departure_lounge) +/area/station/hallway/secondary/exit) "pUi" = ( /obj/structure/railing{ dir = 4 @@ -48094,6 +48089,22 @@ /obj/machinery/light/directional/south, /turf/open/floor/iron, /area/station/security/checkpoint/engineering) +"qbW" = ( +/obj/machinery/holopad, +/obj/structure/disposalpipe/segment{ + dir = 4 + }, +/obj/structure/cable, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/effect/turf_decal/trimline/tram/filled/line, +/obj/effect/turf_decal/trimline/tram/filled/warning, +/obj/machinery/button/transport/tram/directional/south{ + id = 2 + }, +/obj/machinery/transport/destination_sign/indicator/directional/south, +/obj/effect/landmark/observer_start, +/turf/open/floor/iron, +/area/station/hallway/primary/tram/center) "qch" = ( /obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2{ dir = 1 @@ -48307,13 +48318,6 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/iron/white, /area/station/medical/medbay/central) -"qfl" = ( -/obj/structure/bed/double, -/obj/effect/spawner/random/bedsheet/double, -/obj/structure/sign/clock/directional/north, -/obj/item/pillow/random, -/turf/open/floor/carpet, -/area/station/commons/dorms) "qfs" = ( /obj/structure/sign/poster/official/random/directional/north, /turf/open/floor/glass, @@ -48362,6 +48366,11 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/iron/showroomfloor, /area/station/security/lockers) +"qfQ" = ( +/obj/structure/cable, +/obj/machinery/power/apc/auto_name/directional/east, +/turf/open/floor/catwalk_floor, +/area/station/hallway/primary/tram/right) "qfS" = ( /obj/machinery/smartfridge/organ, /obj/structure/window/reinforced/spawner/directional/west, @@ -48983,6 +48992,16 @@ /obj/machinery/light/directional/west, /turf/open/floor/noslip/tram, /area/station/hallway/primary/tram/center) +"qrs" = ( +/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4, +/obj/effect/decal/cleanable/dirt, +/obj/structure/closet/secure_closet/personal, +/obj/effect/spawner/random/bureaucracy/briefcase, +/obj/machinery/power/apc/auto_name/directional/north, +/obj/structure/cable, +/obj/effect/turf_decal/tile/neutral/fourcorners, +/turf/open/floor/iron/dark, +/area/station/commons/vacant_room/commissary) "qrx" = ( /obj/effect/turf_decal/trimline/neutral/filled/corner{ dir = 4 @@ -49776,6 +49795,12 @@ /obj/effect/mapping_helpers/mail_sorting/science/genetics, /turf/open/floor/iron/white, /area/station/science/research) +"qFH" = ( +/obj/structure/railing{ + dir = 1 + }, +/turf/open/floor/iron, +/area/station/hallway/secondary/exit/departure_lounge) "qFK" = ( /obj/machinery/telecomms/processor/preset_four, /turf/open/floor/iron/dark/telecomms, @@ -50313,10 +50338,6 @@ /obj/effect/decal/cleanable/dirt, /turf/open/floor/plating, /area/station/maintenance/tram/left) -"qQM" = ( -/obj/effect/spawner/structure/window, -/turf/open/floor/plating, -/area/station/hallway/primary/tram/right) "qQW" = ( /obj/structure/reagent_dispensers/water_cooler, /obj/structure/sign/flag{ @@ -50925,6 +50946,20 @@ /obj/structure/cable, /turf/open/floor/iron, /area/station/engineering/gravity_generator) +"qZZ" = ( +/obj/effect/turf_decal/trimline/neutral/filled/line{ + dir = 8 + }, +/obj/structure/cable, +/obj/structure/disposalpipe/segment{ + dir = 5 + }, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/light/directional/west, +/obj/machinery/power/apc/auto_name/directional/west, +/turf/open/floor/iron, +/area/station/hallway/secondary/exit) "ram" = ( /obj/machinery/atmospherics/pipe/smart/manifold/violet/visible{ dir = 4 @@ -52349,14 +52384,6 @@ }, /turf/open/floor/plating, /area/station/command/heads_quarters/rd) -"rBv" = ( -/obj/item/kirbyplants/random, -/obj/effect/turf_decal/tile/neutral/fourcorners, -/obj/effect/turf_decal/siding/thinplating/dark{ - dir = 4 - }, -/turf/open/floor/iron/dark, -/area/station/hallway/secondary/exit) "rBy" = ( /obj/structure/table/reinforced, /obj/machinery/door/firedoor, @@ -52428,17 +52455,6 @@ "rCd" = ( /turf/closed/wall, /area/station/engineering/atmospherics_engine) -"rCf" = ( -/obj/structure/bed{ - dir = 4 - }, -/obj/effect/spawner/random/bedsheet{ - dir = 4 - }, -/obj/structure/sign/clock/directional/south, -/obj/item/pillow/random, -/turf/open/floor/carpet, -/area/station/commons/dorms) "rCs" = ( /obj/effect/turf_decal/delivery, /obj/machinery/navbeacon{ @@ -52668,11 +52684,6 @@ /obj/machinery/duct, /turf/open/floor/iron/freezer, /area/station/security/prison) -"rIj" = ( -/obj/structure/cable, -/obj/machinery/power/apc/auto_name/directional/east, -/turf/open/floor/catwalk_floor, -/area/station/hallway/primary/tram/right) "rIm" = ( /obj/machinery/lift_indicator/directional/north{ linked_elevator_id = "tram_upper_center_lift" @@ -54509,6 +54520,14 @@ }, /turf/open/floor/iron, /area/station/commons/fitness) +"snF" = ( +/obj/item/kirbyplants/random, +/obj/effect/turf_decal/tile/neutral/fourcorners, +/obj/effect/turf_decal/siding/thinplating/dark{ + dir = 4 + }, +/turf/open/floor/iron/dark, +/area/station/hallway/secondary/exit) "snK" = ( /obj/effect/turf_decal/trimline/brown/filled/line{ dir = 1 @@ -55289,32 +55308,12 @@ }, /turf/open/floor/iron, /area/station/security/prison) -"sAR" = ( -/obj/effect/turf_decal/trimline/neutral/filled/line{ - dir = 4 - }, -/obj/effect/landmark/event_spawn, -/obj/effect/landmark/start/hangover, -/turf/open/floor/iron, -/area/station/hallway/secondary/exit) "sBt" = ( /obj/structure/cable, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/open/floor/iron/dark, /area/station/maintenance/radshelter/civil) -"sBx" = ( -/obj/effect/turf_decal/trimline/neutral/filled/line{ - dir = 8 - }, -/obj/machinery/camera/directional/west{ - c_tag = "Hallway - Central Escape Wing Entry" - }, -/obj/structure/cable, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/turf/open/floor/iron, -/area/station/hallway/secondary/exit) "sBW" = ( /obj/effect/turf_decal/siding/thinplating/dark/corner{ dir = 8 @@ -55688,6 +55687,14 @@ }, /turf/open/floor/iron, /area/station/commons/dorms) +"sJx" = ( +/obj/structure/chair{ + dir = 1 + }, +/obj/effect/turf_decal/trimline/neutral/filled/line, +/obj/effect/landmark/start/hangover, +/turf/open/floor/iron, +/area/station/hallway/secondary/exit/departure_lounge) "sJQ" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -56312,14 +56319,6 @@ /obj/effect/landmark/start/assistant, /turf/open/floor/wood/large, /area/station/service/library) -"sUy" = ( -/obj/effect/turf_decal/trimline/neutral/filled/corner, -/obj/structure/cable, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/structure/disposalpipe/segment, -/turf/open/floor/iron, -/area/station/hallway/secondary/exit/departure_lounge) "sUD" = ( /obj/structure/chair, /obj/effect/turf_decal/stripes/line{ @@ -56394,6 +56393,12 @@ dir = 4 }, /area/station/service/theater) +"sWq" = ( +/obj/effect/turf_decal/trimline/neutral/filled/line{ + dir = 1 + }, +/turf/open/floor/iron, +/area/station/hallway/secondary/exit/departure_lounge) "sWF" = ( /obj/effect/turf_decal/trimline/neutral/filled/line{ dir = 1 @@ -56457,6 +56462,17 @@ /obj/effect/decal/cleanable/dirt, /turf/open/floor/iron, /area/station/cargo/drone_bay) +"sXo" = ( +/obj/effect/turf_decal/trimline/red/filled/line{ + dir = 1 + }, +/obj/effect/turf_decal/trimline/neutral/filled/warning{ + dir = 1 + }, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/turf/open/floor/iron, +/area/station/hallway/secondary/exit/departure_lounge) "sXL" = ( /obj/effect/turf_decal/trimline/white/line{ dir = 10 @@ -56850,6 +56866,24 @@ "tes" = ( /turf/open/floor/glass/reinforced, /area/station/command/heads_quarters/rd) +"teH" = ( +/obj/structure/reagent_dispensers/watertank/high, +/obj/structure/railing{ + dir = 8 + }, +/obj/effect/turf_decal/trimline/yellow/warning{ + dir = 8 + }, +/obj/machinery/elevator_control_panel/directional/south{ + desc = "A small control panel used to move the kitchen dumbwaiter up and down."; + linked_elevator_id = "dumbwaiter_lift"; + name = "Dumbwaiter control Panel"; + preset_destination_names = list("2" = "Hydroponics", "3" = "Kitchen") + }, +/obj/effect/turf_decal/tile/green/fourcorners, +/obj/item/reagent_containers/cup/watering_can, +/turf/open/floor/iron/dark, +/area/station/service/hydroponics) "teM" = ( /obj/effect/turf_decal/trimline/neutral/filled/corner, /obj/effect/turf_decal/trimline/neutral/filled/corner{ @@ -58276,6 +58310,12 @@ }, /turf/open/floor/iron, /area/station/service/theater) +"tEk" = ( +/obj/effect/landmark/event_spawn, +/obj/structure/cable, +/obj/structure/disposalpipe/segment, +/turf/open/floor/iron, +/area/station/hallway/secondary/exit/departure_lounge) "tEl" = ( /obj/structure/chair/comfy/brown{ dir = 1 @@ -58503,6 +58543,18 @@ /mob/living/simple_animal/bot/floorbot, /turf/open/floor/iron/dark, /area/station/ai_monitored/turret_protected/aisat_interior) +"tIk" = ( +/obj/effect/turf_decal/trimline/neutral/filled/corner{ + dir = 8 + }, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/structure/cable, +/obj/structure/disposalpipe/segment{ + dir = 4 + }, +/turf/open/floor/iron, +/area/station/hallway/secondary/exit/departure_lounge) "tID" = ( /obj/structure/transport/linear/public, /obj/effect/landmark/transport/transport_id{ @@ -59187,6 +59239,17 @@ }, /turf/open/floor/iron, /area/station/security/prison) +"tUM" = ( +/obj/structure/bed{ + dir = 4 + }, +/obj/effect/spawner/random/bedsheet{ + dir = 4 + }, +/obj/structure/sign/clock/directional/west, +/obj/item/pillow/random, +/turf/open/floor/wood, +/area/station/commons/dorms) "tUT" = ( /obj/structure/cable, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -59709,12 +59772,6 @@ /obj/structure/cable, /turf/open/floor/iron, /area/station/hallway/secondary/entry) -"ueg" = ( -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/structure/cable, -/turf/open/floor/iron, -/area/station/hallway/secondary/exit/departure_lounge) "uel" = ( /obj/structure/closet/crate/secure{ desc = "A secure crate containing various materials for building a customised test-site."; @@ -59794,6 +59851,15 @@ "ufO" = ( /turf/open/floor/iron, /area/station/commons/fitness/recreation) +"ugf" = ( +/obj/structure/bed{ + dir = 8 + }, +/obj/effect/spawner/random/bedsheet, +/obj/structure/sign/clock/directional/east, +/obj/item/pillow/random, +/turf/open/floor/carpet, +/area/station/commons/dorms) "ugp" = ( /obj/effect/turf_decal/sand/plating, /turf/open/floor/plating, @@ -60389,6 +60455,14 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/open/floor/iron, /area/station/hallway/secondary/command) +"upb" = ( +/obj/structure/bed/double, +/obj/effect/spawner/random/bedsheet/double, +/obj/effect/landmark/start/hangover, +/obj/structure/sign/clock/directional/north, +/obj/item/pillow/random, +/turf/open/floor/wood, +/area/station/commons/dorms) "upe" = ( /obj/effect/landmark/start/cyborg, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -61501,16 +61575,6 @@ /obj/effect/turf_decal/trimline/red/filled/line, /turf/open/floor/iron, /area/station/security/prison/garden) -"uFM" = ( -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/structure/cable, -/obj/structure/disposalpipe/segment{ - dir = 4 - }, -/obj/effect/turf_decal/trimline/neutral/filled/corner, -/turf/open/floor/iron, -/area/station/hallway/secondary/exit) "uFX" = ( /obj/structure/lattice/catwalk, /obj/machinery/atmospherics/pipe/smart/simple/yellow/visible, @@ -62855,23 +62919,6 @@ /obj/structure/cable, /turf/open/floor/catwalk_floor, /area/station/maintenance/starboard/central) -"vcs" = ( -/obj/structure/reagent_dispensers/watertank/high, -/obj/structure/railing{ - dir = 8 - }, -/obj/effect/turf_decal/trimline/yellow/warning{ - dir = 8 - }, -/obj/machinery/elevator_control_panel/directional/south{ - desc = "A small control panel used to move the kitchen dumbwaiter up and down."; - linked_elevator_id = "dumbwaiter_lift"; - name = "Dumbwaiter control Panel"; - preset_destination_names = list("2" = "Hydroponics", "3" = "Kitchen") - }, -/obj/effect/turf_decal/tile/green/fourcorners, -/turf/open/floor/iron/dark, -/area/station/service/hydroponics) "vcv" = ( /obj/effect/turf_decal/trimline/blue/filled/line{ dir = 10 @@ -63303,17 +63350,6 @@ }, /turf/open/floor/plating, /area/station/science/ordnance/testlab) -"vjN" = ( -/obj/structure/bed/double{ - dir = 4 - }, -/obj/effect/spawner/random/bedsheet/double{ - dir = 4 - }, -/obj/structure/sign/clock/directional/north, -/obj/item/pillow/random, -/turf/open/floor/wood, -/area/station/commons/dorms) "vjT" = ( /obj/machinery/door/airlock/research/glass{ name = "Ordnance Lab" @@ -65129,15 +65165,6 @@ /obj/structure/cable, /turf/open/floor/iron, /area/station/security/checkpoint/escape) -"vRh" = ( -/obj/structure/bed{ - dir = 8 - }, -/obj/effect/spawner/random/bedsheet, -/obj/structure/sign/clock/directional/east, -/obj/item/pillow/random, -/turf/open/floor/carpet, -/area/station/commons/dorms) "vRm" = ( /obj/machinery/atmospherics/components/binary/pump{ name = "Port to Filter" @@ -65922,20 +65949,6 @@ /obj/item/pickaxe/mini, /turf/open/misc/asteroid, /area/station/medical/chemistry) -"wgt" = ( -/obj/effect/turf_decal/trimline/neutral/filled/line{ - dir = 8 - }, -/obj/structure/cable, -/obj/structure/disposalpipe/segment{ - dir = 5 - }, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/machinery/light/directional/west, -/obj/machinery/power/apc/auto_name/directional/west, -/turf/open/floor/iron, -/area/station/hallway/secondary/exit) "wgA" = ( /obj/effect/turf_decal/tile/neutral/tram, /obj/structure/transport/linear/tram, @@ -66142,6 +66155,19 @@ }, /turf/open/floor/iron, /area/station/hallway/primary/tram/right) +"wjd" = ( +/obj/structure/table, +/obj/item/storage/box/beakers{ + pixel_x = 3; + pixel_y = 3 + }, +/obj/machinery/camera/directional/north{ + c_tag = "Service - Hydroponics" + }, +/obj/effect/turf_decal/tile/green/fourcorners, +/obj/item/storage/box/syringes, +/turf/open/floor/iron/dark, +/area/station/service/hydroponics) "wjk" = ( /obj/machinery/door/airlock/maintenance_hatch{ name = "Security Maintenance Hatch" @@ -66676,14 +66702,6 @@ /obj/structure/cable, /turf/open/floor/circuit, /area/station/ai_monitored/turret_protected/aisat_interior) -"wvn" = ( -/obj/machinery/vending/cola/blue, -/obj/effect/turf_decal/siding/thinplating/dark{ - dir = 5 - }, -/obj/effect/turf_decal/tile/neutral/fourcorners, -/turf/open/floor/iron/dark, -/area/station/hallway/secondary/exit) "wvG" = ( /obj/effect/turf_decal/trimline/red/filled/corner{ dir = 1 @@ -66925,21 +66943,6 @@ /obj/effect/spawner/structure/window/reinforced, /turf/open/floor/plating, /area/station/security/checkpoint/escape) -"wzj" = ( -/obj/effect/turf_decal/trimline/neutral/filled/line{ - dir = 1 - }, -/obj/effect/turf_decal/trimline/red/filled/corner{ - dir = 4 - }, -/obj/structure/extinguisher_cabinet/directional/north, -/obj/effect/turf_decal/trimline/neutral/corner{ - 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/hallway/secondary/exit/departure_lounge) "wzk" = ( /obj/effect/turf_decal/trimline/red/filled/line{ dir = 5 @@ -67477,6 +67480,17 @@ /obj/machinery/atmospherics/pipe/smart/simple/green/visible, /turf/open/floor/iron, /area/station/engineering/atmos) +"wJe" = ( +/obj/structure/bed/double{ + dir = 4 + }, +/obj/effect/spawner/random/bedsheet/double{ + dir = 4 + }, +/obj/structure/sign/clock/directional/north, +/obj/item/pillow/random, +/turf/open/floor/wood, +/area/station/commons/dorms) "wJt" = ( /obj/machinery/door/poddoor{ id = "Secure Storage"; @@ -67498,6 +67512,18 @@ dir = 1 }, /area/station/command/bridge) +"wJF" = ( +/obj/machinery/door/firedoor, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/structure/cable, +/obj/structure/disposalpipe/segment{ + dir = 4 + }, +/obj/effect/turf_decal/trimline/neutral/filled/line, +/obj/effect/turf_decal/stripes/white/full, +/turf/open/floor/iron, +/area/station/hallway/secondary/exit/departure_lounge) "wJM" = ( /obj/structure/lattice/catwalk, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -67892,14 +67918,6 @@ }, /turf/open/floor/iron/white, /area/station/science/lower) -"wSl" = ( -/obj/structure/chair{ - dir = 1 - }, -/obj/effect/turf_decal/trimline/neutral/filled/line, -/obj/machinery/light/directional/south, -/turf/open/floor/iron, -/area/station/hallway/secondary/exit/departure_lounge) "wSm" = ( /obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2, /turf/open/floor/carpet, @@ -68006,6 +68024,14 @@ }, /turf/open/floor/wood, /area/station/command/meeting_room) +"wWh" = ( +/obj/machinery/vending/cola/blue, +/obj/effect/turf_decal/siding/thinplating/dark{ + dir = 5 + }, +/obj/effect/turf_decal/tile/neutral/fourcorners, +/turf/open/floor/iron/dark, +/area/station/hallway/secondary/exit) "wWn" = ( /obj/effect/decal/cleanable/dirt, /obj/machinery/door_buttons/airlock_controller{ @@ -68218,17 +68244,6 @@ /obj/effect/turf_decal/stripes/white/line, /turf/open/floor/iron, /area/station/hallway/primary/tram/center) -"xaq" = ( -/obj/effect/turf_decal/trimline/neutral/filled/corner, -/obj/effect/turf_decal/trimline/neutral/filled/line{ - dir = 8 - }, -/obj/structure/cable, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/structure/extinguisher_cabinet/directional/west, -/turf/open/floor/iron, -/area/station/hallway/secondary/exit) "xat" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -69694,12 +69709,6 @@ /obj/effect/spawner/structure/window/reinforced, /turf/open/floor/plating, /area/station/solars/port) -"xCl" = ( -/obj/structure/railing{ - dir = 1 - }, -/turf/open/floor/iron, -/area/station/hallway/secondary/exit/departure_lounge) "xCm" = ( /obj/item/kirbyplants/random, /obj/effect/turf_decal/tile/blue/anticorner/contrasted, @@ -70520,12 +70529,6 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/iron/white, /area/station/security/execution/education) -"xTP" = ( -/obj/effect/landmark/event_spawn, -/obj/structure/cable, -/obj/structure/disposalpipe/segment, -/turf/open/floor/iron, -/area/station/hallway/secondary/exit/departure_lounge) "xUb" = ( /obj/machinery/smartfridge/organ, /obj/structure/sign/warning/cold_temp/directional/east, @@ -86838,15 +86841,15 @@ imm wzJ dIy pZW -jYu +tUM fOs gnC elr -jyN +bzs pKZ ecu elr -jYu +tUM fOs gnC elr @@ -86855,11 +86858,11 @@ ujn elr ecu pKZ -aHa +cPK elr gnC fOs -jYu +tUM apC apC apC @@ -87120,7 +87123,7 @@ oir elr vyR eLl -rCf +dRz apC abM aaa @@ -89404,15 +89407,15 @@ qQq qQq oRE ncF -eiC +upb twk qRc elr -qfl +iuJ szo kYL elr -cSx +cvg twk qRc apC @@ -90432,15 +90435,15 @@ qQq qQq lyV ncF -vjN +wJe twk gnC elr -dBL +pfm szo ecu elr -vjN +wJe twk gnC apC @@ -92774,7 +92777,7 @@ oir elr vyR fQe -iJu +hRK jnq abM abM @@ -93010,11 +93013,11 @@ qRp elr vay elr -eIj +jnR pKZ kYL elr -pNA +hft fOs qRc oTA @@ -93023,11 +93026,11 @@ eZS oTA kYL pKZ -vRh +ugf elr qRc fOs -hXq +lLq jnq jnq jnq @@ -103248,7 +103251,7 @@ adg ykN qMf dyC -kUg +mFj nUP gvC cay @@ -103755,14 +103758,14 @@ iJn gzP uQb nUP -cAc +wjd wHX nWT adg ykN qMf mCR -vcs +teH nUP cQY aer @@ -118921,7 +118924,7 @@ aac aaa aaa xdZ -bLs +fdc cZQ jwy bvA @@ -152106,10 +152109,10 @@ wHT wHT sNr wHT -fRt -fRt +fKO +fKO jvf -fRt +fKO qkV jvf tPE @@ -153135,9 +153138,9 @@ wHT wHT wHT lUK -fRt +fKO jvf -fRt +fKO tki jvf loc @@ -169066,7 +169069,7 @@ sxW vyH iNr rOu -fth +qbW izU pLs sky @@ -185003,9 +185006,9 @@ bAj dJk vUE vUE -qQM +ftZ vUE -qQM +ftZ vUE nSI tXz @@ -185513,7 +185516,7 @@ vPB uCO fZS bMb -rIj +qfQ sUc lCy fiW @@ -185779,7 +185782,7 @@ fvD slr fiW nSI -lLO +qrs xts oNa sJZ @@ -186286,15 +186289,15 @@ iSf jha qDn ajg -wgt +qZZ kAO -sBx +hSt pgo kAO kAO udX -gxg -xaq +jhn +duA bPO iVy tJh @@ -186543,10 +186546,10 @@ fZS kDH vPB pzv -nGF +oGG geG geG -aGa +aFZ geG geG geG @@ -186799,14 +186802,14 @@ lMg qbu riS gAH -iyX -uFM -mMF +aFP +oOP +pTW wuF -sAR +aZm wuF -mMF -iyX +pTW +aFP aDI aHw aHE @@ -187056,15 +187059,15 @@ pSV pSV pSV pEx -nsA -aEB +jYT +wJF fmy -wvn -rBv -lMi +wWh +snF +aGq fmy -nsA -joy +jYT +aGw pEx fmy dbV @@ -187312,17 +187315,17 @@ xkI gbB pkD pSV -eGR +bxC joi -gvP +lyR xWu rUQ rUQ rUQ xWu -hQb +sWq eKD -hVt +gXH fmy fmy vPB @@ -187571,7 +187574,7 @@ aDN wzg tiM qSm -kJG +tIk aGb aGb aGb @@ -187827,11 +187830,11 @@ bNi aDN wzg tiM -xCl -mDz -xTP -sUy -pUb +qFH +iur +tEk +jBk +heS nfJ rdT lgO @@ -188083,11 +188086,11 @@ wJV wXP loQ wAh -fOk -gsS -ueg -ogD -wSl +cpK +nJx +nQq +lRx +jZe fmy aGs kIo @@ -188341,10 +188344,10 @@ fam aDN wzg tiM -xCl -ueg +qFH +nQq qSm -jPN +sJx rUQ aGt kIo @@ -188598,10 +188601,10 @@ krq eIS vQX dJp -kxp +jrc fio qSm -fQO +bYa rUQ lai kIo @@ -188856,9 +188859,9 @@ pSV pSV fmy fmy -wzj +dOM qSm -jPN +sJx rUQ lai kIo @@ -189113,9 +189116,9 @@ ifU kLI kFu uCy -fYH +sXo qSm -fQO +bYa rUQ lai qSm @@ -189372,7 +189375,7 @@ cHS svC nny qSm -wSl +jZe xWu uuS qSm diff --git a/code/__DEFINES/_flags.dm b/code/__DEFINES/_flags.dm index 55b5b12b531accd..75dccb49fdae3f3 100644 --- a/code/__DEFINES/_flags.dm +++ b/code/__DEFINES/_flags.dm @@ -193,6 +193,8 @@ GLOBAL_LIST_INIT(bitflags, list(1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 204 #define INDESTRUCTIBLE (1<<6) /// can't be frozen #define FREEZE_PROOF (1<<7) +/// can't be shuttle crushed. +#define SHUTTLE_CRUSH_PROOF (1<<8) //tesla_zap #define ZAP_MACHINE_EXPLOSIVE (1<<0) diff --git a/code/__DEFINES/access.dm b/code/__DEFINES/access.dm index 7a1e91cd4085016..08c06ebcc739f37 100644 --- a/code/__DEFINES/access.dm +++ b/code/__DEFINES/access.dm @@ -294,6 +294,7 @@ ACCESS_DETECTIVE, \ ACCESS_ENGINE_EQUIP, \ ACCESS_ENGINEERING, \ + ACCESS_EVA, \ ACCESS_EXTERNAL_AIRLOCKS, \ ACCESS_GATEWAY, \ ACCESS_GENETICS, \ diff --git a/code/__DEFINES/alerts.dm b/code/__DEFINES/alerts.dm index 1933b592d55c592..591d212ad30fcc1 100644 --- a/code/__DEFINES/alerts.dm +++ b/code/__DEFINES/alerts.dm @@ -47,7 +47,6 @@ #define ALERT_HACKING_APC "hackingapc" /** MODsuit/Mech related */ -#define ALERT_MODSUIT_CHARGE "mod_charge" #define ALERT_MECH_DAMAGE "mech_damage" /** Food related */ diff --git a/code/__DEFINES/atmospherics/atmos_piping.dm b/code/__DEFINES/atmospherics/atmos_piping.dm index 1993f10222523e3..3870a7aed34acd2 100644 --- a/code/__DEFINES/atmospherics/atmos_piping.dm +++ b/code/__DEFINES/atmospherics/atmos_piping.dm @@ -9,11 +9,13 @@ #define EAST_SHORTPIPE (1<<6) #define WEST_SHORTPIPE (1<<7) // Helpers to convert cardinals to and from pipe bitfields -// Assumes X_FULLPIPE = X, X_SHORTPIPE >> 4 = X as above +// Assumes X_FULLPIPE = X, X_SHORTPIPE >> 4 = X, X_PIPECAPS >> 8 = X as above #define FULLPIPE_TO_CARDINALS(bitfield) ((bitfield) & ALL_CARDINALS) #define SHORTPIPE_TO_CARDINALS(bitfield) (((bitfield) >> 4) & ALL_CARDINALS) +#define PIPECAPS_TO_CARDINALS(bitfield) (((bitfield) >> 8) & ALL_CARDINALS) #define CARDINAL_TO_FULLPIPES(cardinals) (cardinals) #define CARDINAL_TO_SHORTPIPES(cardinals) ((cardinals) << 4) +#define CARDINAL_TO_PIPECAPS(cardinals) ((cardinals) << 8) // A pipe is a stub if it only has zero or one permitted direction. For a regular pipe this is nonsensical, and there are no pipe sprites for this, so it is not allowed. #define ISSTUB(bits) !((bits) & ((bits) - 1)) #define ISNOTSTUB(bits) ((bits) & ((bits) - 1)) diff --git a/code/__DEFINES/atom_hud.dm b/code/__DEFINES/atom_hud.dm index 180bb317fedb4b4..d2e6633e1dddca1 100644 --- a/code/__DEFINES/atom_hud.dm +++ b/code/__DEFINES/atom_hud.dm @@ -124,6 +124,7 @@ #define SECHUD_SCIENTIST "hudscientist" #define SECHUD_SHAFT_MINER "hudshaftminer" #define SECHUD_STATION_ENGINEER "hudstationengineer" +#define SECHUD_VETERAN_ADVISOR "hudveteranadvisor" #define SECHUD_VIROLOGIST "hudvirologist" #define SECHUD_WARDEN "hudwarden" diff --git a/code/__DEFINES/basic_mobs.dm b/code/__DEFINES/basic_mobs.dm index c7275f7c423e706..b673d0e7a120b15 100644 --- a/code/__DEFINES/basic_mobs.dm +++ b/code/__DEFINES/basic_mobs.dm @@ -12,6 +12,8 @@ #define FLAMMABLE_MOB (1<<3) /// Mob never takes damage from unarmed attacks #define IMMUNE_TO_FISTS (1<<4) +/// Mob is immune to getting wet +#define IMMUNE_TO_GETTING_WET (1<<5) /// Temporary trait applied when an attack forecast animation has completed #define TRAIT_BASIC_ATTACK_FORECAST "trait_basic_attack_forecast" diff --git a/code/__DEFINES/client.dm b/code/__DEFINES/client.dm index 0914bc025adda11..17571b5270bb12f 100644 --- a/code/__DEFINES/client.dm +++ b/code/__DEFINES/client.dm @@ -1,11 +1,6 @@ /// Checks if the given target is either a client or a mock client #define IS_CLIENT_OR_MOCK(target) (istype(target, /client) || istype(target, /datum/client_interface)) -/// Ensures that the client has been fully initialized via New(), and can't somehow execute actions before that. Security measure. -/// WILL RETURN OUT OF THE ENTIRE PROC COMPLETELY IF THE CLIENT IS NOT FULLY INITIALIZED. BE WARNED IF YOU WANT RETURN VALUES. -#define VALIDATE_CLIENT(target)\ - if (!target.fully_created) {\ - to_chat(target, span_warning("You are not fully initialized yet! Please wait a moment."));\ - log_access("Client [key_name(target)] attempted to execute a verb before being fully initialized.");\ - return\ - } +/// Checks to see if a /client has fully gone through New() as a safeguard against certain operations. +/// Should return the boolean value of the fully_created var, which should be TRUE if New() has finished running. FALSE otherwise. +#define VALIDATE_CLIENT_INITIALIZATION(target) (target.fully_created) diff --git a/code/__DEFINES/combat.dm b/code/__DEFINES/combat.dm index 33b7853cfd0b865..e97653e50221ee7 100644 --- a/code/__DEFINES/combat.dm +++ b/code/__DEFINES/combat.dm @@ -385,3 +385,8 @@ GLOBAL_LIST_INIT(arm_zones, list(BODY_ZONE_L_ARM, BODY_ZONE_R_ARM)) #define SHOVE_BLOCKED (1<<5) ///If the obstacle is an object at the border of the turf (so no signal from being sent to the other turf) #define SHOVE_DIRECTIONAL_BLOCKED (1<<6) + +///Deathmatch lobby current status +#define DEATHMATCH_NOT_PLAYING 0 +#define DEATHMATCH_PRE_PLAYING 1 +#define DEATHMATCH_PLAYING 2 diff --git a/code/__DEFINES/construction/material.dm b/code/__DEFINES/construction/material.dm index 24ab2eb33032713..445b4e0dc88e481 100644 --- a/code/__DEFINES/construction/material.dm +++ b/code/__DEFINES/construction/material.dm @@ -15,8 +15,8 @@ #define MAXCOIL 30 //Category of materials -/// Is the material from an ore? currently unused but exists atm for categorizations sake -#define MAT_CATEGORY_ORE "ore capable" +/// Can this material be stored in the ore silo +#define MAT_CATEGORY_SILO "silo capable" /// Hard materials, such as iron or silver #define MAT_CATEGORY_RIGID "rigid material" /// Materials that can be used to craft items @@ -68,13 +68,13 @@ //Stock market stock values. /// How much quantity of a material stock exists for common materials like iron & glass. -#define MATERIAL_QUANTITY_COMMON 25000 +#define MATERIAL_QUANTITY_COMMON 5000 /// How much quantity of a material stock exists for uncommon materials like silver & titanium. -#define MATERIAL_QUANTITY_UNCOMMON 10000 +#define MATERIAL_QUANTITY_UNCOMMON 1000 /// How much quantity of a material stock exists for rare materials like gold, uranium, & diamond. -#define MATERIAL_QUANTITY_RARE 2500 +#define MATERIAL_QUANTITY_RARE 200 /// How much quantity of a material stock exists for exotic materials like diamond & bluespace crystals. -#define MATERIAL_QUANTITY_EXOTIC 500 +#define MATERIAL_QUANTITY_EXOTIC 50 // The number of ore vents that will spawn boulders with this material. /// Is this material going to spawn often in ore vents? (80% of vents on lavaland) 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 3ddd0eb85387bed..3478d7b243f3834 100644 --- a/code/__DEFINES/dcs/signals/signals_mob/signals_mob_living.dm +++ b/code/__DEFINES/dcs/signals/signals_mob/signals_mob_living.dm @@ -13,6 +13,9 @@ /// Called when an organ gets surgically removed (mob/living/user, mob/living/carbon/old_owner, target_zone, obj/item/tool) #define COMSIG_ORGAN_SURGICALLY_REMOVED "organ_surgically_removed" +///Called when movement intent is toggled. +#define COMSIG_MOVE_INTENT_TOGGLED "move_intent_toggled" + ///from base of mob/update_transform() #define COMSIG_LIVING_POST_UPDATE_TRANSFORM "living_post_update_transform" diff --git a/code/__DEFINES/dcs/signals/signals_object.dm b/code/__DEFINES/dcs/signals/signals_object.dm index 3654b4cfce5d324..7c278008a14950e 100644 --- a/code/__DEFINES/dcs/signals/signals_object.dm +++ b/code/__DEFINES/dcs/signals/signals_object.dm @@ -158,6 +158,9 @@ /// Return to prevent the default behavior (attack_selfing) from ocurring. #define COMPONENT_ITEM_ACTION_SLOT_INVALID (1<<0) +/// Sent from /obj/item/attack_atom(): (atom/attacked_atom, mob/living/user) +#define COMSIG_ITEM_POST_ATTACK_ATOM "item_post_attack_atom" + ///from base of mob/living/carbon/attacked_by(): (mob/living/carbon/target, mob/living/user, hit_zone) #define COMSIG_ITEM_ATTACK_ZONE "item_attack_zone" ///from base of obj/item/hit_reaction(): (owner, hitby, attack_text, final_block_chance, damage, attack_type, damage_type) @@ -401,6 +404,10 @@ ///sent to the projectile when spawning the item (shrapnel) that may be embedded: (new_item) #define COMSIG_PROJECTILE_ON_SPAWN_EMBEDDED "projectile_on_spawn_embedded" +/// from /obj/projectile/energy/fisher/on_hit() or /obj/item/gun/energy/recharge/fisher when striking a target +#define COMSIG_HIT_BY_SABOTEUR "hit_by_saboteur" + #define COMSIG_SABOTEUR_SUCCESS (1<<0) + // /obj/vehicle/sealed/car/vim signals ///from /datum/action/vehicle/sealed/noise/chime/Trigger(): () diff --git a/code/__DEFINES/dcs/signals/signals_saboteur.dm b/code/__DEFINES/dcs/signals/signals_saboteur.dm deleted file mode 100644 index 5b0fef52aee666d..000000000000000 --- a/code/__DEFINES/dcs/signals/signals_saboteur.dm +++ /dev/null @@ -1,5 +0,0 @@ -// Light disruptor. Not to be confused with the light eater, which permanently disables lights. - -/// from /obj/projectile/energy/fisher/on_hit() or /obj/item/gun/energy/recharge/fisher when striking a target -#define COMSIG_HIT_BY_SABOTEUR "HIT_BY_SABOTEUR" - #define COMSIG_SABOTEUR_SUCCESS (1<<0) diff --git a/code/__DEFINES/economy.dm b/code/__DEFINES/economy.dm index 93b0678581ae8cb..32408e4f538e97d 100644 --- a/code/__DEFINES/economy.dm +++ b/code/__DEFINES/economy.dm @@ -70,12 +70,13 @@ #define PAYMENT_CLINICAL "clinical" #define PAYMENT_FRIENDLY "friendly" #define PAYMENT_ANGRY "angry" +#define PAYMENT_VENDING "vending" #define MARKET_TREND_UPWARD 1 #define MARKET_TREND_DOWNWARD -1 #define MARKET_TREND_STABLE 0 -#define MARKET_EVENT_PROBABILITY 1 //Probability of a market event firing, in percent. Fires once per material, every 20 seconds. +#define MARKET_EVENT_PROBABILITY 8 //Probability of a market event firing, in percent. Fires once per material, every stock market tick. #define MARKET_PROFIT_MODIFIER 0.8 //We don't make every sale a 1-1 of the actual buy price value, like with real life taxes and to encourage more smart trades diff --git a/code/__DEFINES/hud.dm b/code/__DEFINES/hud.dm index 5798fd29e82de95..0d2fb6b874d48b6 100644 --- a/code/__DEFINES/hud.dm +++ b/code/__DEFINES/hud.dm @@ -77,6 +77,7 @@ #define ui_building "EAST-4:22,SOUTH:21" #define ui_language_menu "EAST-4:6,SOUTH:21" #define ui_navigate_menu "EAST-4:22,SOUTH:5" +#define ui_floor_menu "EAST-4:14,SOUTH:37" //Upper-middle right (alerts) #define ui_alert1 "EAST-1:28,CENTER+5:27" @@ -143,6 +144,7 @@ #define ui_borg_alerts "CENTER+4:21,SOUTH:5" #define ui_borg_language_menu "CENTER+4:19,SOUTH+1:6" #define ui_borg_navigate_menu "CENTER+4:19,SOUTH+1:6" +#define ui_borg_floor_menu "CENTER+4:-13,SOUTH+1:6" //Aliens #define ui_alien_health "EAST,CENTER-1:15" @@ -151,6 +153,7 @@ #define ui_alien_storage_r "CENTER+1:18,SOUTH:5" #define ui_alien_language_menu "EAST-4:20,SOUTH:5" #define ui_alien_navigate_menu "EAST-4:20,SOUTH:5" +#define ui_alien_floor_menu "EAST-4:-12,SOUTH:5" //AI #define ui_ai_core "BOTTOM:6,RIGHT-4" @@ -159,6 +162,7 @@ #define ui_ai_state_laws "BOTTOM:6,RIGHT-1" #define ui_ai_mod_int "BOTTOM:6,RIGHT" #define ui_ai_language_menu "BOTTOM+1:8,RIGHT-1:30" +#define ui_ai_floor_menu "BOTTOM+1:8,RIGHT-1:14" #define ui_ai_crew_monitor "BOTTOM:6,CENTER-1" #define ui_ai_crew_manifest "BOTTOM:6,CENTER" @@ -200,6 +204,7 @@ #define ui_ghost_pai "SOUTH: 6, CENTER+1:24" #define ui_ghost_minigames "SOUTH: 6, CENTER+2:24" #define ui_ghost_language_menu "SOUTH: 22, CENTER+3:8" +#define ui_ghost_floor_menu "SOUTH: 6, CENTER+3:8" //Blobbernauts #define ui_blobbernaut_overmind_health "EAST-1:28,CENTER+0:19" diff --git a/code/__DEFINES/icon_smoothing.dm b/code/__DEFINES/icon_smoothing.dm index c00361184a50a3f..efcbfdfb9403511 100644 --- a/code/__DEFINES/icon_smoothing.dm +++ b/code/__DEFINES/icon_smoothing.dm @@ -205,12 +205,18 @@ DEFINE_BITFIELD(smoothing_junction, list( #define SMOOTH_GROUP_CLEANABLE_DIRT S_OBJ(68) ///obj/effect/decal/cleanable/dirt -#define SMOOTH_GROUP_GAS_TANK S_OBJ(72) +#define SMOOTH_GROUP_GAS_TANK S_OBJ(69) + +#define SMOOTH_GROUP_SPIDER_WEB S_OBJ(70) // /obj/structure/spider/stickyweb +#define SMOOTH_GROUP_SPIDER_WEB_WALL S_OBJ(71) // /obj/structure/spider/stickyweb/sealed +#define SMOOTH_GROUP_SPIDER_WEB_ROOF S_OBJ(72) // /obj/structure/spider/passage +#define SMOOTH_GROUP_SPIDER_WEB_WALL_TOUGH S_OBJ(73) // /obj/structure/spider/stickyweb/sealed/thick +#define SMOOTH_GROUP_SPIDER_WEB_WALL_MIRROR S_OBJ(74) // /obj/structure/spider/stickyweb/sealed/reflector //SKYRAT EDIT ADDITION -#define SMOOTH_GROUP_SHUTTERS S_OBJ(73) +#define SMOOTH_GROUP_SHUTTERS S_OBJ(75) -#define SMOOTH_GROUP_WATER S_OBJ(74) ///obj/effect/abstract/liquid_turf +#define SMOOTH_GROUP_WATER S_OBJ(76) ///obj/effect/abstract/liquid_turf //SKYRAT EDIT END /// Performs the work to set smoothing_groups and canSmoothWith. diff --git a/code/__DEFINES/instruments.dm b/code/__DEFINES/instruments.dm index fa09eee0dd799c4..bf54ddf1b908e63 100644 --- a/code/__DEFINES/instruments.dm +++ b/code/__DEFINES/instruments.dm @@ -6,6 +6,8 @@ /// Max number of playing notes per instrument. #define CHANNELS_PER_INSTRUMENT 128 +/// Minimum length a note should ever go for +#define INSTRUMENT_MIN_TOTAL_SUSTAIN 0.1 /// Maximum length a note should ever go for #define INSTRUMENT_MAX_TOTAL_SUSTAIN (5 SECONDS) @@ -16,8 +18,8 @@ /// Minimum volume for when the sound is considered dead. #define INSTRUMENT_MIN_SUSTAIN_DROPOFF 0 -#define SUSTAIN_LINEAR 1 -#define SUSTAIN_EXPONENTIAL 2 +#define SUSTAIN_LINEAR "Linear" +#define SUSTAIN_EXPONENTIAL "Exponential" // /datum/instrument instrument_flags #define INSTRUMENT_LEGACY (1<<0) //Legacy instrument. Implies INSTRUMENT_DO_NOT_AUTOSAMPLE diff --git a/code/__DEFINES/jobs.dm b/code/__DEFINES/jobs.dm index 38aeef7a7cb927d..5e7ac950062df58 100644 --- a/code/__DEFINES/jobs.dm +++ b/code/__DEFINES/jobs.dm @@ -49,6 +49,7 @@ #define JOB_CHIEF_ENGINEER "Chief Engineer" #define JOB_CHIEF_MEDICAL_OFFICER "Chief Medical Officer" #define JOB_BRIDGE_ASSISTANT "Bridge Assistant" +#define JOB_VETERAN_ADVISOR "Veteran Security Advisor" //Silicon #define JOB_AI "AI" #define JOB_CYBORG "Cyborg" @@ -180,10 +181,11 @@ #define JOB_DISPLAY_ORDER_ROBOTICIST 33 #define JOB_DISPLAY_ORDER_GENETICIST 34 #define JOB_DISPLAY_ORDER_HEAD_OF_SECURITY 35 -#define JOB_DISPLAY_ORDER_WARDEN 36 -#define JOB_DISPLAY_ORDER_DETECTIVE 37 -#define JOB_DISPLAY_ORDER_SECURITY_OFFICER 38 -#define JOB_DISPLAY_ORDER_PRISONER 39 +#define JOB_DISPLAY_ORDER_VETERAN_ADVISOR 36 +#define JOB_DISPLAY_ORDER_WARDEN 37 +#define JOB_DISPLAY_ORDER_DETECTIVE 38 +#define JOB_DISPLAY_ORDER_SECURITY_OFFICER 39 +#define JOB_DISPLAY_ORDER_PRISONER 40 #define JOB_DISPLAY_ORDER_SECURITY_MEDIC 100 //SKYRAT EDIT ADDITON #define JOB_DISPLAY_ORDER_CORRECTIONS_OFFICER 101 //SKYRAT EDIT ADDITON #define JOB_DISPLAY_ORDER_NANOTRASEN_CONSULTANT 102 //SKYRAT EDIT ADDITON @@ -248,6 +250,22 @@ /// This job is a head of staff. #define JOB_HEAD_OF_STAFF (1<<12) +DEFINE_BITFIELD(job_flags, list( + "JOB_ANNOUNCE_ARRIVAL" = JOB_ANNOUNCE_ARRIVAL, + "JOB_CREW_MANIFEST" = JOB_CREW_MANIFEST, + "JOB_EQUIP_RANK" = JOB_EQUIP_RANK, + "JOB_CREW_MEMBER" = JOB_CREW_MEMBER, + "JOB_NEW_PLAYER_JOINABLE" = JOB_NEW_PLAYER_JOINABLE, + "JOB_BOLD_SELECT_TEXT" = JOB_BOLD_SELECT_TEXT, + "JOB_REOPEN_ON_ROUNDSTART_LOSS" = JOB_REOPEN_ON_ROUNDSTART_LOSS, + "JOB_ASSIGN_QUIRKS" = JOB_ASSIGN_QUIRKS, + "JOB_CAN_BE_INTERN" = JOB_CAN_BE_INTERN, + "JOB_CANNOT_OPEN_SLOTS" = JOB_CANNOT_OPEN_SLOTS, + "JOB_HIDE_WHEN_EMPTY" = JOB_HIDE_WHEN_EMPTY, + "JOB_LATEJOIN_ONLY" = JOB_LATEJOIN_ONLY, + "JOB_HEAD_OF_STAFF" = JOB_HEAD_OF_STAFF, +)) + /// Combination flag for jobs which are considered regular crew members of the station. #define STATION_JOB_FLAGS (JOB_ANNOUNCE_ARRIVAL|JOB_CREW_MANIFEST|JOB_EQUIP_RANK|JOB_CREW_MEMBER|JOB_NEW_PLAYER_JOINABLE|JOB_REOPEN_ON_ROUNDSTART_LOSS|JOB_ASSIGN_QUIRKS|JOB_CAN_BE_INTERN) /// Combination flag for jobs which are considered heads of staff. diff --git a/code/__DEFINES/lighting.dm b/code/__DEFINES/lighting.dm index 55ade142b1d40da..4eba11db970fb71 100644 --- a/code/__DEFINES/lighting.dm +++ b/code/__DEFINES/lighting.dm @@ -71,7 +71,7 @@ #define LIGHTING_FORCE_UPDATE 3 #define FLASH_LIGHT_DURATION 2 -#define FLASH_LIGHT_POWER 3 +#define FLASH_LIGHT_POWER 2 #define FLASH_LIGHT_RANGE 3.8 // Emissive blocking. diff --git a/code/__DEFINES/logging.dm b/code/__DEFINES/logging.dm index a6102aa6e793809..13fdd4d0b80d92f 100644 --- a/code/__DEFINES/logging.dm +++ b/code/__DEFINES/logging.dm @@ -115,6 +115,7 @@ #define LOG_CATEGORY_TOOL "tool" #define LOG_CATEGORY_TRANSPORT "transport" #define LOG_CATEGORY_VIRUS "virus" +#define LOG_CATEGORY_CAVE_GENERATION "cave-generation" // Admin categories #define LOG_CATEGORY_ADMIN "admin" diff --git a/code/__DEFINES/mining.dm b/code/__DEFINES/mining.dm index 11d150a453db8b3..4b233a5d4f171ec 100644 --- a/code/__DEFINES/mining.dm +++ b/code/__DEFINES/mining.dm @@ -39,6 +39,17 @@ /// The chance of ore spawning in a wall that is VENT_PROX_FAR tiles to a vent. #define VENT_CHANCE_FAR 1 +/// The amount of ore that is mined from a wall that is VENT_PROX_VERY_HIGH tiles to a vent. +#define ORE_WALL_VERY_HIGH 5 +/// The amount of ore that is mined from a wall that is VENT_PROX_HIGH tiles to a vent. +#define ORE_WALL_HIGH 4 +/// The amount of ore that is mined from a wall that is VENT_PROX_MEDIUM tiles to a vent. +#define ORE_WALL_MEDIUM 3 +/// The amount of ore that is mined from a wall that is VENT_PROX_LOW tiles to a vent. +#define ORE_WALL_LOW 2 +/// The amount of ore that is mined from a wall that is VENT_PROX_FAR tiles to a vent. +#define ORE_WALL_FAR 1 + /// The number of points a miner gets for discovering a vent, multiplied by BOULDER_SIZE when completing a wave defense minus the discovery bonus. #define MINER_POINT_MULTIPLIER 100 /// The multiplier that gets applied for automatically generated mining points. diff --git a/code/__DEFINES/mobs.dm b/code/__DEFINES/mobs.dm index 2ffca767d857a22..e3a56e844ccebe1 100644 --- a/code/__DEFINES/mobs.dm +++ b/code/__DEFINES/mobs.dm @@ -1002,3 +1002,17 @@ GLOBAL_LIST_INIT(layers_to_offset, list( /// Types of bullets that mining mobs take full damage from #define MINING_MOB_PROJECTILE_VULNERABILITY list(BRUTE) + +// Sprites for photocopying butts +#define BUTT_SPRITE_HUMAN_MALE "human_male" +#define BUTT_SPRITE_HUMAN_FEMALE "human_female" +#define BUTT_SPRITE_LIZARD "lizard" +#define BUTT_SPRITE_QR_CODE "qr_code" +#define BUTT_SPRITE_XENOMORPH "xeno" +#define BUTT_SPRITE_DRONE "drone" +#define BUTT_SPRITE_CAT "cat" +#define BUTT_SPRITE_FLOWERPOT "flowerpot" +#define BUTT_SPRITE_GREY "grey" +#define BUTT_SPRITE_PLASMA "plasma" +#define BUTT_SPRITE_FUZZY "fuzzy" +#define BUTT_SPRITE_SLIME "slime" diff --git a/code/__DEFINES/procpath.dm b/code/__DEFINES/procpath.dm index 642ca3eab6cc806..16716d6c091f240 100644 --- a/code/__DEFINES/procpath.dm +++ b/code/__DEFINES/procpath.dm @@ -15,12 +15,12 @@ // below, their accesses are optimized away. /// A text string of the verb's name. - var/name as text + var/name = null as text|null /// The verb's help text or description. - var/desc as text + var/desc = null as text|null /// The category or tab the verb will appear in. - var/category as text + var/category = null as text|null /// Only clients/mobs with `see_invisibility` higher can use the verb. - var/invisibility as num + var/invisibility = null as num|null /// Whether or not the verb appears in statpanel and commandbar when you press space - var/hidden as num + var/hidden = null as num|null diff --git a/code/__DEFINES/robots.dm b/code/__DEFINES/robots.dm index 26b66f0de60c1a9..8aec247bfe29053 100644 --- a/code/__DEFINES/robots.dm +++ b/code/__DEFINES/robots.dm @@ -198,6 +198,8 @@ DEFINE_BITFIELD(bot_access_flags, list( #define JUDGE_IDCHECK (1<<1) #define JUDGE_WEAPONCHECK (1<<2) #define JUDGE_RECORDCHECK (1<<3) +///lowered threat level +#define JUDGE_CHILLOUT (1<<4) /// Above this level of assessed threat, Beepsky will attack you #define THREAT_ASSESS_DANGEROUS 4 @@ -215,6 +217,8 @@ DEFINE_BITFIELD(bot_access_flags, list( #define SECBOT_CHECK_RECORDS (1<<3) ///Whether we will stun & cuff or endlessly stun #define SECBOT_HANDCUFF_TARGET (1<<4) +///if it's currently affected by a saboteur bolt (lowered perp threat level) +#define SECBOT_SABOTEUR_AFFECTED (1<<5) DEFINE_BITFIELD(security_mode_flags, list( "SECBOT_DECLARE_ARRESTS" = SECBOT_DECLARE_ARRESTS, @@ -222,6 +226,7 @@ DEFINE_BITFIELD(security_mode_flags, list( "SECBOT_CHECK_WEAPONS" = SECBOT_CHECK_WEAPONS, "SECBOT_CHECK_RECORDS" = SECBOT_CHECK_RECORDS, "SECBOT_HANDCUFF_TARGET" = SECBOT_HANDCUFF_TARGET, + "SECBOT_SABOTEUR_AFFECTED" = SECBOT_SABOTEUR_AFFECTED, )) //MedBOT defines diff --git a/code/__DEFINES/say.dm b/code/__DEFINES/say.dm index a8a6cd673f7a0db..5bb10e71aea51fc 100644 --- a/code/__DEFINES/say.dm +++ b/code/__DEFINES/say.dm @@ -76,7 +76,7 @@ #define SPAN_CLOWN "clown" #define SPAN_SINGING "singing" #define SPAN_TAPE_RECORDER "tape_recorder" -#define SPAN_HELIUM "small" +#define SPAN_SMALL_VOICE "small" //bitflag #defines for return value of the radio() proc. #define ITALICS (1<<0) diff --git a/code/__DEFINES/sound.dm b/code/__DEFINES/sound.dm index 6890fd2ca50479b..a24a929391f2ff2 100644 --- a/code/__DEFINES/sound.dm +++ b/code/__DEFINES/sound.dm @@ -235,3 +235,4 @@ GLOBAL_LIST_INIT(announcer_keys, list( #define SFX_ROCK_TAP "rock_tap" #define SFX_SEAR "sear" #define SFX_REEL "reel" +#define SFX_RATTLE "rattle" diff --git a/code/__DEFINES/status_effects.dm b/code/__DEFINES/status_effects.dm index 4e901c4ba2ce25c..d7e981802619ca6 100644 --- a/code/__DEFINES/status_effects.dm +++ b/code/__DEFINES/status_effects.dm @@ -154,8 +154,8 @@ #define set_drowsiness(duration) set_timed_status_effect(duration, /datum/status_effect/drowsiness) #define set_drowsiness_if_lower(duration) set_timed_status_effect(duration, /datum/status_effect/drowsiness, TRUE) -#define adjust_pacifism(duration) adjust_timed_status_effect(/datum/status_effect/pacify, duration) -#define set_pacifism(duration) set_timed_status_effect(/datum/status_effect/pacify, duration) +#define adjust_pacifism(duration) adjust_timed_status_effect(duration, /datum/status_effect/pacify) +#define set_pacifism(duration) set_timed_status_effect(duration, /datum/status_effect/pacify) #define adjust_eye_blur(duration) adjust_timed_status_effect(duration, /datum/status_effect/eye_blur) #define adjust_eye_blur_up_to(duration, up_to) adjust_timed_status_effect(duration, /datum/status_effect/eye_blur, up_to) diff --git a/code/__DEFINES/text.dm b/code/__DEFINES/text.dm index c98baa5f4aa5426..5dac5df883ddcf0 100644 --- a/code/__DEFINES/text.dm +++ b/code/__DEFINES/text.dm @@ -58,6 +58,12 @@ /// Removes everything enclose in < and > inclusive of the bracket, and limits the length of the message. #define STRIP_HTML_FULL(text, limit) (GLOB.html_tags.Replace(copytext(text, 1, limit), "")) +/** + * stuff like `copytext(input, length(input))` will trim the last character of the input, + * because DM does it so it copies until the char BEFORE the `end` arg, so we need to bump `end` by 1 in these cases. + */ +#define PREVENT_CHARACTER_TRIM_LOSS(integer) (integer + 1) + /// Folder directory for strings #define STRING_DIRECTORY "strings" diff --git a/code/__DEFINES/time.dm b/code/__DEFINES/time.dm index 1935c3c0aee3d4c..6a2a5152903bad9 100644 --- a/code/__DEFINES/time.dm +++ b/code/__DEFINES/time.dm @@ -39,6 +39,7 @@ #define PRIDE_WEEK "Pride Week" #define MOTH_WEEK "Moth Week" #define IAN_HOLIDAY "Ian's Birthday" +#define HOTDOG_DAY "National Hot Dog Day" /* Days of the week to make it easier to reference them. diff --git a/code/__DEFINES/traits/declarations.dm b/code/__DEFINES/traits/declarations.dm index ac2b418b55fc80c..9d27db4737d740d 100644 --- a/code/__DEFINES/traits/declarations.dm +++ b/code/__DEFINES/traits/declarations.dm @@ -509,6 +509,8 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai /// Is the mob standing on an elevated surface? This prevents them from dropping down if not elevated first. #define TRAIT_ON_ELEVATED_SURFACE "on_elevated_surface" +/// Does the mob ignore elevation? (e.g. xeno larvas on hiding) +#define TRAIT_IGNORE_ELEVATION "ignore_elevation" /// Prevents you from twohanding weapons. #define TRAIT_NO_TWOHANDING "no_twohanding" @@ -668,8 +670,6 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai #define TRAIT_NO_STORAGE_INSERT "no_storage_insert" /// Visible on t-ray scanners if the atom/var/level == 1 #define TRAIT_T_RAY_VISIBLE "t-ray-visible" -/// If this item's been grilled -#define TRAIT_FOOD_GRILLED "food_grilled" /// If this item's been fried #define TRAIT_FOOD_FRIED "food_fried" /// This is a silver slime created item @@ -943,6 +943,9 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai #define STATION_TRAIT_UNNATURAL_ATMOSPHERE "station_trait_unnatural_atmosphere" #define STATION_TRAIT_VENDING_SHORTAGE "station_trait_vending_shortage" +///Deathmatch traits +#define TRAIT_DEATHMATCH_EXPLOSIVE_IMPLANTS "deathmath_explosive_implants" + /// This atom is currently spinning. #define TRAIT_SPINNING "spinning" diff --git a/code/__DEFINES/traits/sources.dm b/code/__DEFINES/traits/sources.dm index dd237bf54b704e3..dcbfab7fe5f1621 100644 --- a/code/__DEFINES/traits/sources.dm +++ b/code/__DEFINES/traits/sources.dm @@ -34,6 +34,8 @@ #define CULT_TRAIT "cult" #define LICH_TRAIT "lich" +#define VENDING_MACHINE_TRAIT "vending_machine" + #define ABSTRACT_ITEM_TRAIT "abstract-item" /// A trait given by any status effect #define STATUS_EFFECT_TRAIT "status-effect" @@ -86,6 +88,8 @@ #define MAFIA_TRAIT "mafia" /// Trait associated with ctf #define CTF_TRAIT "ctf" +/// Trait associated with deathmatch +#define DEATHMATCH_TRAIT "deathmatch" /// Trait associated with highlander #define HIGHLANDER_TRAIT "highlander" /// Trait given from playing pretend with baguettes diff --git a/code/__DEFINES/~skyrat_defines/traits/declarations.dm b/code/__DEFINES/~skyrat_defines/traits/declarations.dm index 15a532cbd28c5cf..ce5958bcc378d70 100644 --- a/code/__DEFINES/~skyrat_defines/traits/declarations.dm +++ b/code/__DEFINES/~skyrat_defines/traits/declarations.dm @@ -57,9 +57,6 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai /// The trait which is applied when a `slick skin` trait haver actually gets wet_stacks #define TRAIT_SLIPPERY "slippery" -/// Under the effect of a numbling agent, such as morphine, for surgery. -#define TRAIT_NUMBED "numbed" - // felinid traits #define TRAIT_FELINE "feline_aspect" diff --git a/code/__HELPERS/atmospherics.dm b/code/__HELPERS/atmospherics.dm index 940418f2ebc70bb..3ac3bfaed569d21 100644 --- a/code/__HELPERS/atmospherics.dm +++ b/code/__HELPERS/atmospherics.dm @@ -199,3 +199,10 @@ GLOBAL_LIST_EMPTY(gas_handbook) if(boundaries && boundaries[1] > 0) return FALSE return TRUE + +/proc/print_gas_mixture(datum/gas_mixture/gas_mixture) + var/message = "TEMPERATURE: [gas_mixture.temperature]K, QUANTITY: [gas_mixture.total_moles()] mols, VOLUME: [gas_mixture.volume]L; " + for(var/key in gas_mixture.gases) + var/list/gaslist = gas_mixture.gases[key] + message += "[gaslist[GAS_META][META_GAS_ID]]=[gaslist[MOLES]] mols;" + return message diff --git a/code/__HELPERS/clients.dm b/code/__HELPERS/clients.dm index 3b61cf1e1c45671..156f9e2b5dcdf0b 100644 --- a/code/__HELPERS/clients.dm +++ b/code/__HELPERS/clients.dm @@ -10,3 +10,9 @@ if (ch < 48 || ch > 57) //0-9 return FALSE return TRUE + +/// Proc that just logs whenever an uninitialized client tries to do something before they have fully gone through New(). +/// Intended to be used in conjunction with the `VALIDATE_CLIENT_INITIALIZATION()` macro, but can be dropped anywhere when we look at the `fully_created` var on /client. +/proc/unvalidated_client_error(client/target) + to_chat(target, span_warning("You are not fully initialized yet! Please wait a moment.")) + log_access("Client [key_name(target)] attempted to execute a verb before being fully initialized.") diff --git a/code/__HELPERS/cmp.dm b/code/__HELPERS/cmp.dm index 0210c44ee57baad..f9957f4c7393e80 100644 --- a/code/__HELPERS/cmp.dm +++ b/code/__HELPERS/cmp.dm @@ -192,3 +192,6 @@ /// Orders mobs by health /proc/cmp_mob_health(mob/living/mob_a, mob/living/mob_b) return mob_b.health - mob_a.health + +/proc/cmp_deathmatch_mods(datum/deathmatch_modifier/a, datum/deathmatch_modifier/b) + return sorttext(b.name, a.name) diff --git a/code/__HELPERS/global_lists.dm b/code/__HELPERS/global_lists.dm index 07fd4e2d560ceff..651336fd12e67d5 100644 --- a/code/__HELPERS/global_lists.dm +++ b/code/__HELPERS/global_lists.dm @@ -285,3 +285,10 @@ GLOBAL_LIST_INIT(WALLITEMS_EXTERIOR, typecacheof(list( /obj/structure/camera_assembly, /obj/structure/light_construct, ))) + +/// A static typecache of all the money-based items that can be actively used as currency. +GLOBAL_LIST_INIT(allowed_money, typecacheof(list( + /obj/item/coin, + /obj/item/holochip, + /obj/item/stack/spacecash, +))) diff --git a/code/__HELPERS/logging/atmos.dm b/code/__HELPERS/logging/atmos.dm index 0fcded5c7ab0330..644c9e6562576a9 100644 --- a/code/__HELPERS/logging/atmos.dm +++ b/code/__HELPERS/logging/atmos.dm @@ -1,8 +1,48 @@ /// Logs the contents of the gasmix to the game log, prefixed by text -/proc/log_atmos(text, datum/gas_mixture/mix) - var/message = text - message += "TEMP=[mix.temperature], MOL=[mix.total_moles()], VOL=[mix.volume] " - for(var/key in mix.gases) - var/list/gaslist = mix.gases[key] - message += "[gaslist[GAS_META][META_GAS_ID]]=[gaslist[MOLES]];" - log_game(message) +/proc/log_atmos(text, datum/gas_mixture/gas_mixture) + var/message = "[text]\"[print_gas_mixture(gas_mixture)]\"" + //Cache commonly accessed information. + var/list/gases = gas_mixture.gases //List of gas datum paths that are associated with a list of information related to the gases. + var/heat_capacity = gas_mixture.heat_capacity() + var/temperature = gas_mixture.return_temperature() + var/thermal_energy = temperature * heat_capacity + var/volume = gas_mixture.return_volume() + var/pressure = gas_mixture.return_pressure() + var/total_moles = gas_mixture.total_moles() + ///The total value of the gas mixture in credits. + var/total_value = 0 + var/list/specific_gas_data = list() + + //Gas specific information assigned to each gas. + for(var/datum/gas/gas_path as anything in gases) + var/list/gas = gases[gas_path] + var/moles = gas[MOLES] + var/composition = moles / total_moles + var/energy = temperature * moles * gas[GAS_META][META_GAS_SPECIFIC_HEAT] + var/value = initial(gas_path.base_value) * moles + total_value += value + specific_gas_data[gas[GAS_META][META_GAS_NAME]] = list( + "moles" = moles, + "composition" = composition, + "molar concentration" = moles / volume, + "partial pressure" = composition * pressure, + "energy" = energy, + "energy density" = energy / volume, + "value" = value, + ) + + log_game( + message, + data = list( + "total moles" = total_moles, + "volume" = volume, + "molar density" = total_moles / volume, + "temperature" = temperature, + "pressure" = pressure, + "heat capacity" = heat_capacity, + "energy" = thermal_energy, + "energy density" = thermal_energy / volume, + "value" = total_value, + "gases" = specific_gas_data, + ) + ) diff --git a/code/__HELPERS/logging/debug.dm b/code/__HELPERS/logging/debug.dm index c4ed2f1086f0196..ad5670d2d119ee3 100644 --- a/code/__HELPERS/logging/debug.dm +++ b/code/__HELPERS/logging/debug.dm @@ -23,6 +23,9 @@ /proc/log_mapping(text, skip_world_log) #ifdef UNIT_TESTS GLOB.unit_test_mapping_logs += text +#endif +#ifdef MAP_TEST + message_admins("Mapping: [text]") #endif logger.Log(LOG_CATEGORY_DEBUG_MAPPING, text) if(skip_world_log) diff --git a/code/__HELPERS/maths.dm b/code/__HELPERS/maths.dm index c28357eb478b91a..ead9d54ebaa5f75 100644 --- a/code/__HELPERS/maths.dm +++ b/code/__HELPERS/maths.dm @@ -131,23 +131,23 @@ * Returns: [SI_COEFFICIENT = si unit coefficient, SI_UNIT = prefixed si unit.] */ /proc/siunit_isolated(value, unit, maxdecimals=1) - var/static/list/prefixes = list("f","p","n","μ","m","","k","M","G","T","P") + var/static/list/prefixes = list("q","r","y","z","a","f","p","n","μ","m","","k","M","G","T","P","E","Z","Y","R","Q") // We don't have prefixes beyond this point // and this also captures value = 0 which you can't compute the logarithm for // and also byond numbers are floats and doesn't have much precision beyond this point anyway - if(abs(value) <= 1e-18) + if(abs(value) < 1e-30) . = list(SI_COEFFICIENT = 0, SI_UNIT = " [unit]") return - var/exponent = clamp(log(10, abs(value)), -15, 15) // Calculate the exponent and clamp it so we don't go outside the prefix list bounds + var/exponent = clamp(log(10, abs(value)), -30, 30) // Calculate the exponent and clamp it so we don't go outside the prefix list bounds var/divider = 10 ** (round(exponent / 3) * 3) // Rounds the exponent to nearest SI unit and power it back to the full form var/coefficient = round(value / divider, 10 ** -maxdecimals) // Calculate the coefficient and round it to desired decimals - var/prefix_index = round(exponent / 3) + 6 // Calculate the index in the prefixes list for this exponent + var/prefix_index = round(exponent / 3) + 11 // Calculate the index in the prefixes list for this exponent // An edge case which happens if we round 999.9 to 0 decimals for example, which gets rounded to 1000 // In that case, we manually swap up to the next prefix if there is one available - if(coefficient >= 1000 && prefix_index < 11) + if(coefficient >= 1000 && prefix_index < 21) coefficient /= 1e3 prefix_index++ diff --git a/code/__HELPERS/paths/path.dm b/code/__HELPERS/paths/path.dm index 28ef66aa45e6a69..61e50601e78485b 100644 --- a/code/__HELPERS/paths/path.dm +++ b/code/__HELPERS/paths/path.dm @@ -281,7 +281,7 @@ /// Are we being thrown? var/thrown = FALSE /// Are we anchored - var/anchored = FLASH_LIGHT_POWER + var/anchored = FALSE /// Are we a ghost? (they have effectively unique pathfinding) var/is_observer = FALSE diff --git a/code/__byond_version_compat.dm b/code/__byond_version_compat.dm index 5eb4bda14e78406..87d4348580e29d4 100644 --- a/code/__byond_version_compat.dm +++ b/code/__byond_version_compat.dm @@ -2,11 +2,11 @@ //Update this whenever you need to take advantage of more recent byond features #define MIN_COMPILER_VERSION 515 -#define MIN_COMPILER_BUILD 1621 +#define MIN_COMPILER_BUILD 1627 #if (DM_VERSION < MIN_COMPILER_VERSION || DM_BUILD < MIN_COMPILER_BUILD) && !defined(SPACEMAN_DMM) //Don't forget to update this part #error Your version of BYOND is too out-of-date to compile this project. Go to https://secure.byond.com/download and update. -#error You need version 515.1621 or higher +#error You need version 515.1627 or higher #endif // Keep savefile compatibilty at minimum supported level diff --git a/code/_compile_options.dm b/code/_compile_options.dm index 2a4854c37b858de..8768a1e36222b06 100644 --- a/code/_compile_options.dm +++ b/code/_compile_options.dm @@ -142,3 +142,12 @@ #warn In order to build, run BUILD.bat in the root directory. #warn Consider switching to VSCode editor instead, where you can press Ctrl+Shift+B to build. #endif + +/// Runs the game in "map test mode" +/// Map test mode prevents common annoyances, such as rats from spawning and random light fixture breakage, +/// so mappers can test important facets of their map (working powernet, atmos, good light coverage) without these interfering. +// #define MAP_TEST + +#ifdef MAP_TEST +#warn Compiling in MAP_TEST mode. Certain game mechanics will be disabled. +#endif diff --git a/code/_globalvars/bitfields.dm b/code/_globalvars/bitfields.dm index 7c563a2bb056fa3..87e093ea139520b 100644 --- a/code/_globalvars/bitfields.dm +++ b/code/_globalvars/bitfields.dm @@ -317,7 +317,8 @@ DEFINE_BITFIELD(resistance_flags, list( "UNACIDABLE" = UNACIDABLE, "ACID_PROOF" = ACID_PROOF, "INDESTRUCTIBLE" = INDESTRUCTIBLE, - "FREEZE_PROOF" = FREEZE_PROOF + "FREEZE_PROOF" = FREEZE_PROOF, + "SHUTTLE_CRUSH_PROOF" = SHUTTLE_CRUSH_PROOF )) DEFINE_BITFIELD(sight, list( diff --git a/code/_globalvars/lists/mapping.dm b/code/_globalvars/lists/mapping.dm index b77942bad87195d..8719f45f18fc039 100644 --- a/code/_globalvars/lists/mapping.dm +++ b/code/_globalvars/lists/mapping.dm @@ -151,3 +151,26 @@ GLOBAL_LIST_INIT(megafauna_spawn_list, list( /mob/living/simple_animal/hostile/megafauna/colossus = 2, /mob/living/simple_animal/hostile/megafauna/dragon = 4, )) + +/// List of how many minerals spawned based on proximity to an ore vent. +GLOBAL_LIST_INIT(post_ore_random, list( + "[ORE_WALL_FAR]" = 0, + "[ORE_WALL_LOW]" = 0, + "[ORE_WALL_MEDIUM]" = 0, + "[ORE_WALL_HIGH]" = 0, + "[ORE_WALL_VERY_HIGH]" = 0, +)) +/// List of how many minerals spawned randomly off of mining Z-levels, and at what quantity. +GLOBAL_LIST_INIT(post_ore_manual, list( + "[ORE_WALL_FAR]" = 0, + "[ORE_WALL_LOW]" = 0, + "[ORE_WALL_MEDIUM]" = 0, + "[ORE_WALL_HIGH]" = 0, + "[ORE_WALL_VERY_HIGH]" = 0, +)) +/// List of how many ore vents spawned, and of what size. +GLOBAL_LIST_INIT(ore_vent_sizes, list( + LARGE_VENT_TYPE = 0, + MEDIUM_VENT_TYPE = 0, + SMALL_VENT_TYPE = 0, +)) diff --git a/code/_globalvars/traits/_traits.dm b/code/_globalvars/traits/_traits.dm index 224ffbe6a7b9bcd..3d02262b7f447df 100644 --- a/code/_globalvars/traits/_traits.dm +++ b/code/_globalvars/traits/_traits.dm @@ -18,7 +18,6 @@ GLOBAL_LIST_INIT(traits_by_type, list( "TRAIT_DRYABLE" = TRAIT_DRYABLE, "TRAIT_FOOD_CHEF_MADE" = TRAIT_FOOD_CHEF_MADE, "TRAIT_FOOD_FRIED" = TRAIT_FOOD_FRIED, - "TRAIT_FOOD_GRILLED" = TRAIT_FOOD_GRILLED, "TRAIT_FOOD_SILVER" = TRAIT_FOOD_SILVER, "TRAIT_KEEP_TOGETHER" = TRAIT_KEEP_TOGETHER, "TRAIT_LIGHTING_DEBUGGED" = TRAIT_LIGHTING_DEBUGGED, @@ -99,6 +98,9 @@ GLOBAL_LIST_INIT(traits_by_type, list( "STATION_TRAIT_UNNATURAL_ATMOSPHERE" = STATION_TRAIT_UNNATURAL_ATMOSPHERE, "STATION_TRAIT_VENDING_SHORTAGE" = STATION_TRAIT_VENDING_SHORTAGE, ), + /datum/deathmatch_lobby = list( + "TRAIT_DEATHMATCH_EXPLOSIVE_IMPLANTS" = TRAIT_DEATHMATCH_EXPLOSIVE_IMPLANTS, + ), /datum/wound = list( "TRAIT_WOUND_SCANNED" = TRAIT_WOUND_SCANNED, ), @@ -253,6 +255,7 @@ GLOBAL_LIST_INIT(traits_by_type, list( "TRAIT_HULK" = TRAIT_HULK, "TRAIT_HUSK" = TRAIT_HUSK, "TRAIT_ID_APPRAISER" = TRAIT_ID_APPRAISER, + "TRAIT_IGNORE_ELEVATION" = TRAIT_IGNORE_ELEVATION, "TRAIT_IGNOREDAMAGESLOWDOWN" = TRAIT_IGNOREDAMAGESLOWDOWN, "TRAIT_IGNORESLOWDOWN" = TRAIT_IGNORESLOWDOWN, "TRAIT_IGNORING_GRAVITY" = TRAIT_IGNORING_GRAVITY, @@ -636,7 +639,6 @@ GLOBAL_LIST_INIT(traits_by_type, list( "TRAIT_CARRIER" = TRAIT_CARRIER, "TRAIT_NO_HUSK" = TRAIT_NO_HUSK, "TRAIT_NORUNNING" = TRAIT_NORUNNING, - "TRAIT_NUMBED" = TRAIT_NUMBED, "TRAIT_OVERSIZED" = TRAIT_OVERSIZED, "TRAIT_OXYIMMUNE" = TRAIT_OXYIMMUNE, "TRAIT_PERSONALSPACE" = TRAIT_PERSONALSPACE, diff --git a/code/_globalvars/traits/admin_tooling.dm b/code/_globalvars/traits/admin_tooling.dm index 6d25ef36458e558..797cedec6684bc7 100644 --- a/code/_globalvars/traits/admin_tooling.dm +++ b/code/_globalvars/traits/admin_tooling.dm @@ -95,6 +95,7 @@ GLOBAL_LIST_INIT(admin_visible_traits, list( "TRAIT_HIDE_EXTERNAL_ORGANS" = TRAIT_HIDE_EXTERNAL_ORGANS, "TRAIT_HOLY" = TRAIT_HOLY, "TRAIT_HUSK" = TRAIT_HUSK, + "TRAIT_IGNORE_ELEVATION" = TRAIT_IGNORE_ELEVATION, "TRAIT_IGNOREDAMAGESLOWDOWN" = TRAIT_IGNOREDAMAGESLOWDOWN, "TRAIT_IGNORESLOWDOWN" = TRAIT_IGNORESLOWDOWN, "TRAIT_ILLITERATE" = TRAIT_ILLITERATE, @@ -315,7 +316,6 @@ GLOBAL_LIST_INIT(admin_visible_traits, list( "TRAIT_NIFSOFT_HUD_GRANTER" = TRAIT_NIFSOFT_HUD_GRANTER, "TRAIT_NO_HUSK" = TRAIT_NO_HUSK, "TRAIT_NORUNNING" = TRAIT_NORUNNING, - "TRAIT_NUMBED" = TRAIT_NUMBED, "TRAIT_OVERSIZED" = TRAIT_OVERSIZED, "TRAIT_OXYIMMUNE" = TRAIT_OXYIMMUNE, "TRAIT_PERSONALSPACE" = TRAIT_PERSONALSPACE, diff --git a/code/_onclick/hud/action_button.dm b/code/_onclick/hud/action_button.dm index 92defc661016cd3..9d4343c132e9b42 100644 --- a/code/_onclick/hud/action_button.dm +++ b/code/_onclick/hud/action_button.dm @@ -230,7 +230,7 @@ return for(var/datum/action/action as anything in take_from.actions) - if(!action.show_to_observers) + if(!action.show_to_observers || !action.owner_has_control) continue action.GiveAction(src) RegisterSignal(take_from, COMSIG_MOB_GRANTED_ACTION, PROC_REF(on_observing_action_granted)) @@ -251,7 +251,7 @@ /mob/proc/on_observing_action_granted(mob/living/source, datum/action/action) SIGNAL_HANDLER - if(!action.show_to_observers) + if(!action.show_to_observers || !action.owner_has_control) return action.GiveAction(src) diff --git a/code/_onclick/hud/ai.dm b/code/_onclick/hud/ai.dm index 5f687d19642819a..1d26c4916b04b2c 100644 --- a/code/_onclick/hud/ai.dm +++ b/code/_onclick/hud/ai.dm @@ -186,6 +186,11 @@ using.screen_loc = ui_ai_language_menu static_inventory += using +// Z-level floor change + using = new /atom/movable/screen/floor_menu(null, src) + using.screen_loc = ui_ai_floor_menu + static_inventory += using + //AI core using = new /atom/movable/screen/ai/aicore(null, src) using.screen_loc = ui_ai_core diff --git a/code/_onclick/hud/alert.dm b/code/_onclick/hud/alert.dm index 1f5f7588162abe4..935176f39ab5374 100644 --- a/code/_onclick/hud/alert.dm +++ b/code/_onclick/hud/alert.dm @@ -68,8 +68,8 @@ if(client && hud_used) hud_used.reorganize_alerts() if(!no_anim) - thealert.transform = matrix(32, 6, MATRIX_TRANSLATE) - animate(thealert, transform = matrix(), time = 2.5, easing = CUBIC_EASING) + thealert.transform = matrix(32, 0, MATRIX_TRANSLATE) + animate(thealert, transform = matrix(), time = 1 SECONDS, easing = ELASTIC_EASING) if(timeout_override) thealert.timeout = timeout_override if(thealert.timeout) diff --git a/code/_onclick/hud/alien.dm b/code/_onclick/hud/alien.dm index 3c1b1029a3e06dd..c3b91173a45f52a 100644 --- a/code/_onclick/hud/alien.dm +++ b/code/_onclick/hud/alien.dm @@ -63,6 +63,10 @@ using.screen_loc = ui_alien_language_menu static_inventory += using + using = new /atom/movable/screen/floor_menu(null, src) + using.screen_loc = ui_alien_floor_menu + static_inventory += using + using = new /atom/movable/screen/navigate(null, src) using.screen_loc = ui_alien_navigate_menu static_inventory += using @@ -87,7 +91,7 @@ pull_icon.update_appearance() pull_icon.screen_loc = ui_above_movement static_inventory += pull_icon - + rest_icon = new /atom/movable/screen/rest(null, src) rest_icon.icon = ui_style rest_icon.screen_loc = ui_above_intent diff --git a/code/_onclick/hud/alien_larva.dm b/code/_onclick/hud/alien_larva.dm index d9ebb3611b68b38..77d135ce2c66321 100644 --- a/code/_onclick/hud/alien_larva.dm +++ b/code/_onclick/hud/alien_larva.dm @@ -32,6 +32,10 @@ using.screen_loc = ui_alien_language_menu static_inventory += using + using = new /atom/movable/screen/floor_menu(null, src) + using.screen_loc = ui_alien_floor_menu + static_inventory += using + using = new /atom/movable/screen/navigate(null, src) using.screen_loc = ui_alien_navigate_menu static_inventory += using diff --git a/code/_onclick/hud/ghost.dm b/code/_onclick/hud/ghost.dm index 99b04df906871c2..e20c1ede2f6639c 100644 --- a/code/_onclick/hud/ghost.dm +++ b/code/_onclick/hud/ghost.dm @@ -86,6 +86,16 @@ using.icon = ui_style static_inventory += using + using = new /atom/movable/screen/language_menu(null, src) + using.screen_loc = ui_ghost_language_menu + using.icon = ui_style + static_inventory += using + + using = new /atom/movable/screen/floor_menu(null, src) + using.screen_loc = ui_ghost_floor_menu + using.icon = ui_style + static_inventory += using + /datum/hud/ghost/show_hud(version = 0, mob/viewmob) // don't show this HUD if observing; show the HUD of the observee var/mob/dead/observer/O = mymob diff --git a/code/_onclick/hud/human.dm b/code/_onclick/hud/human.dm index 11f186e98773298..51aca42db3a7d6e 100644 --- a/code/_onclick/hud/human.dm +++ b/code/_onclick/hud/human.dm @@ -70,6 +70,10 @@ using.icon = ui_style static_inventory += using + using = new /atom/movable/screen/floor_menu(null, src) + using.icon = ui_style + static_inventory += using + action_intent = new /atom/movable/screen/combattoggle/flashy(null, src) action_intent.icon = ui_style action_intent.screen_loc = ui_combat_toggle diff --git a/code/_onclick/hud/robot.dm b/code/_onclick/hud/robot.dm index fdc03364e3f948a..ae7ac6fee91e702 100644 --- a/code/_onclick/hud/robot.dm +++ b/code/_onclick/hud/robot.dm @@ -77,6 +77,7 @@ var/mob/living/silicon/robot/robit = mymob var/atom/movable/screen/using +// Language using = new/atom/movable/screen/language_menu(null, src) using.screen_loc = ui_borg_language_menu static_inventory += using @@ -86,6 +87,11 @@ using.screen_loc = ui_borg_navigate_menu static_inventory += using +// Z-level floor change + using = new /atom/movable/screen/floor_menu(null, src) + using.screen_loc = ui_borg_floor_menu + static_inventory += using + //Radio using = new /atom/movable/screen/robot/radio(null, src) using.screen_loc = ui_borg_radio diff --git a/code/_onclick/hud/screen_objects.dm b/code/_onclick/hud/screen_objects.dm index e812e5b2b5d8872..ab4db30f042a00c 100644 --- a/code/_onclick/hud/screen_objects.dm +++ b/code/_onclick/hud/screen_objects.dm @@ -127,6 +127,33 @@ /atom/movable/screen/language_menu/Click() usr.get_language_holder().open_language_menu(usr) +/atom/movable/screen/floor_menu + name = "change floor" + icon = 'icons/hud/screen_midnight.dmi' + icon_state = "floor_change" + screen_loc = ui_floor_menu + +/atom/movable/screen/floor_menu/Initialize(mapload) + . = ..() + register_context() + +/atom/movable/screen/floor_menu/add_context(atom/source, list/context, obj/item/held_item, mob/user) + . = ..() + + context[SCREENTIP_CONTEXT_LMB] = "Go up a floor" + context[SCREENTIP_CONTEXT_RMB] = "Go down a floor" + return CONTEXTUAL_SCREENTIP_SET + +/atom/movable/screen/floor_menu/Click(location,control,params) + var/list/modifiers = params2list(params) + + if(LAZYACCESS(modifiers, RIGHT_CLICK) || LAZYACCESS(modifiers, ALT_CLICK)) + usr.down() + return + + usr.up() + return + /atom/movable/screen/inventory /// The identifier for the slot. It has nothing to do with ID cards. var/slot_id diff --git a/code/_onclick/item_attack.dm b/code/_onclick/item_attack.dm index 174aac2fc620e4b..a3f886e656f2b78 100644 --- a/code/_onclick/item_attack.dm +++ b/code/_onclick/item_attack.dm @@ -264,6 +264,7 @@ user.changeNext_move(attack_speed) user.do_attack_animation(attacked_atom) attacked_atom.attacked_by(src, user) + SEND_SIGNAL(src, COMSIG_ITEM_POST_ATTACK_ATOM, attacked_atom, user) /// Called from [/obj/item/proc/attack_atom] and [/obj/item/proc/attack] if the attack succeeds /atom/proc/attacked_by(obj/item/attacking_item, mob/living/user) diff --git a/code/controllers/subsystem/dbcore.dm b/code/controllers/subsystem/dbcore.dm index 15484fb9cc6100e..0e8e3dfd90ba7fa 100644 --- a/code/controllers/subsystem/dbcore.dm +++ b/code/controllers/subsystem/dbcore.dm @@ -1,3 +1,4 @@ +#define SHUTDOWN_QUERY_TIMELIMIT (1 MINUTES) SUBSYSTEM_DEF(dbcore) name = "Database" flags = SS_TICKER @@ -6,12 +7,17 @@ SUBSYSTEM_DEF(dbcore) init_order = INIT_ORDER_DBCORE priority = FIRE_PRIORITY_DATABASE - var/failed_connection_timeout = 0 - var/schema_mismatch = 0 var/db_minor = 0 var/db_major = 0 + /// Number of failed connection attempts this try. Resets after the timeout or successful connection var/failed_connections = 0 + /// Max number of consecutive failures before a timeout (here and not a define so it can be vv'ed mid round if needed) + var/max_connection_failures = 5 + /// world.time that connection attempts can resume + var/failed_connection_timeout = 0 + /// Total number of times connections have had to be timed out. + var/failed_connection_timeout_count = 0 var/last_error @@ -174,23 +180,32 @@ SUBSYSTEM_DEF(dbcore) /datum/controller/subsystem/dbcore/Shutdown() shutting_down = TRUE - to_chat(world, span_boldannounce("Clearing DB queries standby:[length(queries_standby)] active: [length(queries_active)] all: [length(all_queries)]")) + var/msg = "Clearing DB queries standby:[length(queries_standby)] active: [length(queries_active)] all: [length(all_queries)]" + to_chat(world, span_boldannounce(msg)) + log_world(msg) //This is as close as we can get to the true round end before Disconnect() without changing where it's called, defeating the reason this is a subsystem + var/endtime = REALTIMEOFDAY + SHUTDOWN_QUERY_TIMELIMIT if(SSdbcore.Connect()) - //Execute all waiting queries + //Take over control of all active queries + var/queries_to_check = queries_active.Copy() + queries_active.Cut() + + //Start all waiting queries for(var/datum/db_query/query in queries_standby) - run_query_sync(query) + run_query(query) + queries_to_check += query queries_standby -= query - for(var/datum/db_query/query in queries_active) - //Finish any remaining active qeries - UNTIL(query.process()) - queries_active -= query + + //wait for them all to finish + for(var/datum/db_query/query in queries_to_check) + UNTIL(query.process() || REALTIMEOFDAY > endtime) // SKYRAT EDIT START - SQL-based logging for(var/table in queued_log_entries_by_table) MassInsert(table, rows = queued_log_entries_by_table[table], duplicate_key = FALSE, ignore_errors = FALSE, warn = FALSE, async = TRUE, special_columns = null) // SKYRAT EDIT END + //log shutdown to the db var/datum/db_query/query_round_shutdown = SSdbcore.NewQuery( "UPDATE [format_table_name("round")] SET shutdown_datetime = Now(), end_state = :end_state WHERE id = :round_id", list("end_state" = SSticker.end_state, "round_id" = GLOB.round_id), @@ -199,7 +214,9 @@ SUBSYSTEM_DEF(dbcore) query_round_shutdown.Execute(FALSE) qdel(query_round_shutdown) - to_chat(world, span_boldannounce("Done clearing DB queries standby:[length(queries_standby)] active: [length(queries_active)] all: [length(all_queries)]")) + msg = "Done clearing DB queries standby:[length(queries_standby)] active: [length(queries_active)] all: [length(all_queries)]" + to_chat(world, span_boldannounce(msg)) + log_world(msg) if(IsConnected()) Disconnect() stop_db_daemon() @@ -236,11 +253,15 @@ SUBSYSTEM_DEF(dbcore) if(IsConnected()) return TRUE - if(failed_connection_timeout <= world.time) //it's been more than 5 seconds since we failed to connect, reset the counter + if(connection) + Disconnect() //clear the current connection handle so isconnected() calls stop invoking rustg + connection = null //make sure its cleared even if runtimes happened + + if(failed_connection_timeout <= world.time) //it's been long enough since we failed to connect, reset the counter failed_connections = 0 + failed_connection_timeout = 0 - if(failed_connections > 5) //If it failed to establish a connection more than 5 times in a row, don't bother attempting to connect for 5 seconds. - failed_connection_timeout = world.time + 50 + if(failed_connection_timeout > 0) return FALSE if(!CONFIG_GET(flag/sql_enabled)) @@ -276,6 +297,11 @@ SUBSYSTEM_DEF(dbcore) last_error = result["data"] log_sql("Connect() failed | [last_error]") ++failed_connections + //If it failed to establish a connection more than 5 times in a row, don't bother attempting to connect for a time. + if(failed_connections > max_connection_failures) + failed_connection_timeout_count++ + //basic exponential backoff algorithm + failed_connection_timeout = world.time + ((2 ** failed_connection_timeout_count) SECONDS) /datum/controller/subsystem/dbcore/proc/CheckSchemaVersion() if(CONFIG_GET(flag/sql_enabled)) @@ -655,3 +681,4 @@ Ignore_errors instructes mysql to continue inserting rows if some of them have e /datum/db_query/proc/Close() rows = null item = null +#undef SHUTDOWN_QUERY_TIMELIMIT diff --git a/code/controllers/subsystem/dynamic/dynamic.dm b/code/controllers/subsystem/dynamic/dynamic.dm index 8c593113e0b08cd..e094e199476070c 100644 --- a/code/controllers/subsystem/dynamic/dynamic.dm +++ b/code/controllers/subsystem/dynamic/dynamic.dm @@ -359,6 +359,7 @@ SUBSYSTEM_DEF(dynamic) . += "
Additional Notes:

" + footnote_pile +#ifndef MAP_TEST print_command_report(., "[command_name()] Status Summary", announce=FALSE) if(greenshift) priority_announce("Thanks to the tireless efforts of our security and intelligence divisions, there are currently no credible threats to [station_name()]. All station construction projects have been authorized. Have a secure shift!", "Security Report", SSstation.announcer.get_rand_report_sound(), color_override = "green") @@ -366,6 +367,7 @@ SUBSYSTEM_DEF(dynamic) if(SSsecurity_level.get_current_level_as_number() < SEC_LEVEL_BLUE) SSsecurity_level.set_level(SEC_LEVEL_BLUE, announce = FALSE) priority_announce("[SSsecurity_level.current_security_level.elevating_to_announcement]\n\nA summary has been copied and printed to all communications consoles.", "Security level elevated.", ANNOUNCER_INTERCEPT, color_override = SSsecurity_level.current_security_level.announcement_color) +#endif return . diff --git a/code/controllers/subsystem/events.dm b/code/controllers/subsystem/events.dm index 98f847e4be6ae35..241622509afafe1 100644 --- a/code/controllers/subsystem/events.dm +++ b/code/controllers/subsystem/events.dm @@ -52,7 +52,11 @@ SUBSYSTEM_DEF(events) //checks if we should select a random event yet, and reschedules if necessary /datum/controller/subsystem/events/proc/checkEvent() if(scheduled <= world.time) +#ifdef MAP_TEST + message_admins("Random event skipped (Game is compiled in MAP_TEST mode)") +#else spawnEvent() +#endif reschedule() //decides which world.time we should select another random event at. diff --git a/code/controllers/subsystem/explosions.dm b/code/controllers/subsystem/explosions.dm index 2021964609afdb1..5b3320999f83ef3 100644 --- a/code/controllers/subsystem/explosions.dm +++ b/code/controllers/subsystem/explosions.dm @@ -1,4 +1,8 @@ #define EXPLOSION_THROW_SPEED 4 +#define EXPLOSION_BLOCK_LIGHT 2.5 +#define EXPLOSION_BLOCK_HEAVY 1.5 +#define EXPLOSION_BLOCK_DEV 1 + GLOBAL_LIST_EMPTY(explosions) SUBSYSTEM_DEF(explosions) @@ -127,25 +131,26 @@ SUBSYSTEM_DEF(explosions) var/our_x = explode.x var/our_y = explode.y var/dist = CHEAP_HYPOTENUSE(our_x, our_y, x0, y0) + var/block = 0 if(newmode == "Yes") if(explode != epicenter) var/our_block = cached_exp_block[get_step_towards(explode, epicenter)] - dist += our_block + block += our_block cached_exp_block[explode] = our_block + explode.explosive_resistance else cached_exp_block[explode] = explode.explosive_resistance dist = round(dist, 0.01) - if(dist < dev) + if(dist + (block * EXPLOSION_BLOCK_DEV) < dev) explode.color = "red" explode.maptext = MAPTEXT("[dist]") - else if (dist < heavy) + else if (dist + (block * EXPLOSION_BLOCK_HEAVY) < heavy) explode.color = "yellow" - explode.maptext = MAPTEXT("[dist]") - else if (dist < light) + explode.maptext = MAPTEXT("[dist + (block * EXPLOSION_BLOCK_HEAVY)]") + else if (dist + (block * EXPLOSION_BLOCK_LIGHT) < light) explode.color = "blue" - explode.maptext = MAPTEXT("[dist]") + explode.maptext = MAPTEXT("[dist + (block * EXPLOSION_BLOCK_LIGHT)]") else continue @@ -397,26 +402,26 @@ SUBSYSTEM_DEF(explosions) var/our_x = explode.x var/our_y = explode.y var/dist = CHEAP_HYPOTENUSE(our_x, our_y, x0, y0) - + var/block = 0 // Using this pattern, block will flow out from blocking turfs, essentially caching the recursion // This is safe because if get_step_towards is ever anything but caridnally off, it'll do a diagonal move // So we always sample from a "loop" closer - // It's kind of behaviorly unimpressive that that's a problem for the future + // It's kind of behaviorly unimpressive but that's a problem for the future if(reactionary) if(explode == epicenter) cached_exp_block[explode] = explode.explosive_resistance else var/our_block = cached_exp_block[get_step_towards(explode, epicenter)] - dist += our_block + block += our_block cached_exp_block[explode] = our_block + explode.explosive_resistance var/severity = EXPLODE_NONE - if(dist < devastation_range) + if(dist + (block * EXPLOSION_BLOCK_DEV) < devastation_range) severity = EXPLODE_DEVASTATE - else if(dist < heavy_impact_range) + else if(dist + (block * EXPLOSION_BLOCK_HEAVY) < heavy_impact_range) severity = EXPLODE_HEAVY - else if(dist < light_impact_range) + else if(dist + (block * EXPLOSION_BLOCK_LIGHT) < light_impact_range) severity = EXPLODE_LIGHT if(explode == epicenter) // Ensures explosives detonating from bags trigger other explosives in that bag @@ -730,3 +735,6 @@ SUBSYSTEM_DEF(explosions) currentpart = SSEXPLOSIONS_TURFS #undef EXPLOSION_THROW_SPEED +#undef EXPLOSION_BLOCK_LIGHT +#undef EXPLOSION_BLOCK_HEAVY +#undef EXPLOSION_BLOCK_DEV diff --git a/code/controllers/subsystem/minor_mapping.dm b/code/controllers/subsystem/minor_mapping.dm index 8516ed98ea9497f..1141e53acfc67a4 100644 --- a/code/controllers/subsystem/minor_mapping.dm +++ b/code/controllers/subsystem/minor_mapping.dm @@ -7,13 +7,15 @@ SUBSYSTEM_DEF(minor_mapping) flags = SS_NO_FIRE /datum/controller/subsystem/minor_mapping/Initialize() - #ifdef UNIT_TESTS // This whole subsystem just introduces a lot of odd confounding variables into unit test situations, so let's just not bother with doing an initialize here. +// This whole subsystem just introduces a lot of odd confounding variables into unit test situations, +// so let's just not bother with doing an initialize here. +#if defined(MAP_TEST) || defined(UNIT_TESTS) return SS_INIT_NO_NEED - #else +#else trigger_migration(CONFIG_GET(number/mice_roundstart)) place_satchels(satchel_amount = 10) //SKYRAT EDIT CHANGE - ORIGINAL : place_satchels(satchel_amount = 2) return SS_INIT_SUCCESS - #endif // the mice are easily the bigger problem, but let's just avoid anything that could cause some bullshit. +#endif /// Spawns some critters on exposed wires, usually but not always mice /datum/controller/subsystem/minor_mapping/proc/trigger_migration(to_spawn=10) diff --git a/code/controllers/subsystem/ore_generation.dm b/code/controllers/subsystem/ore_generation.dm index ca8aa09d6111c37..e36dd577794e123 100644 --- a/code/controllers/subsystem/ore_generation.dm +++ b/code/controllers/subsystem/ore_generation.dm @@ -20,27 +20,6 @@ SUBSYSTEM_DEF(ore_generation) var/list/ore_vent_minerals = list() /// A tracker of how many of each ore vent size we have in the game. Useful for tracking purposes. - var/list/ore_vent_sizes = list( - LARGE_VENT_TYPE = 0, - MEDIUM_VENT_TYPE = 0, - SMALL_VENT_TYPE = 0, - ) - /// Ores spawned by proximity to an ore vent. Useful for logging purposes. - var/list/post_ore_random = list( - "1" = 0, - "2" = 0, - "3" = 0, - "4" = 0, - "5" = 0, - ) - /// Ores spawned randomly on the map without proximity to an ore vent. Useful for logging purposes. - var/list/post_ore_manual = list( - "1" = 0, - "2" = 0, - "3" = 0, - "4" = 0, - "5" = 0, - ) /datum/controller/subsystem/ore_generation/Initialize() //Basically, we're going to round robin through the list of ore vents and assign a mineral to them until complete. @@ -56,8 +35,43 @@ SUBSYSTEM_DEF(ore_generation) else stallbreaker++ if(stallbreaker >= length(possible_vents)) - return SS_INIT_SUCCESS //We've done all we can here. + break //We've done all we can here. break inner loop continue + if(stallbreaker >= length(possible_vents)) + break //We've done all we can here. break outer loop + + /// Handles roundstart logging + logger.Log( + LOG_CATEGORY_CAVE_GENERATION, + "Ore Generation spawned the following ores based on vent proximity", + list( + "[ORE_WALL_FAR]" = GLOB.post_ore_random["[ORE_WALL_FAR]"], + "[ORE_WALL_LOW]" = GLOB.post_ore_random["[ORE_WALL_LOW]"], + "[ORE_WALL_MEDIUM]" = GLOB.post_ore_random["[ORE_WALL_MEDIUM]"], + "[ORE_WALL_HIGH]" = GLOB.post_ore_random["[ORE_WALL_HIGH]"], + "[ORE_WALL_VERY_HIGH]" = GLOB.post_ore_random["[ORE_WALL_VERY_HIGH]"], + ), + ) + logger.Log( + LOG_CATEGORY_CAVE_GENERATION, + "Ore Generation spawned the following ores randomly", + list( + "[ORE_WALL_FAR]" = GLOB.post_ore_manual["[ORE_WALL_FAR]"], + "[ORE_WALL_LOW]" = GLOB.post_ore_manual["[ORE_WALL_LOW]"], + "[ORE_WALL_MEDIUM]" = GLOB.post_ore_manual["[ORE_WALL_MEDIUM]"], + "[ORE_WALL_HIGH]" = GLOB.post_ore_manual["[ORE_WALL_HIGH]"], + "[ORE_WALL_VERY_HIGH]" = GLOB.post_ore_manual["[ORE_WALL_VERY_HIGH]"], + ), + ) + logger.Log( + LOG_CATEGORY_CAVE_GENERATION, + "Ore Generation spawned the following vent sizes", + list( + "large" = LAZYACCESS(GLOB.ore_vent_sizes, LARGE_VENT_TYPE), + "medium" = LAZYACCESS(GLOB.ore_vent_sizes, MEDIUM_VENT_TYPE), + "small" = LAZYACCESS(GLOB.ore_vent_sizes, SMALL_VENT_TYPE), + ), + ) return SS_INIT_SUCCESS /datum/controller/subsystem/ore_generation/fire(resumed) diff --git a/code/controllers/subsystem/persistence/_persistence.dm b/code/controllers/subsystem/persistence/_persistence.dm index e42247c71a9961b..eae40a733b0ec04 100644 --- a/code/controllers/subsystem/persistence/_persistence.dm +++ b/code/controllers/subsystem/persistence/_persistence.dm @@ -37,6 +37,14 @@ SUBSYSTEM_DEF(persistence) /// Will be null'd once the persistence system initializes, and never read from again. var/list/obj/item/storage/photo_album/queued_photo_albums + /// A json_database to data/piggy banks.json + /// Schema is persistence_id => array of coins, space cash and holochips. + var/datum/json_database/piggy_banks_database + /// List of persistene ids which piggy banks. + var/list/queued_broken_piggy_ids + + var/list/broken_piggy_banks + var/rounds_since_engine_exploded = 0 var/delam_highscore = 0 var/tram_hits_this_round = 0 diff --git a/code/controllers/subsystem/persistence/piggy_banks.dm b/code/controllers/subsystem/persistence/piggy_banks.dm new file mode 100644 index 000000000000000..240fd98ab0c9e37 --- /dev/null +++ b/code/controllers/subsystem/persistence/piggy_banks.dm @@ -0,0 +1,56 @@ +///This proc is used to initialize holochips, cash and coins inside our persistent piggy bank. +/datum/controller/subsystem/persistence/proc/load_piggy_bank(obj/item/piggy_bank/piggy) + if(isnull(piggy_banks_database)) + piggy_banks_database = new("data/piggy_banks.json") + + var/list/data = piggy_banks_database.get_key(piggy.persistence_id) + if(isnull(data)) + return + var/total_value = 0 + for(var/iteration in 1 to length(data)) + var/money_path = text2path(data[iteration]) + if(!money_path) //For a reason or another, it was removed. + continue + var/obj/item/spawned + if(ispath(money_path, /obj/item/holochip)) + //We want to safely access the assoc of this position and not that of last key that happened to match this one. + var/list/key_and_assoc = data.Copy(iteration, iteration + 1) + var/amount = key_and_assoc["[money_path]"] + spawned = new money_path (piggy, amount) + //the operations are identical to those of chips, but they're different items, so I'll keep them separated. + else if(ispath(money_path, /obj/item/stack/spacecash)) + var/list/key_and_assoc = data.Copy(iteration, iteration + 1) + var/amount = key_and_assoc["[money_path]"] + spawned = new money_path (piggy, amount) + else if(ispath(money_path, /obj/item/coin)) + spawned = new money_path (piggy) + else + stack_trace("Unsupported path found in the data of a persistent piggy bank. item: [money_path], id:[piggy.persistence_id]") + continue + total_value += spawned.get_item_credit_value() + if(total_value >= piggy.maximum_value) + break + +///This proc is used to save money stored inside our persistent the piggy bank for the next time it's loaded. +/datum/controller/subsystem/persistence/proc/save_piggy_bank(obj/item/piggy_bank/piggy) + if(isnull(piggy_banks_database)) + return + + if(queued_broken_piggy_ids) + for(var/broken_id in queued_broken_piggy_ids) + piggy_banks_database.remove(broken_id) + queued_broken_piggy_ids = null + + var/list/data = list() + for(var/obj/item/item as anything in piggy.contents) + var/piggy_value = 1 + if(istype(item, /obj/item/holochip)) + var/obj/item/holochip/chip = item + piggy_value = chip.credits + else if(istype(item, /obj/item/stack/spacecash)) + var/obj/item/stack/spacecash/cash = item + piggy_value = cash.amount + else if(!istype(item, /obj/item/coin)) + continue + data += list("[item.type]" = piggy_value) + piggy_banks_database.set_key(piggy.persistence_id, data) diff --git a/code/controllers/subsystem/processing/instruments.dm b/code/controllers/subsystem/processing/instruments.dm index acee4480b946f0f..1cfbb144e5f8af0 100644 --- a/code/controllers/subsystem/processing/instruments.dm +++ b/code/controllers/subsystem/processing/instruments.dm @@ -20,7 +20,10 @@ PROCESSING_SUBSYSTEM_DEF(instruments) var/static/current_instrument_channels = 0 /// Single cached list for synthesizer instrument ids, so you don't have to have a new list with every synthesizer. var/static/list/synthesizer_instrument_ids - var/static/list/note_sustain_modes = list("Linear" = SUSTAIN_LINEAR, "Exponential" = SUSTAIN_EXPONENTIAL) + var/static/list/note_sustain_modes = list( + SUSTAIN_LINEAR, + SUSTAIN_EXPONENTIAL, + ) /datum/controller/subsystem/processing/instruments/Initialize() initialize_instrument_data() diff --git a/code/controllers/subsystem/processing/station.dm b/code/controllers/subsystem/processing/station.dm index cae0f4105867c83..d05a0b5d30f7bfb 100644 --- a/code/controllers/subsystem/processing/station.dm +++ b/code/controllers/subsystem/processing/station.dm @@ -118,6 +118,12 @@ PROCESSING_SUBSYSTEM_DEF(station) var/neutral_trait_budget = text2num(pick_weight(CONFIG_GET(keyed_list/neutral_station_traits))) var/negative_trait_budget = text2num(pick_weight(CONFIG_GET(keyed_list/negative_station_traits))) +#ifdef MAP_TEST + positive_trait_budget = 0 + neutral_trait_budget = 0 + negative_trait_budget = 0 +#endif + pick_traits(STATION_TRAIT_POSITIVE, positive_trait_budget) pick_traits(STATION_TRAIT_NEUTRAL, neutral_trait_budget) pick_traits(STATION_TRAIT_NEGATIVE, negative_trait_budget) diff --git a/code/controllers/subsystem/queuelinks.dm b/code/controllers/subsystem/queuelinks.dm index 6a3b8288821624b..a6d56cf622ec9ca 100644 --- a/code/controllers/subsystem/queuelinks.dm +++ b/code/controllers/subsystem/queuelinks.dm @@ -18,16 +18,30 @@ SUBSYSTEM_DEF(queuelinks) if(isnull(id)) CRASH("Attempted to add to queue with no ID; [what]") - var/datum/queue_link/link - if(isnull(queues[id])) + var/datum/queue_link/link = queues[id] + if(isnull(link)) link = new /datum/queue_link(id) queues[id] = link - else - link = queues[id] if(link.add(what, queue_max)) queues -= id +/** + * Pop a queue link without waiting for it to reach its max size. + * This is useful for those links that do not have a fixed size and thus may not pop. + */ +/datum/controller/subsystem/queuelinks/proc/pop_link(id) + if(isnull(id)) + CRASH("Attempted to pop a queue with no ID") + + var/datum/queue_link/link = queues[id] + if(isnull(queues[id])) + CRASH("Attempted to pop a non-existant queue: [id]") + + link.pop() + queues -= id + + /datum/queue_link /// atoms in our queue var/list/partners = list() @@ -50,17 +64,17 @@ SUBSYSTEM_DEF(queuelinks) if(queue_max != 0 && max != 0 && max != queue_max) CRASH("Tried to change queue size to [max] from [queue_max]!") else if(!queue_max) - queue_max = max - + queue_max = max + if(!queue_max || length(partners) < queue_max) return - + pop() return TRUE /datum/queue_link/proc/pop() for(var/atom/item as anything in partners) - item.MatchedLinks(id, partners) + item.MatchedLinks(id, partners - item) qdel(src) /datum/queue_link/Destroy() diff --git a/code/controllers/subsystem/stock_market.dm b/code/controllers/subsystem/stock_market.dm index c9f632c7faf129b..6c4341adc8d8ad0 100644 --- a/code/controllers/subsystem/stock_market.dm +++ b/code/controllers/subsystem/stock_market.dm @@ -1,7 +1,7 @@ SUBSYSTEM_DEF(stock_market) name = "Stock Market" - wait = 20 SECONDS + wait = 60 SECONDS init_order = INIT_ORDER_DEFAULT runlevels = RUNLEVEL_GAME @@ -28,7 +28,7 @@ SUBSYSTEM_DEF(stock_market) materials_trends[possible_market] = rand(MARKET_TREND_DOWNWARD,MARKET_TREND_UPWARD) //aka -1 to 1 materials_trend_life += possible_market - materials_trend_life[possible_market] = rand(1,10) + materials_trend_life[possible_market] = rand(1,3) materials_quantity += possible_market materials_quantity[possible_market] = possible_market.tradable_base_quantity + (rand(-(possible_market.tradable_base_quantity) * 0.5, possible_market.tradable_base_quantity * 0.5)) @@ -80,7 +80,7 @@ SUBSYSTEM_DEF(stock_market) materials_trends[mat] = MARKET_TREND_DOWNWARD else materials_trends[mat] = MARKET_TREND_STABLE - materials_trend_life[mat] = rand(3,10) // Change our trend life for x number of fires of the subsystem + materials_trend_life[mat] = rand(1,3) // Change our trend life for x number of fires of the subsystem else materials_trend_life[mat] -= 1 @@ -88,14 +88,14 @@ SUBSYSTEM_DEF(stock_market) var/quantity_change = 0 switch(trend) if(MARKET_TREND_UPWARD) - price_change = ROUND_UP(gaussian(price_units * 0.1, price_baseline * 0.05)) //If we don't ceil, small numbers will get trapped at low values - quantity_change = -round(gaussian(quantity_baseline * 0.05, quantity_baseline * 0.05)) + price_change = ROUND_UP(gaussian(price_units * 0.30, price_baseline * 0.15)) //If we don't ceil, small numbers will get trapped at low values + quantity_change = -round(gaussian(quantity_baseline * 0.15, quantity_baseline * 0.15)) if(MARKET_TREND_STABLE) price_change = round(gaussian(0, price_baseline * 0.01)) - quantity_change = round(gaussian(0, quantity_baseline * 0.01)) + quantity_change = round(gaussian(0, quantity_baseline * 0.5)) if(MARKET_TREND_DOWNWARD) - price_change = -ROUND_UP(gaussian(price_units * 0.1, price_baseline * 0.05)) - quantity_change = round(gaussian(quantity_baseline * 0.05, quantity_baseline * 0.05)) + price_change = -ROUND_UP(gaussian(price_units * 0.3, price_baseline * 0.15)) + quantity_change = round(gaussian(quantity_baseline * 0.15, quantity_baseline * 0.15)) materials_prices[mat] = round(clamp(price_units + price_change, price_minimum, price_maximum)) materials_quantity[mat] = round(clamp(stock_quantity + quantity_change, 0, quantity_baseline * 2)) diff --git a/code/datums/ai/_ai_controller.dm b/code/datums/ai/_ai_controller.dm index b525f66576c2fbd..91f624972adced6 100644 --- a/code/datums/ai/_ai_controller.dm +++ b/code/datums/ai/_ai_controller.dm @@ -34,7 +34,7 @@ multiple modular subtrees with behaviors ///Stored arguments for behaviors given during their initial creation var/list/behavior_args = list() ///Tracks recent pathing attempts, if we fail too many in a row we fail our current plans. - var/pathing_attempts + var/consecutive_pathing_attempts ///Can the AI remain in control if there is a client? var/continue_processing_when_client = FALSE ///distance to give up on target diff --git a/code/datums/ai/basic_mobs/targeting_strategies/basic_targeting_strategy.dm b/code/datums/ai/basic_mobs/targeting_strategies/basic_targeting_strategy.dm index a7d43d600b1cdee..14f0d03207959fe 100644 --- a/code/datums/ai/basic_mobs/targeting_strategies/basic_targeting_strategy.dm +++ b/code/datums/ai/basic_mobs/targeting_strategies/basic_targeting_strategy.dm @@ -50,7 +50,9 @@ if(living_mob.see_invisible < the_target.invisibility) //Target's invisible to us, forget it return FALSE - if(isturf(living_mob.loc) && isturf(the_target.loc) && living_mob.z != the_target.z) // z check will always fail if target is in a mech or pawn is shapeshifted or jaunting + if(!isturf(living_mob.loc)) + return FALSE + if(isturf(the_target.loc) && living_mob.z != the_target.z) // z check will always fail if target is in a mech or pawn is shapeshifted or jaunting return FALSE if(isliving(the_target)) //Targeting vs living mobs diff --git a/code/datums/ai/generic/generic_behaviors.dm b/code/datums/ai/generic/generic_behaviors.dm index 43e37f66e8c8aa1..b70375ef3933fc6 100644 --- a/code/datums/ai/generic/generic_behaviors.dm +++ b/code/datums/ai/generic/generic_behaviors.dm @@ -333,7 +333,7 @@ //just in case- it won't do anything if the instrument isn't playing song.stop_playing() - song.ParseSong(song_lines) + song.ParseSong(new_song = song_lines) song.repeat = 10 song.volume = song.max_volume - 10 finish_action(controller, TRUE) diff --git a/code/datums/ai/movement/_ai_movement.dm b/code/datums/ai/movement/_ai_movement.dm index af29e83f1a4a3ad..3f455b2acd0abfc 100644 --- a/code/datums/ai/movement/_ai_movement.dm +++ b/code/datums/ai/movement/_ai_movement.dm @@ -8,22 +8,25 @@ //Override this to setup the moveloop you want to use /datum/ai_movement/proc/start_moving_towards(datum/ai_controller/controller, atom/current_movement_target, min_distance) SHOULD_CALL_PARENT(TRUE) - controller.pathing_attempts = 0 + controller.consecutive_pathing_attempts = 0 controller.set_blackboard_key(BB_CURRENT_MIN_MOVE_DISTANCE, min_distance) moving_controllers[controller] = current_movement_target /datum/ai_movement/proc/stop_moving_towards(datum/ai_controller/controller) - controller.pathing_attempts = 0 + controller.consecutive_pathing_attempts = 0 moving_controllers -= controller // We got deleted as we finished an action if(!QDELETED(controller.pawn)) SSmove_manager.stop_looping(controller.pawn, SSai_movement) /datum/ai_movement/proc/increment_pathing_failures(datum/ai_controller/controller) - controller.pathing_attempts++ - if(controller.pathing_attempts >= max_pathing_attempts) + controller.consecutive_pathing_attempts++ + if(controller.consecutive_pathing_attempts >= max_pathing_attempts) controller.CancelActions() +/datum/ai_movement/proc/reset_pathing_failures(datum/ai_controller/controller) + controller.consecutive_pathing_attempts = 0 + ///Should the movement be allowed to happen? return TRUE if it can, FALSE otherwise /datum/ai_movement/proc/allowed_to_move(datum/move_loop/source) SHOULD_BE_PURE(TRUE) @@ -68,7 +71,8 @@ //Anything to do post movement /datum/ai_movement/proc/post_move(datum/move_loop/source, succeeded) SIGNAL_HANDLER - if(succeeded != FALSE) - return var/datum/ai_controller/controller = source.extra_info + if(succeeded != MOVELOOP_FAILURE) + reset_pathing_failures(controller) + return increment_pathing_failures(controller) diff --git a/code/datums/ai/movement/ai_movement_jps.dm b/code/datums/ai/movement/ai_movement_jps.dm index 6024b7e7562ccdc..825feefabfa3b56 100644 --- a/code/datums/ai/movement/ai_movement_jps.dm +++ b/code/datums/ai/movement/ai_movement_jps.dm @@ -51,3 +51,6 @@ /datum/ai_movement/jps/bot/travel_to_beacon maximum_length = AI_BOT_PATH_LENGTH + +/datum/ai_movement/jps/modsuit + maximum_length = MOD_AI_RANGE diff --git a/code/datums/ai/objects/mod.dm b/code/datums/ai/objects/mod.dm index 2bb555d281bf737..67d8121a4e16f63 100644 --- a/code/datums/ai/objects/mod.dm +++ b/code/datums/ai/objects/mod.dm @@ -5,7 +5,7 @@ BB_MOD_IMPLANT, ) max_target_distance = MOD_AI_RANGE //a little spicy but its one specific item that summons it, and it doesn't run otherwise - ai_movement = /datum/ai_movement/jps + ai_movement = /datum/ai_movement/jps/modsuit ///ID card generated from the suit's required access. Used for pathing. var/obj/item/card/id/advanced/id_card diff --git a/code/datums/brain_damage/severe.dm b/code/datums/brain_damage/severe.dm index fc30d7fb3b8f6f9..d78f2abe9bcf0b0 100644 --- a/code/datums/brain_damage/severe.dm +++ b/code/datums/brain_damage/severe.dm @@ -419,7 +419,7 @@ desc = "Patient seems to oxidise things around them at random, and seem to believe they are aiding a creature in climbing a mountin." scan_desc = "C_)L(#_I_##M;B" gain_text = span_warning("The rusted climb shall finish at the peak") - lose_text = span_notice("The rusted climb? Whats that? An odd dream to be sure.") + lose_text = span_notice("The rusted climb? What's that? An odd dream to be sure.") random_gain = FALSE /datum/brain_trauma/severe/rusting/on_life(seconds_per_tick, times_fired) diff --git a/code/datums/brain_damage/special.dm b/code/datums/brain_damage/special.dm index e24ecd99c61776c..31f316221301e91 100644 --- a/code/datums/brain_damage/special.dm +++ b/code/datums/brain_damage/special.dm @@ -426,3 +426,49 @@ to_chat(victim, "[span_name("[name]")] exclaims, \"[span_robot("[beepskys_cry]")]") if(victim.client?.prefs.read_preference(/datum/preference/toggle/enable_runechat)) victim.create_chat_message(src, raw_message = beepskys_cry, spans = list("robotic")) + +// Used by Veteran Security Advisor job. +/datum/brain_trauma/special/ptsd + name = "Combat PTSD" + desc = "The patient is experiencing PTSD stemming from past combat exposure, resulting in a lack of emotions. Additionally, they are experiencing mild hallucinations." + scan_desc = "PTSD" + gain_text = span_warning("You're thrust back into the chaos of past! Explosions! Gunfire! Emotions, gone AWOL!") + lose_text = span_notice("You feel flashbacks of past fade, as your emotions return and mind clear.") + resilience = TRAUMA_RESILIENCE_ABSOLUTE + can_gain = TRUE + random_gain = FALSE + /// Our cooldown declare for causing hallucinations + COOLDOWN_DECLARE(ptsd_hallucinations) + var/list/ptsd_hallucinations_list = list( + /datum/hallucination/fake_sound/normal/boom, + /datum/hallucination/fake_sound/normal/distant_boom, + /datum/hallucination/stray_bullet, + /datum/hallucination/battle/gun/disabler, + /datum/hallucination/battle/gun/laser, + /datum/hallucination/battle/bomb, + /datum/hallucination/battle/e_sword, + /datum/hallucination/battle/harm_baton, + /datum/hallucination/battle/stun_prod, + ) + +/datum/brain_trauma/special/ptsd/on_life(seconds_per_tick, times_fired) + if(owner.stat != CONSCIOUS) + return + + if(!COOLDOWN_FINISHED(src, ptsd_hallucinations)) + return + + owner.cause_hallucination(pick(ptsd_hallucinations_list), "Caused by The Combat PTSD brain trauma") + COOLDOWN_START(src, ptsd_hallucinations, rand(10 SECONDS, 10 MINUTES)) + +/datum/brain_trauma/special/ptsd/on_gain() + owner.add_mood_event("combat_ptsd", /datum/mood_event/desentized) + owner.mob_mood?.mood_modifier -= 1 //Basically nothing can change your mood + owner.mob_mood?.sanity_level = SANITY_DISTURBED //Makes sanity on a unstable level unless cured + ..() + +/datum/brain_trauma/special/ptsd/on_lose() + owner.clear_mood_event("combat_ptsd") + owner.mob_mood?.mood_modifier += 1 + owner.mob_mood?.sanity_level = SANITY_GREAT + return ..() diff --git a/code/datums/components/attached_sticker.dm b/code/datums/components/attached_sticker.dm deleted file mode 100644 index 49541a6b37c474e..000000000000000 --- a/code/datums/components/attached_sticker.dm +++ /dev/null @@ -1,78 +0,0 @@ -// The attached sticker - -/datum/component/attached_sticker - dupe_mode = COMPONENT_DUPE_ALLOWED - ///The overlay we apply to things we stick to - var/mutable_appearance/sticker_overlay - ///The turf our COMSIG_TURF_EXPOSE is registered to, so we can unregister it later. - var/turf/signal_turf - ///Our physical sticker to drop - var/obj/item/sticker - ///Can we be washed off? - var/washable = TRUE - -/datum/component/attached_sticker/Initialize(px, py, obj/stick, mob/living/user, cleanable=TRUE) - if(!isatom(parent)) - return COMPONENT_INCOMPATIBLE - washable = cleanable - var/atom/atom_parent = parent - sticker = stick - sticker_overlay = mutable_appearance(stick.icon, stick.icon_state , layer = atom_parent.layer + 1, appearance_flags = RESET_COLOR | PIXEL_SCALE) - sticker_overlay.pixel_x = px - sticker_overlay.pixel_y = py - atom_parent.add_overlay(sticker_overlay) - if(isliving(parent) && user) - var/mob/living/victim = parent - if(victim.client) - user.log_message("stuck [sticker] to [key_name(victim)]", LOG_ATTACK) - victim.log_message("had [sticker] stuck to them by [key_name(user)]", LOG_ATTACK) - else if(isturf(parent) && (sticker.resistance_flags & FLAMMABLE)) - //register signals on the users turf instead because we can assume they are on flooring sticking it to a wall so it should burn (otherwise it would fruitlessly check wall temperature) - signal_turf = (user && isclosedturf(parent)) ? get_turf(user) : parent - RegisterSignal(signal_turf, COMSIG_TURF_EXPOSE, PROC_REF(on_turf_expose)) - sticker.moveToNullspace() - RegisterSignal(sticker, COMSIG_QDELETING, PROC_REF(peel)) - -/datum/component/attached_sticker/Destroy() - var/atom/as_atom = parent - as_atom.cut_overlay(sticker_overlay) - sticker_overlay = null - if(sticker) - QDEL_NULL(sticker) - return ..() - -///Move sticker item from nullspace, delete this component, cut overlay -/datum/component/attached_sticker/proc/peel(atom/source) - SIGNAL_HANDLER - if(!QDELETED(sticker)) - var/atom/as_atom = parent - sticker.forceMove(isturf(as_atom) ? as_atom : as_atom.drop_location()) - sticker.pixel_y = rand(-4,1) - sticker.pixel_x = rand(-3,3) - sticker = null - if(!QDELETED(src)) - qdel(src) - -/datum/component/attached_sticker/RegisterWithParent() - if(sticker.resistance_flags & FLAMMABLE) - RegisterSignal(parent, COMSIG_LIVING_IGNITED, PROC_REF(peel)) - if(washable) - RegisterSignal(parent, COMSIG_COMPONENT_CLEAN_ACT, PROC_REF(peel)) - RegisterSignal(parent, COMSIG_QDELETING, PROC_REF(peel)) - ADD_TRAIT(parent, TRAIT_STICKERED, REF(sticker)) - -/datum/component/attached_sticker/UnregisterFromParent() - UnregisterSignal(parent, list(COMSIG_LIVING_IGNITED, COMSIG_QDELETING)) - if(signal_turf) - UnregisterSignal(signal_turf, COMSIG_TURF_EXPOSE) - signal_turf = null - if(washable) - UnregisterSignal(parent, COMSIG_COMPONENT_CLEAN_ACT) - REMOVE_TRAIT(parent, TRAIT_STICKERED, REF(sticker)) - -///Signal handler for COMSIG_TURF_EXPOSE, deletes this sticker if the temperature is above 100C and it is flammable -/datum/component/attached_sticker/proc/on_turf_expose(datum/source, datum/gas_mixture/air, exposed_temperature) - SIGNAL_HANDLER - if(exposed_temperature <= FIRE_MINIMUM_TEMPERATURE_TO_EXIST) - return - peel() diff --git a/code/datums/components/bullet_intercepting.dm b/code/datums/components/bullet_intercepting.dm index c176de54b94c5df..32e757c1823e136 100644 --- a/code/datums/components/bullet_intercepting.dm +++ b/code/datums/components/bullet_intercepting.dm @@ -12,8 +12,10 @@ var/mob/wearer /// Callback called when we catch a projectile var/datum/callback/on_intercepted + /// Number of things we can block before we delete ourself (stop being able to block) + var/block_charges = INFINITY -/datum/component/bullet_intercepting/Initialize(block_chance = 2, block_type = BULLET, active_slots, datum/callback/on_intercepted) +/datum/component/bullet_intercepting/Initialize(block_chance = 2, block_type = BULLET, active_slots, datum/callback/on_intercepted, block_charges = INFINITY) . = ..() if (!isitem(parent)) return COMPONENT_INCOMPATIBLE @@ -21,6 +23,7 @@ src.block_type = block_type src.active_slots = active_slots src.on_intercepted = on_intercepted + src.block_charges = block_charges RegisterSignal(parent, COMSIG_ITEM_EQUIPPED, PROC_REF(on_parent_equipped)) RegisterSignal(parent, COMSIG_ITEM_PRE_UNEQUIP, PROC_REF(on_unequipped)) @@ -55,11 +58,14 @@ /// Called when wearer is shot, check if we're going to block the hit /datum/component/bullet_intercepting/proc/on_wearer_shot(mob/living/victim, list/signal_args, obj/projectile/bullet) SIGNAL_HANDLER - if (victim != wearer || victim.stat == DEAD || bullet.armor_flag != block_type ) - return + if (victim != wearer || victim.stat == DEAD || bullet.armor_flag != block_type) + return NONE if (!prob(block_chance)) - return + return NONE on_intercepted?.Invoke(victim, bullet) + block_charges-- + if (block_charges <= 0) + qdel(src) return PROJECTILE_INTERRUPT_HIT /// Called when wearer is deleted, stop tracking them diff --git a/code/datums/components/crafting/entertainment.dm b/code/datums/components/crafting/entertainment.dm index 8b2bfa407315c36..dae810c220ae1ec 100644 --- a/code/datums/components/crafting/entertainment.dm +++ b/code/datums/components/crafting/entertainment.dm @@ -1,3 +1,22 @@ +/datum/crafting_recipe/moffers + name = "Moffers" + result = /obj/item/clothing/shoes/clown_shoes/moffers + time = 6 SECONDS //opportunity to rethink your life + reqs = list( + /obj/item/stack/sheet/animalhide/mothroach = 2, + /obj/item/clothing/shoes/clown_shoes = 1, + ) + parts = list(/obj/item/clothing/shoes/clown_shoes = 1) + blacklist = list( + /obj/item/clothing/shoes/clown_shoes/combat, + /obj/item/clothing/shoes/clown_shoes/banana_shoes, + /obj/item/clothing/shoes/clown_shoes/banana_shoes/combat, + /obj/item/clothing/shoes/clown_shoes/jester, + /obj/item/clothing/shoes/clown_shoes/meown_shoes, + /obj/item/clothing/shoes/clown_shoes/moffers, + ) + category = CAT_ENTERTAINMENT + /datum/crafting_recipe/mothplush name = "Moth Plushie" result = /obj/item/toy/plush/moth @@ -8,6 +27,16 @@ ) category = CAT_ENTERTAINMENT +/datum/crafting_recipe/sharkplush + name = "Shark Plushie" + result = /obj/item/toy/plush/shark + reqs = list( + /obj/item/clothing/suit/hooded/shark_costume = 1, + /obj/item/grown/cotton = 10, + /obj/item/stack/sheet/cloth = 5, + ) + category = CAT_ENTERTAINMENT + /datum/crafting_recipe/mixedbouquet name = "Mixed bouquet" result = /obj/item/bouquet diff --git a/code/datums/components/crafting/equipment.dm b/code/datums/components/crafting/equipment.dm index 741d53ed56b6c13..e7971488d638fbc 100644 --- a/code/datums/components/crafting/equipment.dm +++ b/code/datums/components/crafting/equipment.dm @@ -83,6 +83,17 @@ time = 5 SECONDS category = CAT_EQUIPMENT +/datum/crafting_recipe/barbeque_grill + name = "Barbeque grill" + result = /obj/machinery/grill + reqs = list( + /obj/item/stack/sheet/iron = 5, + /obj/item/stack/rods = 5, + /obj/item/assembly/igniter = 1, + ) + time = 7 SECONDS + category = CAT_EQUIPMENT + /datum/crafting_recipe/secure_closet name = "Secure Closet" result = /obj/structure/closet/secure_closet diff --git a/code/datums/components/crafting/tailoring.dm b/code/datums/components/crafting/tailoring.dm index bb01a4d78dc0f03..56a6bfb2c3f18f0 100644 --- a/code/datums/components/crafting/tailoring.dm +++ b/code/datums/components/crafting/tailoring.dm @@ -345,6 +345,27 @@ ) category = CAT_CLOTHING +/datum/crafting_recipe/shark_costume + name = "shark costume" + result = /obj/item/clothing/suit/hooded/shark_costume + time = 2 SECONDS + reqs = list( + /obj/item/stack/sheet/leather = 5, + /obj/item/stack/sheet/animalhide/carp = 5, + ) + category = CAT_CLOTHING + +/datum/crafting_recipe/shork_costume + name = "shork costume" + result = /obj/item/clothing/suit/hooded/shork_costume + time = 2 SECONDS + tool_behaviors = list(TOOL_WIRECUTTER) + reqs = list( + /obj/item/clothing/suit/hooded/shark_costume = 1, + ) + category = CAT_CLOTHING + + /datum/crafting_recipe/sturdy_shako name = "Sturdy Shako" result = /obj/item/clothing/head/hats/hos/shako diff --git a/code/datums/components/crank_recharge.dm b/code/datums/components/crank_recharge.dm index 455fa9298f908d0..9c2a1737658e274 100644 --- a/code/datums/components/crank_recharge.dm +++ b/code/datums/components/crank_recharge.dm @@ -2,6 +2,8 @@ /datum/component/crank_recharge /// Our cell to charge var/obj/item/stock_parts/cell/charging_cell + /// Whether we spin our gun to reload (and therefore need the relevant trait) + var/spin_to_win = FALSE /// How much charge we give our cell on each crank var/charge_amount /// How long is the cooldown time between each charge @@ -14,13 +16,14 @@ var/is_charging = FALSE COOLDOWN_DECLARE(charge_sound_cooldown) -/datum/component/crank_recharge/Initialize(charging_cell, charge_amount = 500, cooldown_time = 2 SECONDS, charge_sound = 'sound/weapons/laser_crank.ogg', charge_sound_cooldown_time = 1.8 SECONDS) +/datum/component/crank_recharge/Initialize(charging_cell, spin_to_win = FALSE, charge_amount = 500, cooldown_time = 2 SECONDS, charge_sound = 'sound/weapons/laser_crank.ogg', charge_sound_cooldown_time = 1.8 SECONDS) . = ..() if(!isitem(parent)) return COMPONENT_INCOMPATIBLE if(isnull(charging_cell) || !istype(charging_cell, /obj/item/stock_parts/cell)) return COMPONENT_INCOMPATIBLE src.charging_cell = charging_cell + src.spin_to_win = spin_to_win src.charge_amount = charge_amount src.cooldown_time = cooldown_time src.charge_sound = charge_sound @@ -45,6 +48,10 @@ return if(is_charging) return + if(spin_to_win && !HAS_TRAIT(user, TRAIT_GUNFLIP)) + source.balloon_alert(user, "need holster to spin!") + return + is_charging = TRUE if(COOLDOWN_FINISHED(src, charge_sound_cooldown)) COOLDOWN_START(src, charge_sound_cooldown, charge_sound_cooldown_time) @@ -57,4 +64,6 @@ SEND_SIGNAL(parent, COMSIG_UPDATE_AMMO_HUD) // SKYRAT EDIT ADDITION - AMMO COUNT HUD source.update_appearance() is_charging = FALSE + if(spin_to_win) + source.SpinAnimation(4, 2) //What a badass source.balloon_alert(user, "charged") diff --git a/code/datums/components/echolocation.dm b/code/datums/components/echolocation.dm index 5e4f7528415d794..13ef8f4ed243159 100644 --- a/code/datums/components/echolocation.dm +++ b/code/datums/components/echolocation.dm @@ -4,11 +4,11 @@ /// Time between echolocations. var/cooldown_time = 1.8 SECONDS /// Time for the image to start fading out. - var/image_expiry_time = 1.5 SECONDS + var/image_expiry_time = 1.4 SECONDS /// Time for the image to fade in. - var/fade_in_time = 0.5 SECONDS + var/fade_in_time = 0.4 SECONDS /// Time for the image to fade out and delete itself. - var/fade_out_time = 0.5 SECONDS + var/fade_out_time = 0.4 SECONDS /// Are images static? If yes, spawns them on the turf and makes them not change location. Otherwise they change location and pixel shift with the original. var/images_are_static = TRUE /// With mobs that have this echo group in their echolocation receiver trait, we share echo images. @@ -32,7 +32,7 @@ /// Cooldown for the echolocation. COOLDOWN_DECLARE(cooldown_last) -/datum/component/echolocation/Initialize(echo_range, cooldown_time, image_expiry_time, fade_in_time, fade_out_time, images_are_static, blocking_trait, echo_group, echo_icon, color_path) +/datum/component/echolocation/Initialize(echo_range, cooldown_time, image_expiry_time, fade_in_time, fade_out_time, images_are_static, blocking_trait, echo_group, echo_icon = "echo", color_path) . = ..() var/mob/living/echolocator = parent if(!istype(echolocator)) diff --git a/code/datums/components/fishing_spot.dm b/code/datums/components/fishing_spot.dm index 7ee368e543e3487..2763d583f819c93 100644 --- a/code/datums/components/fishing_spot.dm +++ b/code/datums/components/fishing_spot.dm @@ -16,6 +16,7 @@ RegisterSignal(parent, COMSIG_ATOM_ATTACKBY, PROC_REF(handle_attackby)) RegisterSignal(parent, COMSIG_FISHING_ROD_CAST, PROC_REF(handle_cast)) RegisterSignal(parent, COMSIG_ATOM_EXAMINE, PROC_REF(on_examined)) + RegisterSignal(parent, COMSIG_ATOM_EXAMINE_MORE, PROC_REF(on_examined_more)) /datum/component/fishing_spot/Destroy() fish_source = null diff --git a/code/datums/components/food/ice_cream_holder.dm b/code/datums/components/food/ice_cream_holder.dm index f3db67efab5c0ae..4161c749703609c 100644 --- a/code/datums/components/food/ice_cream_holder.dm +++ b/code/datums/components/food/ice_cream_holder.dm @@ -58,6 +58,7 @@ RegisterSignal(owner, COMSIG_ITEM_ATTACK_ATOM, PROC_REF(on_item_attack_obj)) RegisterSignal(owner, COMSIG_ATOM_UPDATE_OVERLAYS, PROC_REF(on_update_overlays)) + RegisterSignal(owner, COMSIG_ATOM_EXAMINE, PROC_REF(on_examine)) if(change_name) RegisterSignal(owner, COMSIG_ATOM_UPDATE_NAME, PROC_REF(on_update_name)) if(!change_desc) @@ -105,20 +106,27 @@ else source.desc = replacetext(replacetext("[flavour.desc_prefix] [flavour.desc]", "$CONE_NAME", initial(source.name)), "$CUSTOM_NAME", key) else /// Many flavours. - source.desc = "A delicious [initial(source.name)] filled with scoops of [english_list(scoops)] icecream. That's as many as [scoops_len] scoops!" + source.desc = "A delicious [initial(source.name)] filled with scoops of [english_list(scoops)] ice cream. That's as many as [scoops_len] scoops!" + +/datum/component/ice_cream_holder/proc/on_examine(atom/source, mob/mob, list/examine_list) + SIGNAL_HANDLER + if(length(scoops) < max_scoops) + examine_list += span_tinynoticeital("you could use a ice cream vat to fill it with yummy ice cream...") /datum/component/ice_cream_holder/proc/on_examine_more(atom/source, mob/mob, list/examine_list) SIGNAL_HANDLER var/scoops_len = length(scoops) + if(!scoops_len) + return if(scoops_len == 1 || length(unique_list(scoops)) == 1) /// Only one flavour. var/key = scoops[1] var/datum/ice_cream_flavour/flavour = GLOB.ice_cream_flavours[LAZYACCESS(special_scoops, key) || key] if(flavour?.desc) //I scream. - examine_list += "[source.p_Theyre()] filled with scoops of [flavour ? flavour.name : "broken, unhappy"] icecream." + examine_list += "[source.p_Theyre()] filled with scoops of [flavour ? flavour.name : "broken, unhappy"] ice cream." else examine_list += replacetext(replacetext("[source.p_Theyre()] [flavour.desc]", "$CONE_NAME", initial(source.name)), "$CUSTOM_NAME", key) else /// Many flavours. - examine_list += "[source.p_Theyre()] filled with scoops of [english_list(scoops)] icecream. That's as many as [scoops_len] scoops!" + examine_list += "[source.p_Theyre()] filled with scoops of [english_list(scoops)] ice cream. That's as many as [scoops_len] scoops!" /datum/component/ice_cream_holder/proc/on_update_overlays(atom/source, list/new_overlays) SIGNAL_HANDLER @@ -330,14 +338,14 @@ GLOBAL_LIST_INIT_TYPED(ice_cream_flavours, /datum/ice_cream_flavour, init_ice_cr /datum/ice_cream_flavour/custom name = ICE_CREAM_CUSTOM color = COLOR_STARLIGHT //has its own mutable appearance overlay it will be overwritten with anyways. - desc = "filled with artisanal icecream. Made with real $CUSTOM_NAME. Ain't that something." + desc = "filled with artisanal ice cream. Made with real $CUSTOM_NAME. Ain't that something." ingredients = list(/datum/reagent/consumable/milk, /datum/reagent/consumable/ice) ingredients_text = "optional flavorings" takes_custom_ingredients = TRUE /datum/ice_cream_flavour/custom/korta name = ICE_CREAM_KORTA_CUSTOM - desc = "filled with artisanal lizard-friendly icecream. Made with real $CUSTOM_NAME. Ain't that something." + desc = "filled with artisanal lizard-friendly ice cream. Made with real $CUSTOM_NAME. Ain't that something." ingredients = list(/datum/reagent/consumable/korta_milk, /datum/reagent/consumable/ice) ingredients_text = "optional flavorings" @@ -354,7 +362,7 @@ GLOBAL_LIST_INIT_TYPED(ice_cream_flavours, /datum/ice_cream_flavour, init_ice_cr /datum/ice_cream_flavour/bland name = ICE_CREAM_BLAND color = COLOR_ICECREAM_CUSTOM - desc = "filled with anemic, flavorless icecream. You wonder why this was ever scooped..." + desc = "filled with anemic, flavorless ice cream. You wonder why this was ever scooped..." hidden = TRUE #undef SWEETENER_PER_SCOOP diff --git a/code/datums/components/material/remote_materials.dm b/code/datums/components/material/remote_materials.dm index e418d4276be1046..568b018e58b2b0a 100644 --- a/code/datums/components/material/remote_materials.dm +++ b/code/datums/components/material/remote_materials.dm @@ -84,23 +84,9 @@ handles linking back and forth. silo = null - var/static/list/allowed_mats = list( - /datum/material/iron, - /datum/material/glass, - /datum/material/silver, - /datum/material/gold, - /datum/material/diamond, - /datum/material/plasma, - /datum/material/uranium, - /datum/material/bananium, - /datum/material/titanium, - /datum/material/bluespace, - /datum/material/plastic, - ) - mat_container = parent.AddComponent( \ /datum/component/material_container, \ - allowed_mats, \ + SSmaterials.materials_by_category[MAT_CATEGORY_SILO], \ local_size, \ mat_container_flags, \ container_signals = mat_container_signals, \ diff --git a/code/datums/components/overlay_lighting.dm b/code/datums/components/overlay_lighting.dm index efff82b703a6caa..19c7528db8bf3c0 100644 --- a/code/datums/components/overlay_lighting.dm +++ b/code/datums/components/overlay_lighting.dm @@ -398,7 +398,7 @@ return if(current_holder && overlay_lighting_flags & LIGHTING_ON) current_holder.underlays -= cone - cone.alpha = min(200, (abs(new_power) * 90)+20) + cone.alpha = min(120, (abs(new_power) * 60) + 15) if(current_holder && overlay_lighting_flags & LIGHTING_ON) current_holder.underlays += cone diff --git a/code/datums/components/payment.dm b/code/datums/components/payment.dm index 1220614e9c3864d..5e79b28fd57246d 100644 --- a/code/datums/components/payment.dm +++ b/code/datums/components/payment.dm @@ -19,11 +19,6 @@ var/datum/bank_account/target_acc ///Does this payment component respect same-department-discount? var/department_discount = FALSE - ///A static typecache of all the money-based items that can be actively used as currency. - var/static/list/allowed_money = typecacheof(list( - /obj/item/stack/spacecash, - /obj/item/holochip, - /obj/item/coin)) /datum/component/payment/Initialize(_cost, _target, _style) target_acc = _target @@ -80,13 +75,13 @@ //Here is all the possible non-ID payment methods. var/list/counted_money = list() var/physical_cash_total = 0 - for(var/obj/item/credit in typecache_filter_list(user.get_all_contents(), allowed_money)) //Coins, cash, and credits. + for(var/obj/item/credit in typecache_filter_list(user.get_all_contents(), GLOB.allowed_money)) //Coins, cash, and credits. if(physical_cash_total > total_cost) break physical_cash_total += credit.get_item_credit_value() counted_money += credit - if(is_type_in_typecache(user.pulling, allowed_money) && (physical_cash_total < total_cost)) //Coins(Pulled). + if(is_type_in_typecache(user.pulling, GLOB.allowed_money) && (physical_cash_total < total_cost)) //Coins(Pulled). var/obj/item/counted_credit = user.pulling physical_cash_total += counted_credit.get_item_credit_value() counted_money += counted_credit @@ -134,9 +129,11 @@ * Attempts to charge a mob, user, an integer number of credits, total_cost, directly from an ID card/bank account. */ /datum/component/payment/proc/handle_card(mob/living/user, obj/item/card/id/idcard, total_cost) - var/atom/atom_parent = parent + var/atom/movable/atom_parent = parent if(!idcard) + if(transaction_style == PAYMENT_VENDING) + to_chat(user, span_warning("No card found.")) return FALSE if(!idcard?.registered_account) switch(transaction_style) @@ -146,6 +143,13 @@ to_chat(user, span_warning("ARE YOU JOKING. YOU DON'T HAVE A BANK ACCOUNT ON YOUR ID YOU IDIOT.")) if(PAYMENT_CLINICAL) to_chat(user, span_warning("ID Card lacks a bank account. Advancing.")) + if(PAYMENT_VENDING) + to_chat(user, span_warning("No account found.")) + + return FALSE + + if(!idcard.registered_account.account_job) + atom_parent.say("Departmental accounts have been blacklisted from personal expenses due to embezzlement.") return FALSE if(!(idcard.registered_account.has_money(total_cost))) @@ -156,6 +160,8 @@ to_chat(user, span_warning("YOU MORON. YOU ABSOLUTE BAFOON. YOU INSUFFERABLE TOOL. YOU ARE POOR.")) if(PAYMENT_CLINICAL) to_chat(user, span_warning("ID Card lacks funds. Aborting.")) + if(PAYMENT_VENDING) + to_chat(user, span_warning("You do not possess the funds to purchase that.")) atom_parent.balloon_alert(user, "needs [total_cost] credit\s!") return FALSE target_acc.transfer_money(idcard.registered_account, total_cost, "Nanotrasen: Usage of Corporate Machinery") diff --git a/code/datums/components/riding/riding_vehicle.dm b/code/datums/components/riding/riding_vehicle.dm index 2a556ac8944c560..d6c5a665d1557eb 100644 --- a/code/datums/components/riding/riding_vehicle.dm +++ b/code/datums/components/riding/riding_vehicle.dm @@ -169,6 +169,8 @@ /datum/component/riding/vehicle/scooter/skateboard vehicle_move_delay = 1.5 ride_check_flags = RIDER_NEEDS_LEGS | UNBUCKLE_DISABLED_RIDER + ///If TRUE, the vehicle will be slower (but safer) to ride on walk intent. + var/can_slow_down = TRUE /datum/component/riding/vehicle/scooter/skateboard/handle_specials() . = ..() @@ -177,8 +179,82 @@ set_vehicle_dir_layer(EAST, OBJ_LAYER) set_vehicle_dir_layer(WEST, OBJ_LAYER) +/datum/component/riding/vehicle/scooter/skateboard/RegisterWithParent() + . = ..() + if(can_slow_down) + RegisterSignal(parent, COMSIG_ATOM_EXAMINE, PROC_REF(on_examine)) + var/obj/vehicle/ridden/scooter/skateboard/board = parent + if(istype(board)) + board.can_slow_down = can_slow_down + +/datum/component/riding/vehicle/scooter/skateboard/proc/on_examine(datum/source, mob/user, list/examine_list) + SIGNAL_HANDLER + examine_list += span_notice("Going slow and nice at [EXAMINE_HINT("walk")] speed will prevent crashing into things.") + +/datum/component/riding/vehicle/scooter/skateboard/vehicle_mob_buckle(datum/source, mob/living/rider, force = FALSE) + . = ..() + if(can_slow_down) + RegisterSignal(rider, COMSIG_MOVE_INTENT_TOGGLED, PROC_REF(toggle_move_delay)) + toggle_move_delay(rider) + +/datum/component/riding/vehicle/scooter/skateboard/handle_unbuckle(mob/living/rider) + . = ..() + if(can_slow_down) + toggle_move_delay(rider) + UnregisterSignal(rider, COMSIG_MOVE_INTENT_TOGGLED) + +/datum/component/riding/vehicle/scooter/skateboard/proc/toggle_move_delay(mob/living/rider) + SIGNAL_HANDLER + vehicle_move_delay = initial(vehicle_move_delay) + if(rider.move_intent == MOVE_INTENT_WALK) + vehicle_move_delay += 0.6 + +/datum/component/riding/vehicle/scooter/skateboard/pro + vehicle_move_delay = 1 + +///This one lets the rider ignore gravity, move in zero g and son on, but only on ground turfs or at most one z-level above them. +/datum/component/riding/vehicle/scooter/skateboard/hover + vehicle_move_delay = 1 + override_allow_spacemove = TRUE + +/datum/component/riding/vehicle/scooter/skateboard/hover/RegisterWithParent() + . = ..() + RegisterSignal(parent, COMSIG_ATOM_HAS_GRAVITY, PROC_REF(check_grav)) + RegisterSignal(parent, COMSIG_MOVABLE_SPACEMOVE, PROC_REF(check_drifting)) + hover_check() + +///Makes sure that the vehicle is grav-less if capable of zero-g movement. Forced gravity will honestly screw this. +/datum/component/riding/vehicle/scooter/skateboard/hover/proc/check_grav(datum/source, turf/gravity_turf, list/gravs) + SIGNAL_HANDLER + if(override_allow_spacemove) + gravs += 0 + +///Makes sure the vehicle isn't drifting while it can be maneuvered. +/datum/component/riding/vehicle/scooter/skateboard/hover/proc/check_drifting(datum/source, movement_dir, continuous_move) + SIGNAL_HANDLER + if(override_allow_spacemove) + return COMSIG_MOVABLE_STOP_SPACEMOVE + +/datum/component/riding/vehicle/scooter/skateboard/hover/vehicle_moved(atom/movable/source, oldloc, dir, forced) + . = ..() + hover_check(TRUE) + +///Makes sure that the hoverboard can move in zero-g in (open) space but only there's a ground turf on the z-level below. +/datum/component/riding/vehicle/scooter/skateboard/hover/proc/hover_check(is_moving = FALSE) + var/atom/movable/movable = parent + if(!isopenspaceturf(movable.loc)) + override_allow_spacemove = TRUE + return + var/turf/open/our_turf = movable.loc + var/turf/turf_below = GET_TURF_BELOW(our_turf) + if(our_turf.zPassOut(DOWN) && (isnull(turf_below) || (isopenspaceturf(turf_below) && turf_below.zPassIn(DOWN) && turf_below.zPassOut(DOWN)))) + override_allow_spacemove = FALSE + if(turf_below) + our_turf.zFall(movable, falling_from_move = is_moving) + /datum/component/riding/vehicle/scooter/skateboard/wheelys vehicle_move_delay = 1.75 // SKYRAT EDIT - ORIGINAL: 0 + can_slow_down = FALSE /datum/component/riding/vehicle/scooter/skateboard/wheelys/handle_specials() . = ..() diff --git a/code/datums/components/shrink.dm b/code/datums/components/shrink.dm index 67cd3d39e23cd79..d2615ea2f777057 100644 --- a/code/datums/components/shrink.dm +++ b/code/datums/components/shrink.dm @@ -15,6 +15,7 @@ if(isliving(parent_atom)) var/mob/living/L = parent_atom ADD_TRAIT(L, TRAIT_UNDENSE, SHRUNKEN_TRAIT) + RegisterSignal(L, COMSIG_MOB_SAY, PROC_REF(handle_shrunk_speech)) L.add_movespeed_modifier(/datum/movespeed_modifier/shrink_ray) if(iscarbon(L)) var/mob/living/carbon/C = L @@ -30,6 +31,10 @@ span_userdanger("Everything grows bigger!")) QDEL_IN(src, shrink_time) +/datum/component/shrink/proc/handle_shrunk_speech(mob/living/little_guy, list/speech_args) + SIGNAL_HANDLER + speech_args[SPEECH_SPANS] |= SPAN_SMALL_VOICE + /datum/component/shrink/Destroy() var/atom/parent_atom = parent parent_atom.transform = parent_atom.transform.Scale(2,2) @@ -38,6 +43,7 @@ var/mob/living/L = parent_atom L.remove_movespeed_modifier(/datum/movespeed_modifier/shrink_ray) REMOVE_TRAIT(L, TRAIT_UNDENSE, SHRUNKEN_TRAIT) + UnregisterSignal(L, COMSIG_MOB_SAY) if(ishuman(L)) var/mob/living/carbon/human/H = L H.physiology.damage_resistance += 100 diff --git a/code/datums/components/sizzle.dm b/code/datums/components/sizzle.dm index ce91e9593f75f7d..957586aa806b8e0 100644 --- a/code/datums/components/sizzle.dm +++ b/code/datums/components/sizzle.dm @@ -1,26 +1,31 @@ /datum/component/sizzle - var/mutable_appearance/sizzling - var/sizzlealpha = 0 dupe_mode = COMPONENT_DUPE_UNIQUE_PASSARGS -/datum/component/sizzle/Initialize() + ///The sizzling appearance to put on top of the food item + var/mutable_appearance/sizzling + ///The amount of time the food item has been sizzling for + var/grilled_time = 0 + +/datum/component/sizzle/Initialize(grilled_time) if(!isatom(parent)) return COMPONENT_INCOMPATIBLE - setup_sizzle() - -/datum/component/sizzle/InheritComponent(datum/component/C, i_am_original) - var/atom/food = parent - sizzlealpha += 5 - sizzling.alpha = sizzlealpha - food.cut_overlay(sizzling) - food.add_overlay(sizzling) -/datum/component/sizzle/proc/setup_sizzle() var/atom/food = parent var/icon/grill_marks = icon(food.icon, food.icon_state) grill_marks.Blend("#fff", ICON_ADD) //fills the icon_state with white (except where it's transparent) grill_marks.Blend(icon('icons/obj/machines/kitchen.dmi', "grillmarks"), ICON_MULTIPLY) //adds grill marks and the remaining white areas become transparent sizzling = new(grill_marks) - sizzling.alpha = sizzlealpha food.add_overlay(sizzling) + src.grilled_time = grilled_time + +/datum/component/sizzle/InheritComponent(datum/component/C, i_am_original, grilled_time) + var/atom/food = parent + sizzling.alpha += 5 + food.cut_overlay(sizzling) + food.add_overlay(sizzling) + src.grilled_time = grilled_time + +///Returns how long the food item has been sizzling for +/datum/component/sizzle/proc/time_elapsed() + return src.grilled_time diff --git a/code/datums/components/sticker.dm b/code/datums/components/sticker.dm new file mode 100644 index 000000000000000..0562f6048077ea3 --- /dev/null +++ b/code/datums/components/sticker.dm @@ -0,0 +1,111 @@ +/** + * ### Sticker component + * + * Component that draws supplied atom's icon over parent object with specified offset, + * icon centering is handled inside. + */ +/datum/component/sticker + dupe_mode = COMPONENT_DUPE_ALLOWED + + /// Either `turf` or `null`, used to connect to `COMSIG_TURF_EXPOSE` signal when parent is a turf. + var/turf/listening_turf + /// Refernce to a "stickered" atom. + var/atom/movable/our_sticker + /// Reference to the created overlay, used during component deletion. + var/mutable_appearance/sticker_overlay + +/datum/component/sticker/Initialize(atom/stickering_atom, mob/user, dir = NORTH, px = 0, py = 0) + if(!isatom(parent)) + return COMPONENT_INCOMPATIBLE + + src.our_sticker = our_sticker + + if(isliving(parent) && !isnull(user)) + var/mob/living/victim = parent + + if(!isnull(victim.client)) + user.log_message("stuck [stickering_atom] to [key_name(victim)]", LOG_ATTACK) + victim.log_message("had [stickering_atom] stuck to them by [key_name(user)]", LOG_ATTACK) + + stick(stickering_atom, px, py) + register_turf_signals(dir) + +/datum/component/sticker/Destroy(force) + var/atom/parent_atom = parent + parent_atom.cut_overlay(sticker_overlay) + + unregister_turf_signals() + + REMOVE_TRAIT(parent, TRAIT_STICKERED, REF(src)) + + QDEL_NULL(our_sticker) + QDEL_NULL(sticker_overlay) + return ..() + +/datum/component/sticker/RegisterWithParent() + if(isliving(parent)) + RegisterSignal(parent, COMSIG_LIVING_IGNITED, PROC_REF(on_ignite)) + RegisterSignal(parent, COMSIG_COMPONENT_CLEAN_ACT, PROC_REF(on_clean)) + +/datum/component/sticker/UnregisterFromParent() + if(isliving(parent)) + UnregisterSignal(parent, COMSIG_LIVING_IGNITED) + UnregisterSignal(parent, COMSIG_COMPONENT_CLEAN_ACT) + +/// Subscribes to `COMSIG_TURF_EXPOSE` if parent atom is a turf. If turf is closed - subscribes to signal +/datum/component/sticker/proc/register_turf_signals(dir) + if(!isturf(parent)) + return + + listening_turf = isclosedturf(parent) ? get_step(parent, dir) : parent + RegisterSignal(listening_turf, COMSIG_TURF_EXPOSE, PROC_REF(on_turf_expose)) + +/// Unsubscribes from `COMSIG_TURF_EXPOSE` if `listening_turf` is not `null`. +/datum/component/sticker/proc/unregister_turf_signals() + if(isnull(listening_turf)) + return + + UnregisterSignal(listening_turf, COMSIG_TURF_EXPOSE) + +/// Handles overlay creation from supplied atom, adds created icon to the parent object, moves source atom to the nullspace. +/datum/component/sticker/proc/stick(atom/movable/stickering_atom, px, py) + our_sticker = stickering_atom + our_sticker.moveToNullspace() + + var/atom/parent_atom = parent + + sticker_overlay = mutable_appearance(icon = our_sticker.icon, icon_state = our_sticker.icon_state, layer = parent_atom.layer + 0.01, appearance_flags = RESET_COLOR) + sticker_overlay.pixel_w = px - world.icon_size / 2 + sticker_overlay.pixel_z = py - world.icon_size / 2 + + parent_atom.add_overlay(sticker_overlay) + + ADD_TRAIT(parent, TRAIT_STICKERED, REF(src)) + +/// Moves stickered atom from the nullspace, deletes component. +/datum/component/sticker/proc/peel() + var/atom/parent_atom = parent + var/turf/drop_location = isnull(listening_turf) ? parent_atom.drop_location() : listening_turf + + our_sticker.forceMove(drop_location) + our_sticker = null + + qdel(src) + +/datum/component/sticker/proc/on_ignite(datum/source) + SIGNAL_HANDLER + + qdel(src) + +/datum/component/sticker/proc/on_clean(datum/source, clean_types) + SIGNAL_HANDLER + + peel() + + return COMPONENT_CLEANED + +/datum/component/sticker/proc/on_turf_expose(datum/source, datum/gas_mixture/air, exposed_temperature) + SIGNAL_HANDLER + + if(exposed_temperature >= FIRE_MINIMUM_TEMPERATURE_TO_EXIST) + qdel(src) diff --git a/code/datums/components/style/style.dm b/code/datums/components/style/style.dm index d50b9736e8f9859..8b532277e34af33 100644 --- a/code/datums/components/style/style.dm +++ b/code/datums/components/style/style.dm @@ -96,8 +96,6 @@ if(multitooled) src.multitooled = multitooled - RegisterSignal(src, COMSIG_ATOM_TOOL_ACT(TOOL_MULTITOOL), PROC_REF(on_parent_multitool)) - ADD_TRAIT(mob_parent, TRAIT_STYLISH, REF(src)) // SKYRAT EDIT ADD - allows style meter chads to do flips /datum/component/style/RegisterWithParent() @@ -345,12 +343,6 @@ INVOKE_ASYNC(source, TYPE_PROC_REF(/mob/living, put_in_hands), target) source.visible_message(span_notice("[source] quickly swaps [weapon] out with [target]!"), span_notice("You quickly swap [weapon] with [target].")) - -/datum/component/style/proc/on_parent_multitool(datum/source, mob/living/user, obj/item/tool, list/recipes) - multitooled = !multitooled - user.balloon_alert(user, "meter [multitooled ? "" : "un"]hacked") - - // Point givers /datum/component/style/proc/on_punch(mob/living/carbon/human/punching_person, atom/attacked_atom, proximity) SIGNAL_HANDLER diff --git a/code/datums/components/style/style_meter.dm b/code/datums/components/style/style_meter.dm index 8c5b5ea87df60bc..72688f41c527494 100644 --- a/code/datums/components/style/style_meter.dm +++ b/code/datums/components/style/style_meter.dm @@ -17,7 +17,6 @@ /obj/item/style_meter/Initialize(mapload) . = ..() meter_appearance = mutable_appearance(icon, icon_state) - RegisterSignal(src, COMSIG_ATOM_TOOL_ACT(TOOL_MULTITOOL), PROC_REF(on_multitool)) /obj/item/style_meter/Destroy(force) if(istype(loc, /obj/item/clothing/glasses)) @@ -28,28 +27,30 @@ . = ..() . += span_notice("You feel like a multitool could be used on this.") -/obj/item/style_meter/afterattack(atom/movable/attacked_atom, mob/user, proximity_flag, click_parameters) - . = ..() - if(!istype(attacked_atom, /obj/item/clothing/glasses)) - return +/obj/item/style_meter/interact_with_atom(atom/interacting_with, mob/living/user) + if(!istype(interacting_with, /obj/item/clothing/glasses)) + return NONE - forceMove(attacked_atom) - attacked_atom.add_overlay(meter_appearance) - RegisterSignal(attacked_atom, COMSIG_ITEM_EQUIPPED, PROC_REF(check_wearing)) - RegisterSignal(attacked_atom, COMSIG_ITEM_DROPPED, PROC_REF(on_drop)) - RegisterSignal(attacked_atom, COMSIG_ATOM_EXAMINE, PROC_REF(on_examine)) - RegisterSignal(attacked_atom, COMSIG_CLICK_ALT, PROC_REF(on_altclick)) - RegisterSignal(attacked_atom, COMSIG_ATOM_TOOL_ACT(TOOL_MULTITOOL), PROC_REF(on_multitool)) + . = ITEM_INTERACT_SUCCESS + + forceMove(interacting_with) + interacting_with.add_overlay(meter_appearance) + RegisterSignal(interacting_with, COMSIG_ITEM_EQUIPPED, PROC_REF(check_wearing)) + RegisterSignal(interacting_with, COMSIG_ITEM_DROPPED, PROC_REF(on_drop)) + RegisterSignal(interacting_with, COMSIG_ATOM_EXAMINE, PROC_REF(on_examine)) + RegisterSignal(interacting_with, COMSIG_CLICK_ALT, PROC_REF(on_altclick)) + RegisterSignal(interacting_with, COMSIG_ATOM_TOOL_ACT(TOOL_MULTITOOL), PROC_REF(redirect_multitool)) balloon_alert(user, "style meter attached") playsound(src, 'sound/machines/click.ogg', 30, TRUE) - if(!iscarbon(attacked_atom.loc)) - return + if(!iscarbon(interacting_with.loc)) + return . - var/mob/living/carbon/carbon_wearer = attacked_atom.loc - if(carbon_wearer.glasses != attacked_atom) - return + var/mob/living/carbon/carbon_wearer = interacting_with.loc + if(carbon_wearer.glasses != interacting_with) + return . style_meter = carbon_wearer.AddComponent(/datum/component/style, multitooled) + return . /obj/item/style_meter/Moved(atom/old_loc, Dir, momentum_change) . = ..() @@ -98,15 +99,17 @@ return COMPONENT_CANCEL_CLICK_ALT - -/// Signal proc for when the glasses or the meter is multitooled -/obj/item/style_meter/proc/on_multitool(datum/source, mob/living/user, obj/item/tool, list/recipes) +/obj/item/style_meter/multitool_act(mob/living/user, obj/item/tool) multitooled = !multitooled - if(style_meter) - SEND_SIGNAL(style_meter, COMSIG_ATOM_TOOL_ACT(TOOL_MULTITOOL), user, tool, recipes) - else - balloon_alert(user, "meter [multitooled ? "" : "un"]hacked") + balloon_alert(user, "meter [multitooled ? "" : "un"]hacked") + style_meter?.multitooled = multitooled + return ITEM_INTERACT_SUCCESS + +/// Redirect multitooling on our glasses to our style meter +/obj/item/style_meter/proc/redirect_multitool(datum/source, mob/living/user, obj/item/tool, ...) + SIGNAL_HANDLER + return multitool_act(user, tool) /// Unregister signals and just generally clean up ourselves after being removed from glasses /obj/item/style_meter/proc/clean_up(atom/movable/old_location) diff --git a/code/datums/components/surgery_initiator.dm b/code/datums/components/surgery_initiator.dm index ab18408b62996a5..360e7ab9b51cc8f 100644 --- a/code/datums/components/surgery_initiator.dm +++ b/code/datums/components/surgery_initiator.dm @@ -339,7 +339,7 @@ span_notice("You drape [parent] over [target]'s [parse_zone(selected_zone)] to prepare for \an [procedure.name]."), ) - if(!(HAS_TRAIT(target, TRAIT_NUMBED) || target.stat >= UNCONSCIOUS)) ///skyrat add start - warning for unanesthetized surgery + if(!(HAS_TRAIT(target, TRAIT_ANALGESIA) || target.stat >= UNCONSCIOUS)) ///skyrat add start - warning for unanesthetized surgery target.balloon_alert(user, "not numbed!") ///skyrat add end log_combat(user, target, "operated on", null, "(OPERATION TYPE: [procedure.name]) (TARGET AREA: [selected_zone])") diff --git a/code/datums/components/tackle.dm b/code/datums/components/tackle.dm index 128a48d30a929c6..0254022b5665cca 100644 --- a/code/datums/components/tackle.dm +++ b/code/datums/components/tackle.dm @@ -443,7 +443,7 @@ if(human_sacker.get_mob_height() <= HUMAN_HEIGHT_SHORTEST) //JUST YOU WAIT TILL I FIND A CHAIR, BUDDY, THEN YOU'LL BE SORRY attack_mod -= 2 - if(human_sacker.mob_mood.sanity_level == SANITY_INSANE) //I've gone COMPLETELY INSANE + if(human_sacker.mob_mood.sanity_level == SANITY_LEVEL_INSANE) //I've gone COMPLETELY INSANE attack_mod += 15 human_sacker.adjustStaminaLoss(100) //AHAHAHAHAHAHAHAHA diff --git a/code/datums/components/tameable.dm b/code/datums/components/tameable.dm index 67325b489d3670d..43f48005bf89e56 100644 --- a/code/datums/components/tameable.dm +++ b/code/datums/components/tameable.dm @@ -10,10 +10,8 @@ var/bonus_tame_chance ///Current chance to tame on interaction var/current_tame_chance - ///For effects once soemthing is tamed - var/datum/callback/after_tame -/datum/component/tameable/Initialize(food_types, tame_chance, bonus_tame_chance, datum/callback/after_tame, unique = TRUE) +/datum/component/tameable/Initialize(food_types, tame_chance, bonus_tame_chance, unique = TRUE) if(!isatom(parent)) //yes, you could make a tameable toolbox. return COMPONENT_INCOMPATIBLE @@ -24,18 +22,12 @@ src.current_tame_chance = tame_chance if(bonus_tame_chance) src.bonus_tame_chance = bonus_tame_chance - if(after_tame) - src.after_tame = after_tame src.unique = unique RegisterSignal(parent, COMSIG_ATOM_ATTACKBY, PROC_REF(try_tame)) RegisterSignal(parent, COMSIG_SIMPLEMOB_SENTIENCEPOTION, PROC_REF(on_tame)) //Instantly succeeds RegisterSignal(parent, COMSIG_SIMPLEMOB_TRANSFERPOTION, PROC_REF(on_tame)) //Instantly succeeds -/datum/component/tameable/Destroy(force) - after_tame = null - return ..() - /datum/component/tameable/proc/try_tame(datum/source, obj/item/food, mob/living/attacker, params) SIGNAL_HANDLER if(!is_type_in_list(food, food_types)) @@ -70,9 +62,9 @@ return living_parent.faction.Find(REF(potential_friend)) ///Ran once taming succeeds -/datum/component/tameable/proc/on_tame(atom/source, mob/living/tamer, atom/food, inform_tamer = FALSE) +/datum/component/tameable/proc/on_tame(atom/source, mob/living/tamer, obj/item/food, inform_tamer = FALSE) SIGNAL_HANDLER - after_tame?.Invoke(tamer, food)//Run custom behavior if needed + source.tamed(tamer, food)//Run custom behavior if needed if(isliving(parent) && isliving(tamer)) INVOKE_ASYNC(source, TYPE_PROC_REF(/mob/living, befriend), tamer) diff --git a/code/datums/components/uplink.dm b/code/datums/components/uplink.dm index e4e6e611ebca11a..5007d8caeb92d3a 100644 --- a/code/datums/components/uplink.dm +++ b/code/datums/components/uplink.dm @@ -375,18 +375,18 @@ // PDA signal responses -/datum/component/uplink/proc/new_ringtone(datum/source, atom/source, new_ring_text) +/datum/component/uplink/proc/new_ringtone(datum/source, mob/living/user, new_ring_text) SIGNAL_HANDLER if(trim(lowertext(new_ring_text)) != trim(lowertext(unlock_code))) if(trim(lowertext(new_ring_text)) == trim(lowertext(failsafe_code))) - failsafe(source) + failsafe(user) return COMPONENT_STOP_RINGTONE_CHANGE return locked = FALSE - if(ismob(source)) - interact(null, source) - to_chat(source, span_hear("The computer softly beeps.")) + if(ismob(user)) + interact(null, user) + to_chat(user, span_hear("The computer softly beeps.")) return COMPONENT_STOP_RINGTONE_CHANGE /datum/component/uplink/proc/check_detonate() diff --git a/code/datums/dna.dm b/code/datums/dna.dm index 2a7423a1fc19088..fc56cfc9c43fb31 100644 --- a/code/datums/dna.dm +++ b/code/datums/dna.dm @@ -514,7 +514,7 @@ GLOBAL_LIST_INIT(total_uf_len_by_block, populate_total_uf_len_by_block()) mutant_bodyparts = species.get_mutant_bodyparts(features, existing_mutant_bodyparts = randomize_features ? list() : mutant_bodyparts) // SKYRAT EDIT ADDITION update_dna_identity() -/datum/dna/stored //subtype used by brain mob's stored_dna +/datum/dna/stored //subtype used by brain mob's stored_dna and the crew manifest /datum/dna/stored/add_mutation(mutation_name) //no mutation changes on stored dna. return diff --git a/code/controllers/subsystem/eigenstate.dm b/code/datums/eigenstate.dm similarity index 66% rename from code/controllers/subsystem/eigenstate.dm rename to code/datums/eigenstate.dm index f167fdf24d1efd1..3bba74632099772 100644 --- a/code/controllers/subsystem/eigenstate.dm +++ b/code/datums/eigenstate.dm @@ -1,7 +1,7 @@ -///Subsystem used to teleport people to a linked web of itterative entries. If one entry is deleted, the 2 around it will forge a link instead. -SUBSYSTEM_DEF(eigenstates) - name = "Eigenstates" - flags = SS_NO_INIT | SS_NO_FIRE +GLOBAL_DATUM_INIT(eigenstate_manager, /datum/eigenstate_manager, new) + +///A singleton used to teleport people to a linked web of itterative entries. If one entry is deleted, the 2 around it will forge a link instead. +/datum/eigenstate_manager ///The list of objects that something is linked to indexed by UID var/list/eigen_targets = list() ///UID to object reference @@ -12,7 +12,7 @@ SUBSYSTEM_DEF(eigenstates) var/spark_time = 0 ///Creates a new link of targets unique to their own id -/datum/controller/subsystem/eigenstates/proc/create_new_link(targets) +/datum/eigenstate_manager/proc/create_new_link(targets, subtle = TRUE) if(length(targets) <= 1) return FALSE for(var/atom/target as anything in targets) //Clear out any connected @@ -20,40 +20,44 @@ SUBSYSTEM_DEF(eigenstates) if(!already_linked) continue if(length(eigen_targets[already_linked]) > 1) //Eigenstates are notorious for having cliques! - target.visible_message("[target] fizzes, it's already linked to something else!") + if(!subtle) + target.visible_message("[target] fizzes, it's already linked to something else!") targets -= target continue - target.visible_message("[target] fizzes, collapsing it's unique wavefunction into the others!") //If we're in a eigenlink all on our own and are open to new friends + if(!subtle) + target.visible_message("[target] fizzes, collapsing it's unique wavefunction into the others!") //If we're in a eigenlink all on our own and are open to new friends remove_eigen_entry(target) //clearup for new stuff //Do we still have targets? if(!length(targets)) return FALSE var/atom/visible_atom = targets[1] //The object that'll handle the messages if(length(targets) == 1) - visible_atom.visible_message("[targets[1]] fizzes, there's nothing it can link to!") + if(!subtle) + visible_atom.visible_message("[targets[1]] fizzes, there's nothing it can link to!") return FALSE - eigen_targets["[id_counter]"] = list() //Add to the master list + var/subtle_keyword = subtle ? "subtle" : "" + eigen_targets["[id_counter][subtle_keyword]"] = list() //Add to the master list for(var/atom/target as anything in targets) - eigen_targets["[id_counter]"] += target - eigen_id[target] = "[id_counter]" + eigen_targets["[id_counter][subtle_keyword]"] += target + eigen_id[target] = "[id_counter][subtle_keyword]" RegisterSignal(target, COMSIG_CLOSET_INSERT, PROC_REF(use_eigenlinked_atom)) RegisterSignal(target, COMSIG_QDELETING, PROC_REF(remove_eigen_entry)) - RegisterSignal(target, COMSIG_ATOM_TOOL_ACT(TOOL_WELDER), PROC_REF(tool_interact)) + if(!subtle) + RegisterSignal(target, COMSIG_ATOM_TOOL_ACT(TOOL_WELDER), PROC_REF(tool_interact)) target.RegisterSignal(target, COMSIG_EIGENSTATE_ACTIVATE, TYPE_PROC_REF(/obj/structure/closet,bust_open)) ADD_TRAIT(target, TRAIT_BANNED_FROM_CARGO_SHUTTLE, REF(src)) - var/obj/item = target - if(item) - item.color = COLOR_PERIWINKLEE //Tint the locker slightly. - item.alpha = 200 - do_sparks(3, FALSE, item) + if(!subtle) + target.add_atom_colour(COLOR_PERIWINKLEE, FIXED_COLOUR_PRIORITY) //Tint the locker slightly. + target.alpha = 200 + do_sparks(3, FALSE, target) visible_atom.visible_message("The items shimmer and fizzle, turning a shade of violet blue.") id_counter++ return TRUE ///reverts everything back to start -/datum/controller/subsystem/eigenstates/Destroy() +/datum/eigenstate_manager/eigenstates/Destroy() for(var/index in 1 to id_counter) for(var/entry in eigen_targets["[index]"]) remove_eigen_entry(entry) @@ -63,12 +67,12 @@ SUBSYSTEM_DEF(eigenstates) return ..() ///removes an object reference from the master list -/datum/controller/subsystem/eigenstates/proc/remove_eigen_entry(atom/entry) +/datum/eigenstate_manager/proc/remove_eigen_entry(atom/entry) SIGNAL_HANDLER var/id = eigen_id[entry] eigen_targets[id] -= entry eigen_id -= entry - entry.color = COLOR_WHITE + entry.remove_atom_colour(FIXED_COLOUR_PRIORITY, COLOR_PERIWINKLEE) entry.alpha = 255 UnregisterSignal(entry, list( COMSIG_QDELETING, @@ -83,13 +87,14 @@ SUBSYSTEM_DEF(eigenstates) eigen_targets -= targets ///Finds the object within the master list, then sends the thing to the object's location -/datum/controller/subsystem/eigenstates/proc/use_eigenlinked_atom(atom/object_sent_from, atom/movable/thing_to_send) +/datum/eigenstate_manager/proc/use_eigenlinked_atom(atom/object_sent_from, atom/movable/thing_to_send) SIGNAL_HANDLER var/id = eigen_id[object_sent_from] if(!id) stack_trace("[object_sent_from] attempted to eigenlink to something that didn't have a valid id!") return FALSE + var/subtle = findtext(id, "subtle") var/list/items = eigen_targets[id] var/index = (items.Find(object_sent_from))+1 //index + 1 if(!index) @@ -104,19 +109,21 @@ SUBSYSTEM_DEF(eigenstates) if(check_teleport_valid(thing_to_send, eigen_target, TELEPORT_CHANNEL_EIGENSTATE)) thing_to_send.forceMove(get_turf(eigen_target)) else - object_sent_from.balloon_alert(thing_to_send, "nothing happens!") + if(!subtle) + object_sent_from.balloon_alert(thing_to_send, "nothing happens!") return FALSE //Create ONE set of sparks for ALL times in iteration - if(spark_time != world.time) + if(!subtle && spark_time != world.time) do_sparks(5, FALSE, eigen_target) do_sparks(5, FALSE, object_sent_from) - spark_time = world.time + spark_time = world.time //Calls a special proc for the atom if needed (closets use bust_open()) SEND_SIGNAL(eigen_target, COMSIG_EIGENSTATE_ACTIVATE) - return COMPONENT_CLOSET_INSERT_INTERRUPT + if(!subtle) + return COMPONENT_CLOSET_INSERT_INTERRUPT ///Prevents tool use on the item -/datum/controller/subsystem/eigenstates/proc/tool_interact(atom/source, mob/user, obj/item/item) +/datum/eigenstate_manager/proc/tool_interact(atom/source, mob/user, obj/item/item) SIGNAL_HANDLER to_chat(user, span_notice("The unstable nature of [source] makes it impossible to use [item] on [source.p_them()]!")) return ITEM_INTERACT_BLOCKING diff --git a/code/datums/elements/basic_body_temp_sensitive.dm b/code/datums/elements/basic_body_temp_sensitive.dm index 8e11ed92575ea03..8bb1cae854631ed 100644 --- a/code/datums/elements/basic_body_temp_sensitive.dm +++ b/code/datums/elements/basic_body_temp_sensitive.dm @@ -47,14 +47,15 @@ if(basic_mob.bodytemperature < min_body_temp) basic_mob.adjust_health(cold_damage * seconds_per_tick) - switch(cold_damage) - if(1 to 5) - basic_mob.throw_alert(ALERT_TEMPERATURE, /atom/movable/screen/alert/cold, 1) - if(5 to 10) - basic_mob.throw_alert(ALERT_TEMPERATURE, /atom/movable/screen/alert/cold, 2) - if(10 to INFINITY) - basic_mob.throw_alert(ALERT_TEMPERATURE, /atom/movable/screen/alert/cold, 3) - gave_alert = TRUE + if(!basic_mob.has_status_effect(/datum/status_effect/inebriated)) + switch(cold_damage) + if(1 to 5) + basic_mob.throw_alert(ALERT_TEMPERATURE, /atom/movable/screen/alert/cold, 1) + if(5 to 10) + basic_mob.throw_alert(ALERT_TEMPERATURE, /atom/movable/screen/alert/cold, 2) + if(10 to INFINITY) + basic_mob.throw_alert(ALERT_TEMPERATURE, /atom/movable/screen/alert/cold, 3) + gave_alert = TRUE else if(basic_mob.bodytemperature > max_body_temp) basic_mob.adjust_health(heat_damage * seconds_per_tick) diff --git a/code/datums/elements/bed_tucking.dm b/code/datums/elements/bed_tucking.dm index 70b10d4a58c0cc5..58f5640c31c75e9 100644 --- a/code/datums/elements/bed_tucking.dm +++ b/code/datums/elements/bed_tucking.dm @@ -1,7 +1,7 @@ /// Tucking element, for things that can be tucked into bed. /datum/element/bed_tuckable element_flags = ELEMENT_BESPOKE - argument_hash_start_idx = 2 + argument_hash_start_idx = 3 /// our pixel_x offset - how much the item moves x when in bed (+x is closer to the pillow) var/x_offset = 0 /// our pixel_y offset - how much the item move y when in bed (-y is closer to the middle) @@ -11,7 +11,7 @@ /// our starting angle for the item var/starting_angle = 0 -/datum/element/bed_tuckable/Attach(obj/target, x = 0, y = 0, rotation = 0) +/datum/element/bed_tuckable/Attach(obj/target, mapload = FALSE, x = 0, y = 0, rotation = 0) . = ..() if(!isitem(target)) return ELEMENT_INCOMPATIBLE @@ -20,6 +20,13 @@ y_offset = y starting_angle = rotation RegisterSignal(target, COMSIG_ITEM_ATTACK_ATOM, PROC_REF(tuck_into_bed)) + if(!mapload) + return + var/turf/our_home = get_turf(target) + var/obj/structure/bed/eepy = locate(/obj/structure/bed) in our_home + if(isnull(eepy)) + return + tuck(target, eepy) /datum/element/bed_tuckable/Detach(obj/target) . = ..() @@ -42,6 +49,10 @@ return to_chat(tucker, span_notice("You lay [tucked] out on [target_bed].")) + tuck(tucked, target_bed) + return COMPONENT_NO_AFTERATTACK + +/datum/element/bed_tuckable/proc/tuck(obj/item/tucked, obj/structure/bed/target_bed) tucked.dir = target_bed.dir tucked.pixel_x = target_bed.dir & EAST ? -x_offset : x_offset tucked.pixel_y = y_offset @@ -50,8 +61,6 @@ tucked.transform = turn(tucked.transform, rotation_degree) RegisterSignal(tucked, COMSIG_ITEM_PICKUP, PROC_REF(untuck)) - return COMPONENT_NO_AFTERATTACK - /** * If we rotate our object, then we need to un-rotate it when it's picked up * diff --git a/code/datums/elements/shatters_when_thrown.dm b/code/datums/elements/can_shatter.dm similarity index 69% rename from code/datums/elements/shatters_when_thrown.dm rename to code/datums/elements/can_shatter.dm index cbb5994852c810d..73b025ad83c0839 100644 --- a/code/datums/elements/shatters_when_thrown.dm +++ b/code/datums/elements/can_shatter.dm @@ -1,7 +1,8 @@ /** * When attached to something, will make that thing shatter into shards on throw impact or z level falling + * Or even when used as a weapon if the 'shatters_as_weapon' arg is TRUE */ -/datum/element/shatters_when_thrown +/datum/element/can_shatter element_flags = ELEMENT_BESPOKE argument_hash_start_idx = 2 @@ -12,7 +13,12 @@ /// What sound plays when the thing we're attached to shatters var/shattering_sound -/datum/element/shatters_when_thrown/Attach(datum/target, shard_type = /obj/item/plate_shard, number_of_shards = 5, shattering_sound = 'sound/items/ceramic_break.ogg') +/datum/element/can_shatter/Attach(datum/target, + shard_type = /obj/item/plate_shard, + number_of_shards = 5, + shattering_sound = 'sound/items/ceramic_break.ogg', + shatters_as_weapon = FALSE, + ) . = ..() if(!ismovable(target)) @@ -24,26 +30,28 @@ RegisterSignal(target, COMSIG_MOVABLE_IMPACT, PROC_REF(on_throw_impact)) RegisterSignal(target, COMSIG_ATOM_ON_Z_IMPACT, PROC_REF(on_z_impact)) + if(shatters_as_weapon) + RegisterSignal(target, COMSIG_ITEM_POST_ATTACK_ATOM, PROC_REF(on_post_attack_atom)) -/datum/element/shatters_when_thrown/Detach(datum/target) +/datum/element/can_shatter/Detach(datum/target) . = ..() UnregisterSignal(target, list(COMSIG_MOVABLE_IMPACT, COMSIG_ATOM_ON_Z_IMPACT)) /// Tells the parent to shatter if we impact a lower zlevel -/datum/element/shatters_when_thrown/proc/on_z_impact(datum/source, turf/impacted_turf, levels) +/datum/element/can_shatter/proc/on_z_impact(datum/source, turf/impacted_turf, levels) SIGNAL_HANDLER shatter(source, impacted_turf) /// Tells the parent to shatter if we are thrown and impact something -/datum/element/shatters_when_thrown/proc/on_throw_impact(datum/source, atom/hit_atom) +/datum/element/can_shatter/proc/on_throw_impact(datum/source, atom/hit_atom) SIGNAL_HANDLER shatter(source, hit_atom) /// Handles the actual shattering part, throwing shards of whatever is defined on the component everywhere -/datum/element/shatters_when_thrown/proc/shatter(atom/movable/source, atom/hit_atom) +/datum/element/can_shatter/proc/shatter(atom/movable/source, atom/hit_atom) var/generator/scatter_gen = generator(GEN_CIRCLE, 0, 48, NORMAL_RAND) var/scatter_turf = get_turf(hit_atom) @@ -64,3 +72,7 @@ return else qdel(source) + +/datum/element/can_shatter/proc/on_post_attack_atom(obj/item/source, atom/attacked_atom, mob/living/user) + SIGNAL_HANDLER + shatter(source, attacked_atom) diff --git a/code/datums/elements/elevation.dm b/code/datums/elements/elevation.dm index ffa6de398b6e483..92fba97a09414d2 100644 --- a/code/datums/elements/elevation.dm +++ b/code/datums/elements/elevation.dm @@ -113,6 +113,8 @@ for(var/mob/living/living in target) ADD_TRAIT(living, TRAIT_ON_ELEVATED_SURFACE, REF(src)) RegisterSignal(living, COMSIG_LIVING_SET_BUCKLED, PROC_REF(on_set_buckled)) + RegisterSignal(living, SIGNAL_ADDTRAIT(TRAIT_IGNORE_ELEVATION), PROC_REF(on_ignore_elevation_add)) + RegisterSignal(living, SIGNAL_REMOVETRAIT(TRAIT_IGNORE_ELEVATION), PROC_REF(on_ignore_elevation_remove)) elevate_mob(living) /datum/element/elevation_core/Detach(datum/source) @@ -133,7 +135,7 @@ continue REMOVE_TRAIT(living, TRAIT_ON_ELEVATED_SURFACE, REF(src)) elevate_mob(living, -pixel_shift) - UnregisterSignal(living, COMSIG_LIVING_SET_BUCKLED) + UnregisterSignal(living, list(COMSIG_LIVING_SET_BUCKLED, SIGNAL_ADDTRAIT(TRAIT_IGNORE_ELEVATION), SIGNAL_REMOVETRAIT(TRAIT_IGNORE_ELEVATION))) return ..() /datum/element/elevation_core/proc/on_entered(turf/source, atom/movable/entered, atom/old_loc) @@ -143,6 +145,8 @@ var/elevate_time = isturf(old_loc) && source.Adjacent(old_loc) ? ELEVATE_TIME : 0 elevate_mob(entered, elevate_time = elevate_time) RegisterSignal(entered, COMSIG_LIVING_SET_BUCKLED, PROC_REF(on_set_buckled)) + RegisterSignal(entered, SIGNAL_ADDTRAIT(TRAIT_IGNORE_ELEVATION), PROC_REF(on_ignore_elevation_add)) + RegisterSignal(entered, SIGNAL_REMOVETRAIT(TRAIT_IGNORE_ELEVATION), PROC_REF(on_ignore_elevation_remove)) /datum/element/elevation_core/proc/on_initialized_on(turf/source, atom/movable/spawned) SIGNAL_HANDLER @@ -152,15 +156,17 @@ /datum/element/elevation_core/proc/on_exited(turf/source, atom/movable/gone) SIGNAL_HANDLER if((isnull(gone.loc) || !HAS_TRAIT_FROM(gone.loc, TRAIT_ELEVATED_TURF, REF(src))) && isliving(gone)) - // Always unregister the signal, we're still leaving even if already shifted down. - UnregisterSignal(gone, COMSIG_LIVING_SET_BUCKLED) + // Always unregister the signals, we're still leaving even if not affected by elevation. + UnregisterSignal(gone, list(COMSIG_LIVING_SET_BUCKLED, SIGNAL_ADDTRAIT(TRAIT_IGNORE_ELEVATION), SIGNAL_REMOVETRAIT(TRAIT_IGNORE_ELEVATION))) if(!HAS_TRAIT_FROM(gone, TRAIT_ON_ELEVATED_SURFACE, REF(src))) return REMOVE_TRAIT(gone, TRAIT_ON_ELEVATED_SURFACE, REF(src)) var/elevate_time = isturf(gone.loc) && source.Adjacent(gone.loc) ? ELEVATE_TIME : 0 elevate_mob(gone, -pixel_shift, elevate_time) -/datum/element/elevation_core/proc/elevate_mob(mob/living/target, z_shift = pixel_shift, elevate_time = ELEVATE_TIME) +/datum/element/elevation_core/proc/elevate_mob(mob/living/target, z_shift = pixel_shift, elevate_time = ELEVATE_TIME, force = FALSE) + if(HAS_TRAIT(target, TRAIT_IGNORE_ELEVATION) && !force) + return var/buckled_to_vehicle = FALSE if(target.buckled) if(isvehicle(target.buckled)) @@ -181,6 +187,8 @@ */ /datum/element/elevation_core/proc/on_set_buckled(mob/living/source, atom/movable/new_buckled) SIGNAL_HANDLER + if(HAS_TRAIT(source, TRAIT_IGNORE_ELEVATION)) + return if(source.buckled) if(isvehicle(source.buckled)) animate(source.buckled, pixel_z = -pixel_shift, time = ELEVATE_TIME, flags = ANIMATION_RELATIVE|ANIMATION_PARALLEL) @@ -193,6 +201,14 @@ else if(!isliving(new_buckled)) animate(source, pixel_z = -pixel_shift, time = ELEVATE_TIME, flags = ANIMATION_RELATIVE|ANIMATION_PARALLEL) +/datum/element/elevation_core/proc/on_ignore_elevation_add(mob/living/source, trait) + SIGNAL_HANDLER + elevate_mob(source, -pixel_shift, force = TRUE) + +/datum/element/elevation_core/proc/on_ignore_elevation_remove(mob/living/source, trait) + SIGNAL_HANDLER + elevate_mob(source, pixel_shift) + /datum/element/elevation_core/proc/on_reset_elevation(turf/source, list/current_values) SIGNAL_HANDLER current_values[ELEVATION_CURRENT_PIXEL_SHIFT] = pixel_shift diff --git a/code/datums/elements/food/grilled_item.dm b/code/datums/elements/food/grilled_item.dm index f657b969f062ea7..de6c2ef41c1b915 100644 --- a/code/datums/elements/food/grilled_item.dm +++ b/code/datums/elements/food/grilled_item.dm @@ -9,30 +9,27 @@ var/atom/this_food = target switch(grill_time) //no 0-20 to prevent spam - if(20 to 30) + if(20 SECONDS to 30 SECONDS) this_food.name = "lightly-grilled [this_food.name]" this_food.desc += " It's been lightly grilled." - if(30 to 80) + if(30 SECONDS to 80 SECONDS) this_food.name = "grilled [this_food.name]" this_food.desc += " It's been grilled." - if(80 to 100) + if(80 SECONDS to 100 SECONDS) this_food.name = "heavily grilled [this_food.name]" this_food.desc += " It's been heavily grilled." - if(100 to INFINITY) //grill marks reach max alpha + if(100 SECONDS to INFINITY) //grill marks reach max alpha this_food.name = "Powerfully Grilled [this_food.name]" this_food.desc = "A [this_food.name]. Reminds you of your wife, wait, no, it's prettier!" - if(grill_time > 20) - ADD_TRAIT(this_food, TRAIT_FOOD_GRILLED, ELEMENT_TRAIT(type)) - if(grill_time > 30) + if(grill_time > 30 SECONDS && isnull(this_food.GetComponent(/datum/component/edible))) this_food.AddComponent(/datum/component/edible, foodtypes = FRIED) /datum/element/grilled_item/Detach(atom/source, ...) source.name = initial(source.name) source.desc = initial(source.desc) - REMOVE_TRAIT(source, TRAIT_FOOD_GRILLED, ELEMENT_TRAIT(type)) qdel(source.GetComponent(/datum/component/edible)) // Don't care if it was initially edible return ..() diff --git a/code/datums/elements/frozen.dm b/code/datums/elements/frozen.dm index b88cc2afa224009..434968dd4d5e0f2 100644 --- a/code/datums/elements/frozen.dm +++ b/code/datums/elements/frozen.dm @@ -55,9 +55,13 @@ GLOBAL_LIST_INIT(freon_color_matrix, list("#2E5E69", "#60A2A8", "#A1AFB1", rgb(0 Detach(source) ///signal handler for COMSIG_MOVABLE_POST_THROW that shatters our target after impacting after a throw -/datum/element/frozen/proc/shatter_on_throw(datum/target) +/datum/element/frozen/proc/shatter_on_throw(datum/target, datum/thrownthing/throwingdatum) SIGNAL_HANDLER var/obj/obj_target = target + if(ismob(throwingdatum.thrower)) + log_combat(throwingdatum.thrower, target, "shattered", addition = "from being thrown due to [target] being frozen.") + else + log_combat(throwingdatum.thrower, target, "launched", addition = "shattering it due to being frozen.") obj_target.visible_message(span_danger("[obj_target] shatters into a million pieces!")) obj_target.obj_flags |= NO_DECONSTRUCTION // disable item spawning obj_target.deconstruct(FALSE) // call pre-deletion specialized code -- internals release gas etc diff --git a/code/datums/elements/inverted_movement.dm b/code/datums/elements/inverted_movement.dm new file mode 100644 index 000000000000000..537e7343893e75c --- /dev/null +++ b/code/datums/elements/inverted_movement.dm @@ -0,0 +1,14 @@ +/datum/element/inverted_movement + +/datum/element/inverted_movement/Attach(datum/target) + . = ..() + if(!isliving(target)) + return ELEMENT_INCOMPATIBLE + RegisterSignal(target, COMSIG_MOB_CLIENT_PRE_MOVE, PROC_REF(invert_movement)) + +/datum/element/inverted_movement/Detach(datum/source) + UnregisterSignal(source, COMSIG_MOB_CLIENT_PRE_MOVE) + return ..() + +/datum/element/inverted_movement/proc/invert_movement(mob/living/source, move_args) + move_args[MOVE_ARG_DIRECTION] = REVERSE_DIR(move_args[MOVE_ARG_DIRECTION]) diff --git a/code/datums/elements/sticker.dm b/code/datums/elements/sticker.dm deleted file mode 100644 index 3cc8e977daf20f0..000000000000000 --- a/code/datums/elements/sticker.dm +++ /dev/null @@ -1,53 +0,0 @@ -#define MAX_ALLOWED_STICKERS 12 - -/datum/element/sticker - ///The typepath for our attached sticker component - var/stick_type = /datum/component/attached_sticker - ///If TRUE, our attached_sticker can be washed off - var/washable = TRUE - -/datum/element/sticker/Attach(datum/target, sticker_type, cleanable=TRUE) - . = ..() - if(!isitem(target)) - return ELEMENT_INCOMPATIBLE - RegisterSignal(target, COMSIG_ITEM_AFTERATTACK, PROC_REF(on_afterattack)) - RegisterSignal(target, COMSIG_MOVABLE_IMPACT, PROC_REF(on_throw_impact)) - if(sticker_type) - stick_type = sticker_type - washable = cleanable - -/datum/element/sticker/Detach(datum/source) - . = ..() - UnregisterSignal(source, list(COMSIG_ITEM_AFTERATTACK, COMSIG_MOVABLE_IMPACT)) - -/datum/element/sticker/proc/on_afterattack(obj/item/source, atom/target, mob/living/user, prox, params) - SIGNAL_HANDLER - if(!prox) - return - if(!isatom(target)) - return - var/list/parameters = params2list(params) - if(!LAZYACCESS(parameters, ICON_X) || !LAZYACCESS(parameters, ICON_Y)) - return - var/divided_size = world.icon_size / 2 - var/px = text2num(LAZYACCESS(parameters, ICON_X)) - divided_size - var/py = text2num(LAZYACCESS(parameters, ICON_Y)) - divided_size - - user.do_attack_animation(target) - if(do_stick(source, target, user, px, py)) - target.balloon_alert_to_viewers("sticker sticked") - -///Add our stick_type to the target with px and py as pixel x and pixel y respectively -/datum/element/sticker/proc/do_stick(obj/item/source, atom/target, mob/living/user, px, py) - if(COUNT_TRAIT_SOURCES(target, TRAIT_STICKERED) >= MAX_ALLOWED_STICKERS) - source.balloon_alert_to_viewers("sticker won't stick!") - return FALSE - target.AddComponent(stick_type, px, py, source, user, washable) - return TRUE - -/datum/element/sticker/proc/on_throw_impact(obj/item/source, atom/hit_atom, datum/thrownthing/throwingdatum) - SIGNAL_HANDLER - if(prob(50) && do_stick(source, hit_atom, null, rand(-7,7), rand(-7,7))) - hit_atom.balloon_alert_to_viewers("sticker landed on sticky side!") - -#undef MAX_ALLOWED_STICKERS diff --git a/code/datums/greyscale/config_types/greyscale_configs/greyscale_items.dm b/code/datums/greyscale/config_types/greyscale_configs/greyscale_items.dm index 28433ba9064b6fe..6b9465bf46af077 100644 --- a/code/datums/greyscale/config_types/greyscale_configs/greyscale_items.dm +++ b/code/datums/greyscale/config_types/greyscale_configs/greyscale_items.dm @@ -335,3 +335,8 @@ name = "Flower Worn" icon_file = 'icons/mob/clothing/head/hydroponics.dmi' json_config = 'code/datums/greyscale/json_configs/simple_flower_worn.json' + +/datum/greyscale_config/piggy_bank + name = "Piggy Bank" + icon_file = 'icons/obj/fluff/general.dmi' + json_config = 'code/datums/greyscale/json_configs/piggy_bank.json' diff --git a/code/datums/greyscale/json_configs/piggy_bank.json b/code/datums/greyscale/json_configs/piggy_bank.json new file mode 100644 index 000000000000000..71876213e197f59 --- /dev/null +++ b/code/datums/greyscale/json_configs/piggy_bank.json @@ -0,0 +1,10 @@ +{ + "piggy_bank": [ + { + "type": "icon_state", + "icon_state": "piggy_bank", + "blend_mode": "overlay", + "color_ids": [ 1 ] + } + ] +} diff --git a/code/datums/id_trim/jobs.dm b/code/datums/id_trim/jobs.dm index ea46cc91319fa9a..46f691564bb4bc9 100644 --- a/code/datums/id_trim/jobs.dm +++ b/code/datums/id_trim/jobs.dm @@ -1183,6 +1183,36 @@ ) job = /datum/job/station_engineer +/datum/id_trim/job/veteran_advisor + assignment = "Veteran Security Advisor" + trim_state = "trim_veteranadvisor" + department_color = COLOR_SECURITY_RED + subdepartment_color = COLOR_COMMAND_BLUE + sechud_icon_state = SECHUD_VETERAN_ADVISOR + minimal_access = list( + ACCESS_COMMAND, + ACCESS_BRIG, + ACCESS_BRIG_ENTRANCE, + ACCESS_COURT, + ACCESS_MECH_SECURITY, + ACCESS_MINERAL_STOREROOM, + ACCESS_SECURITY, + ACCESS_WEAPONS, + ) + extra_access = list() + template_access = list() + job = /datum/job/veteran_advisor + +/datum/id_trim/job/veteran_advisor/refresh_trim_access() + . = ..() + + if(!.) + return + + // Config check for if sec has maint access. + if(CONFIG_GET(flag/security_has_maint_access)) + access |= list(ACCESS_MAINT_TUNNELS) + /datum/id_trim/job/virologist assignment = "Virologist" trim_state = "trim_virologist" diff --git a/code/datums/materials/basemats.dm b/code/datums/materials/basemats.dm index 3c5f6ab62d0cb1b..e2897a772e530c5 100644 --- a/code/datums/materials/basemats.dm +++ b/code/datums/materials/basemats.dm @@ -4,7 +4,7 @@ desc = "Common iron ore often found in sedimentary and igneous layers of the crust." color = "#878687" greyscale_colors = "#878687" - categories = list(MAT_CATEGORY_ORE = TRUE, MAT_CATEGORY_RIGID = TRUE, MAT_CATEGORY_BASE_RECIPES = TRUE, MAT_CATEGORY_ITEM_MATERIAL=TRUE) + categories = list(MAT_CATEGORY_SILO = TRUE, MAT_CATEGORY_RIGID = TRUE, MAT_CATEGORY_BASE_RECIPES = TRUE, MAT_CATEGORY_ITEM_MATERIAL=TRUE) sheet_type = /obj/item/stack/sheet/iron ore_type = /obj/item/stack/ore/iron value_per_unit = 5 / SHEET_MATERIAL_AMOUNT @@ -25,10 +25,10 @@ color = "#88cdf1" greyscale_colors = "#88cdf196" alpha = 150 - categories = list(MAT_CATEGORY_RIGID = TRUE, MAT_CATEGORY_BASE_RECIPES = TRUE, MAT_CATEGORY_ITEM_MATERIAL=TRUE) + categories = list(MAT_CATEGORY_SILO = TRUE, MAT_CATEGORY_RIGID = TRUE, MAT_CATEGORY_BASE_RECIPES = TRUE, MAT_CATEGORY_ITEM_MATERIAL=TRUE) integrity_modifier = 0.1 sheet_type = /obj/item/stack/sheet/glass - ore_type = /obj/item/stack/ore/glass + ore_type = /obj/item/stack/ore/glass/basalt shard_type = /obj/item/shard debris_type = /obj/effect/decal/cleanable/glass value_per_unit = 5 / SHEET_MATERIAL_AMOUNT @@ -47,12 +47,12 @@ /datum/material/glass/on_applied_obj(atom/source, amount, material_flags) . = ..() if(!isstack(source)) - source.AddElement(/datum/element/shatters_when_thrown, shard_type, round(amount / SHEET_MATERIAL_AMOUNT), SFX_SHATTER) + source.AddElement(/datum/element/can_shatter, shard_type, round(amount / SHEET_MATERIAL_AMOUNT), SFX_SHATTER) /datum/material/glass/on_removed(atom/source, amount, material_flags) . = ..() - source.RemoveElement(/datum/element/shatters_when_thrown, shard_type) + source.RemoveElement(/datum/element/can_shatter, shard_type) /* Color matrices are like regular colors but unlike with normal colors, you can go over 255 on a channel. @@ -65,7 +65,7 @@ Unless you know what you're doing, only use the first three numbers. They're in desc = "Silver" color = list(255/255, 284/255, 302/255,0, 0,0,0,0, 0,0,0,0, 0,0,0,1, 0,0,0,0) greyscale_colors = "#e3f1f8" - categories = list(MAT_CATEGORY_ORE = TRUE, MAT_CATEGORY_RIGID = TRUE, MAT_CATEGORY_BASE_RECIPES = TRUE, MAT_CATEGORY_ITEM_MATERIAL=TRUE) + categories = list(MAT_CATEGORY_SILO = TRUE, MAT_CATEGORY_RIGID = TRUE, MAT_CATEGORY_BASE_RECIPES = TRUE, MAT_CATEGORY_ITEM_MATERIAL=TRUE) sheet_type = /obj/item/stack/sheet/mineral/silver ore_type = /obj/item/stack/ore/silver value_per_unit = 50 / SHEET_MATERIAL_AMOUNT @@ -86,7 +86,7 @@ Unless you know what you're doing, only use the first three numbers. They're in color = list(340/255, 240/255, 50/255,0, 0,0,0,0, 0,0,0,0, 0,0,0,1, 0,0,0,0) //gold is shiny, but not as bright as bananium greyscale_colors = "#dbdd4c" strength_modifier = 1.2 - categories = list(MAT_CATEGORY_ORE = TRUE, MAT_CATEGORY_RIGID = TRUE, MAT_CATEGORY_BASE_RECIPES = TRUE, MAT_CATEGORY_ITEM_MATERIAL=TRUE) + categories = list(MAT_CATEGORY_SILO = TRUE, MAT_CATEGORY_RIGID = TRUE, MAT_CATEGORY_BASE_RECIPES = TRUE, MAT_CATEGORY_ITEM_MATERIAL=TRUE) sheet_type = /obj/item/stack/sheet/mineral/gold ore_type = /obj/item/stack/ore/gold value_per_unit = 125 / SHEET_MATERIAL_AMOUNT @@ -107,7 +107,7 @@ Unless you know what you're doing, only use the first three numbers. They're in desc = "Highly pressurized carbon" color = list(48/255, 272/255, 301/255,0, 0,0,0,0, 0,0,0,0, 0,0,0,1, 0,0,0,0) greyscale_colors = "#71c8f784" - categories = list(MAT_CATEGORY_ORE = TRUE, MAT_CATEGORY_RIGID = TRUE, MAT_CATEGORY_BASE_RECIPES = TRUE, MAT_CATEGORY_ITEM_MATERIAL=TRUE) + categories = list(MAT_CATEGORY_SILO = TRUE, MAT_CATEGORY_RIGID = TRUE, MAT_CATEGORY_BASE_RECIPES = TRUE, MAT_CATEGORY_ITEM_MATERIAL=TRUE) sheet_type = /obj/item/stack/sheet/mineral/diamond ore_type = /obj/item/stack/ore/diamond alpha = 132 @@ -130,7 +130,7 @@ Unless you know what you're doing, only use the first three numbers. They're in desc = "Uranium" color = rgb(48, 237, 26) greyscale_colors = rgb(48, 237, 26) - categories = list(MAT_CATEGORY_ORE = TRUE, MAT_CATEGORY_RIGID = TRUE, MAT_CATEGORY_BASE_RECIPES = TRUE, MAT_CATEGORY_ITEM_MATERIAL=TRUE) + categories = list(MAT_CATEGORY_SILO = TRUE, MAT_CATEGORY_RIGID = TRUE, MAT_CATEGORY_BASE_RECIPES = TRUE, MAT_CATEGORY_ITEM_MATERIAL=TRUE) sheet_type = /obj/item/stack/sheet/mineral/uranium ore_type = /obj/item/stack/ore/uranium value_per_unit = 100 / SHEET_MATERIAL_AMOUNT @@ -170,7 +170,7 @@ Unless you know what you're doing, only use the first three numbers. They're in desc = "Isn't plasma a state of matter? Oh whatever." color = list(298/255, 46/255, 352/255,0, 0,0,0,0, 0,0,0,0, 0,0,0,1, 0,0,0,0) greyscale_colors = "#c162ec" - categories = list(MAT_CATEGORY_ORE = TRUE, MAT_CATEGORY_RIGID = TRUE, MAT_CATEGORY_BASE_RECIPES = TRUE, MAT_CATEGORY_ITEM_MATERIAL=TRUE) + categories = list(MAT_CATEGORY_SILO = TRUE, MAT_CATEGORY_RIGID = TRUE, MAT_CATEGORY_BASE_RECIPES = TRUE, MAT_CATEGORY_ITEM_MATERIAL=TRUE) sheet_type = /obj/item/stack/sheet/mineral/plasma ore_type = /obj/item/stack/ore/plasma value_per_unit = 200 / SHEET_MATERIAL_AMOUNT @@ -204,7 +204,7 @@ Unless you know what you're doing, only use the first three numbers. They're in greyscale_colors = "#4e7dffC8" alpha = 200 starlight_color = COLOR_BLUE - categories = list(MAT_CATEGORY_ORE = TRUE, MAT_CATEGORY_ITEM_MATERIAL = TRUE) + categories = list(MAT_CATEGORY_SILO = TRUE, MAT_CATEGORY_ITEM_MATERIAL = TRUE) beauty_modifier = 0.5 sheet_type = /obj/item/stack/sheet/bluespace_crystal ore_type = /obj/item/stack/ore/bluespace_crystal @@ -225,7 +225,7 @@ Unless you know what you're doing, only use the first three numbers. They're in desc = "Material with hilarious properties" color = list(460/255, 464/255, 0, 0, 0,0,0,0, 0,0,0,0, 0,0,0,1, 0,0,0,0) //obnoxiously bright yellow greyscale_colors = "#ffff00" - categories = list(MAT_CATEGORY_ORE = TRUE, MAT_CATEGORY_RIGID = TRUE, MAT_CATEGORY_BASE_RECIPES = TRUE, MAT_CATEGORY_ITEM_MATERIAL=TRUE) + categories = list(MAT_CATEGORY_SILO = TRUE, MAT_CATEGORY_RIGID = TRUE, MAT_CATEGORY_BASE_RECIPES = TRUE, MAT_CATEGORY_ITEM_MATERIAL=TRUE) sheet_type = /obj/item/stack/sheet/mineral/bananium ore_type = /obj/item/stack/ore/bananium value_per_unit = 1000 / SHEET_MATERIAL_AMOUNT @@ -256,7 +256,7 @@ Unless you know what you're doing, only use the first three numbers. They're in color = "#b3c0c7" greyscale_colors = "#b3c0c7" strength_modifier = 1.3 - categories = list(MAT_CATEGORY_ORE = TRUE, MAT_CATEGORY_RIGID = TRUE, MAT_CATEGORY_BASE_RECIPES = TRUE, MAT_CATEGORY_ITEM_MATERIAL=TRUE) + categories = list(MAT_CATEGORY_SILO = TRUE, MAT_CATEGORY_RIGID = TRUE, MAT_CATEGORY_BASE_RECIPES = TRUE, MAT_CATEGORY_ITEM_MATERIAL=TRUE) sheet_type = /obj/item/stack/sheet/mineral/titanium ore_type = /obj/item/stack/ore/titanium value_per_unit = 125 / SHEET_MATERIAL_AMOUNT @@ -297,7 +297,7 @@ Unless you know what you're doing, only use the first three numbers. They're in strength_modifier = 0.85 sheet_type = /obj/item/stack/sheet/plastic ore_type = /obj/item/stack/ore/slag //No plastic or coal ore, so we use slag. - categories = list(MAT_CATEGORY_RIGID = TRUE, MAT_CATEGORY_BASE_RECIPES = TRUE, MAT_CATEGORY_ITEM_MATERIAL=TRUE) + categories = list(MAT_CATEGORY_SILO = TRUE, MAT_CATEGORY_RIGID = TRUE, MAT_CATEGORY_BASE_RECIPES = TRUE, MAT_CATEGORY_ITEM_MATERIAL=TRUE) value_per_unit = 25 / SHEET_MATERIAL_AMOUNT beauty_modifier = -0.01 armor_modifiers = list(MELEE = 1.5, BULLET = 1.1, LASER = 0.3, ENERGY = 0.5, BOMB = 1, BIO = 1, FIRE = 1.1, ACID = 1) diff --git a/code/datums/mood_events/eldritch_painting_events.dm b/code/datums/mood_events/eldritch_painting_events.dm index 7df89104263bace..df801998c1d9836 100644 --- a/code/datums/mood_events/eldritch_painting_events.dm +++ b/code/datums/mood_events/eldritch_painting_events.dm @@ -17,13 +17,13 @@ mood_change = 5 timeout = 3 MINUTES -/datum/mood_event/eldritch_painting/weeping_withdrawl +/datum/mood_event/eldritch_painting/weeping_withdrawal description = "My mind is clear from his influence." mood_change = 1 timeout = 3 MINUTES /datum/mood_event/eldritch_painting/desire_heretic - description = "A part gained, the manus takes and gives. What did it take from me?" + description = "A part gained, the mansus takes and gives. What did it take from me?" mood_change = -2 timeout = 3 MINUTES diff --git a/code/datums/mood_events/generic_negative_events.dm b/code/datums/mood_events/generic_negative_events.dm index 32b9772dc0709de..0cfb48f7a9823dc 100644 --- a/code/datums/mood_events/generic_negative_events.dm +++ b/code/datums/mood_events/generic_negative_events.dm @@ -483,3 +483,9 @@ /datum/mood_event/all_nighter description = "I didn't sleep at all last night. I'm exhausted." mood_change = -5 + +//Used by the Veteran Advisor trait job +/datum/mood_event/desentized + description = "Nothing will ever rival with what I seen in the past..." + mood_change = -3 + special_screen_obj = "mood_desentized" diff --git a/code/datums/mutations/body.dm b/code/datums/mutations/body.dm index 38806aa7529dd95..035cf64db80504f 100644 --- a/code/datums/mutations/body.dm +++ b/code/datums/mutations/body.dm @@ -232,7 +232,7 @@ instability = 5 power_coeff = 1 conflicts = list(/datum/mutation/human/glow/anti) - var/glow_power = 2.5 + var/glow_power = 2 var/glow_range = 2.5 var/glow_color var/obj/effect/dummy/lighting_obj/moblight/glow diff --git a/code/datums/records/manifest.dm b/code/datums/records/manifest.dm index c13acad9f05311d..3a942325cbac6bc 100644 --- a/code/datums/records/manifest.dm +++ b/code/datums/records/manifest.dm @@ -111,7 +111,7 @@ GLOBAL_DATUM_INIT(manifest, /datum/manifest, new) person_gender = "Male" if(person.gender == "female") person_gender = "Female" - var/datum/dna/record_dna = new() + var/datum/dna/stored/record_dna = new() person.dna.copy_dna(record_dna) // SKYRAT EDIT ADDITION BEGIN - ALTERNATIVE_JOB_TITLES diff --git a/code/datums/ruins/lavaland.dm b/code/datums/ruins/lavaland.dm index f66d06a4bba6b9f..d10b477c083c245 100644 --- a/code/datums/ruins/lavaland.dm +++ b/code/datums/ruins/lavaland.dm @@ -29,6 +29,13 @@ description = "WELCOME TO CLOWN PLANET! HONK HONK HONK etc.!" suffix = "lavaland_biodome_clown_planet.dmm" +/datum/map_template/ruin/lavaland/lizgas + name = "The Lizard's Gas(Lava)" + id = "lizgas2" + description = "A recently opened gas station from the Lizard's Gas franchise." + suffix = "lavaland_surface_gas.dmm" + allow_duplicates = FALSE + /datum/map_template/ruin/lavaland/cube name = "The Wishgranter Cube" id = "wishgranter-cube" diff --git a/code/datums/station_traits/job_traits.dm b/code/datums/station_traits/job_traits.dm index 8ad478e6c83a9f6..c588475094be141 100644 --- a/code/datums/station_traits/job_traits.dm +++ b/code/datums/station_traits/job_traits.dm @@ -60,21 +60,18 @@ for (var/mob/dead/new_player/signee as anything in lobby_candidates) if (isnull(signee) || !signee.client || !signee.mind || signee.ready != PLAYER_READY_TO_PLAY) LAZYREMOVE(lobby_candidates, signee) - if (!LAZYLEN(lobby_candidates)) - on_failed_assignment() - return // Nobody signed up :( - for(var/_ in 1 to position_amount) + + var/datum/job/our_job = SSjob.GetJobType(job_to_add) + while(length(lobby_candidates) && position_amount > 0) var/mob/dead/new_player/picked_player = pick_n_take(lobby_candidates) - picked_player.mind.assigned_role = new job_to_add() - lobby_candidates = null + picked_player.mind.set_assigned_role(our_job) + position_amount-- -/// Called if we didn't assign a role before the round began, we add it to the latejoin menu instead -/datum/station_trait/job/proc/on_failed_assignment() - var/datum/job/our_job = SSjob.GetJob(job_to_add::title) - our_job.total_positions = position_amount + our_job.total_positions = max(0, position_amount) + lobby_candidates = null /datum/station_trait/job/can_display_lobby_button(client/player) - var/datum/job/our_job = SSjob.GetJob(job_to_add::title) + var/datum/job/our_job = SSjob.GetJobType(job_to_add) return our_job.player_old_enough(player) && ..() /// Adds a gorilla to the cargo department, replacing the sloth and the mech @@ -165,6 +162,21 @@ new /obj/item/reagent_containers/cup/coffeepot(picked_turf) new /obj/item/storage/box/coffeepack(picked_turf) +/datum/station_trait/job/veteran_advisor + name = "Veteran Advisor" + button_desc = "Sign up to become a DISABLED but hard boiled Veteran Advisor of Nanotrasen Security Force. Advise HoS and Captain, train Officers, all while fighting your PTSD." + weight = 2 + report_message = "Veteran Security Advisor has been assigned to your station to help with Security matters." + show_in_report = TRUE + can_roll_antag = CAN_ROLL_PROTECTED + job_to_add = /datum/job/veteran_advisor + +/* SKYRAT EDIT -- REMOVAL -- We handle the lobby a bit differently for time being +/datum/station_trait/job/veteran_advisor/on_lobby_button_update_overlays(atom/movable/screen/lobby/button/sign_up/lobby_button, list/overlays) + . = ..() + overlays += "veteran_advisor" +*/ + #undef CAN_ROLL_ALWAYS #undef CAN_ROLL_PROTECTED #undef CAN_ROLL_NEVER diff --git a/code/datums/station_traits/neutral_traits.dm b/code/datums/station_traits/neutral_traits.dm index f12f9bed8558046..905bfed2e8e4c62 100644 --- a/code/datums/station_traits/neutral_traits.dm +++ b/code/datums/station_traits/neutral_traits.dm @@ -362,6 +362,41 @@ show_in_report = TRUE report_message = "There sure are a lot of trees out there." +/datum/station_trait/linked_closets + name = "Closet Anomaly" + trait_type = STATION_TRAIT_NEUTRAL + show_in_report = TRUE + weight = 1 + report_message = "We've reports of high amount of trace eigenstasium on your station. Ensure that your closets are working correctly." + +/datum/station_trait/linked_closets/on_round_start() + . = ..() + var/list/roundstart_non_secure_closets = GLOB.roundstart_station_closets.Copy() + for(var/obj/structure/closet/closet in roundstart_non_secure_closets) + if(closet.secure) + roundstart_non_secure_closets -= closet + + /** + * The number of links to perform. + * Combined with 50/50 the probability of the link being triangular, the boundaries of any given + * on-station, non-secure closet being linked are as high as 1 in 7/8 and as low as 1 in 16-17, + * nearing an a mean of 1 in 9 to 11/12 the more repetitions are done. + * + * There are more than 220 roundstart closets on meta, around 150 of which aren't secure, + * so, about 13 to 17 closets will be affected by this most of the times. + */ + var/number_of_links = round(length(roundstart_non_secure_closets) * (rand(350, 450)*0.0001), 1) + for(var/repetition in 1 to number_of_links) + var/closets_left = length(roundstart_non_secure_closets) + if(closets_left < 2) + return + var/list/targets = list() + for(var/how_many in 1 to min(closets_left, rand(2,3))) + targets += pick_n_take(roundstart_non_secure_closets) + if(closets_left == 1) //there's only one closet left. Let's not leave it alone. + targets += roundstart_non_secure_closets[1] + GLOB.eigenstate_manager.create_new_link(targets) + /datum/station_trait/triple_ai name = "AI Triumvirate" trait_type = STATION_TRAIT_NEUTRAL diff --git a/code/datums/status_effects/_status_effect_helpers.dm b/code/datums/status_effects/_status_effect_helpers.dm index 0ee952200610661..f887afd91428e9c 100644 --- a/code/datums/status_effects/_status_effect_helpers.dm +++ b/code/datums/status_effects/_status_effect_helpers.dm @@ -56,7 +56,7 @@ . = FALSE for(var/datum/status_effect/existing_effect as anything in status_effects) - if(existing_effect.id == initial(removed_effect.id) && existing_effect.before_remove(arguments)) + if(existing_effect.id == initial(removed_effect.id) && existing_effect.before_remove(arglist(arguments))) qdel(existing_effect) . = TRUE @@ -84,6 +84,17 @@ return null +///Gets every status effect of an ID and returns all of them in a list, rather than the individual 'has_status_effect' +/mob/living/proc/get_all_status_effect_of_id(datum/status_effect/checked_effect) + RETURN_TYPE(/list/datum/status_effect) + + var/list/all_effects_of_type = list() + for(var/datum/status_effect/present_effect as anything in status_effects) + if(present_effect.id == initial(checked_effect.id)) + all_effects_of_type += present_effect + + return all_effects_of_type + /** * Checks if this mob has a status effect that shares the passed effect's ID * and has the passed sources are in its list of sources (ONLY works for grouped efects!) diff --git a/code/datums/status_effects/buffs/food/chilling.dm b/code/datums/status_effects/buffs/food/chilling.dm new file mode 100644 index 000000000000000..8b1d60fbcc15602 --- /dev/null +++ b/code/datums/status_effects/buffs/food/chilling.dm @@ -0,0 +1,13 @@ +///food effect applied by ice cream and frozen treats +/datum/status_effect/food/chilling + alert_type = /atom/movable/screen/alert/status_effect/icecream_chilling //different path, so we sprite one state and not five. + +/datum/status_effect/food/chilling/tick(seconds_between_ticks) + var/minimum_temp = (BODYTEMP_HEAT_DAMAGE_LIMIT - 12 * strength) + if(owner.bodytemperature >= minimum_temp) + owner.adjust_bodytemperature(-2.75 * strength * seconds_between_ticks, min_temp = minimum_temp) + +/atom/movable/screen/alert/status_effect/icecream_chilling + desc = "Nothing beats a cup of ice cream during hot, plasma-floody day..." + icon_state = "food_icecream" + diff --git a/code/datums/status_effects/buffs/food_traits.dm b/code/datums/status_effects/buffs/food/food_traits.dm similarity index 51% rename from code/datums/status_effects/buffs/food_traits.dm rename to code/datums/status_effects/buffs/food/food_traits.dm index ebe22116dd0dea8..dfd0b888aa09677 100644 --- a/code/datums/status_effects/buffs/food_traits.dm +++ b/code/datums/status_effects/buffs/food/food_traits.dm @@ -1,8 +1,7 @@ /datum/status_effect/food/trait/shockimmune - alert_type = /atom/movable/screen/alert/status_effect/food_trait_shockimmune + alert_type = /atom/movable/screen/alert/status_effect/food/trait_shockimmune trait = TRAIT_SHOCKIMMUNE -/atom/movable/screen/alert/status_effect/food_trait_shockimmune +/atom/movable/screen/alert/status_effect/food/trait_shockimmune name = "Grounded" desc = "That meal made me feel like a superconductor..." - icon_state = "food_buff_4" diff --git a/code/datums/status_effects/buffs/food/haste.dm b/code/datums/status_effects/buffs/food/haste.dm new file mode 100644 index 000000000000000..8dbe7a7762efef3 --- /dev/null +++ b/code/datums/status_effects/buffs/food/haste.dm @@ -0,0 +1,27 @@ +///Haste makes the eater move and act faster +/datum/status_effect/food/haste + +/datum/status_effect/food/haste/on_apply() + var/datum/movespeed_modifier/food_haste/speed_mod = new() + speed_mod.multiplicative_slowdown = -0.04 * strength + owner.add_movespeed_modifier(speed_mod, update = TRUE) + var/datum/actionspeed_modifier/status_effect/food_haste/action_mod = new() + action_mod.multiplicative_slowdown = -0.06 * strength + owner.add_actionspeed_modifier(action_mod, update = TRUE) + return ..() + +/datum/status_effect/food/haste/be_replaced() + owner.remove_movespeed_modifier(/datum/movespeed_modifier/food_haste) + owner.remove_actionspeed_modifier(/datum/actionspeed_modifier/status_effect/food_haste) + return ..() + +/datum/status_effect/food/haste/on_remove() + owner.remove_movespeed_modifier(/datum/movespeed_modifier/food_haste, update = TRUE) + owner.remove_actionspeed_modifier(/datum/actionspeed_modifier/status_effect/food_haste, update = TRUE) + return ..() + +/datum/movespeed_modifier/food_haste + multiplicative_slowdown = -0.04 + +/datum/actionspeed_modifier/status_effect/food_haste + multiplicative_slowdown = -0.06 diff --git a/code/datums/status_effects/buffs/food_haste.dm b/code/datums/status_effects/buffs/food_haste.dm deleted file mode 100644 index 9daf859fb19c7f6..000000000000000 --- a/code/datums/status_effects/buffs/food_haste.dm +++ /dev/null @@ -1,20 +0,0 @@ -/// Haste makes the eater move faster -/datum/status_effect/food/haste - var/datum/movespeed_modifier/food_haste/modifier - -/datum/status_effect/food/haste/on_apply() - modifier = new() - modifier.multiplicative_slowdown = -0.04 * strength - owner.add_movespeed_modifier(modifier, update = TRUE) - return ..() - -/datum/status_effect/food/haste/be_replaced() - owner.remove_movespeed_modifier(modifier, update = TRUE) - return ..() - -/datum/status_effect/food/haste/on_remove() - owner.remove_movespeed_modifier(modifier, update = TRUE) - return ..() - -/datum/movespeed_modifier/food_haste - multiplicative_slowdown = -0.1 diff --git a/code/datums/status_effects/debuffs/debuffs.dm b/code/datums/status_effects/debuffs/debuffs.dm index ee1c79fb6267365..1e5bdb91da94fae 100644 --- a/code/datums/status_effects/debuffs/debuffs.dm +++ b/code/datums/status_effects/debuffs/debuffs.dm @@ -278,7 +278,7 @@ . = ..() if(!.) return - owner.add_traits(list(TRAIT_IMMOBILIZED, TRAIT_HANDS_BLOCKED, TRAIT_STASIS, TRAIT_NUMBED), TRAIT_STATUS_EFFECT(id)) // SKYRAT EDIT CHANGE - ORIGINAL: owner.add_traits(list(TRAIT_IMMOBILIZED, TRAIT_HANDS_BLOCKED, TRAIT_STASIS), TRAIT_STATUS_EFFECT(id)) + owner.add_traits(list(TRAIT_IMMOBILIZED, TRAIT_HANDS_BLOCKED, TRAIT_STASIS, TRAIT_ANALGESIA), TRAIT_STATUS_EFFECT(id)) // SKYRAT EDIT CHANGE - ORIGINAL: owner.add_traits(list(TRAIT_IMMOBILIZED, TRAIT_HANDS_BLOCKED, TRAIT_STASIS), TRAIT_STATUS_EFFECT(id)) owner.throw_alert("stasis numbed", /atom/movable/screen/alert/numbed) //SKYRAT EDIT ADDITION - STASIS APPLIES NUMBED owner.add_filter("stasis_status_ripple", 2, list("type" = "ripple", "flags" = WAVE_BOUNDED, "radius" = 0, "size" = 2)) var/filter = owner.get_filter("stasis_status_ripple") @@ -294,7 +294,7 @@ owner.Sleeping(15 SECONDS) //SKYRAT EDIT END /datum/status_effect/grouped/stasis/on_remove() - owner.remove_traits(list(TRAIT_IMMOBILIZED, TRAIT_HANDS_BLOCKED, TRAIT_STASIS, TRAIT_NUMBED), TRAIT_STATUS_EFFECT(id)) // SKYRAT EDIT CHANGE - ORIGINAL: owner.remove_traits(list(TRAIT_IMMOBILIZED, TRAIT_HANDS_BLOCKED, TRAIT_STASIS), TRAIT_STATUS_EFFECT(id)) + owner.remove_traits(list(TRAIT_IMMOBILIZED, TRAIT_HANDS_BLOCKED, TRAIT_STASIS, TRAIT_ANALGESIA), TRAIT_STATUS_EFFECT(id)) // SKYRAT EDIT CHANGE - ORIGINAL: owner.remove_traits(list(TRAIT_IMMOBILIZED, TRAIT_HANDS_BLOCKED, TRAIT_STASIS), TRAIT_STATUS_EFFECT(id)) owner.clear_alert("stasis numbed") //SKYRAT EDIT ADDITION - STASIS APPLIED NUMBED owner.remove_filter("stasis_status_ripple") update_time_of_death() @@ -346,7 +346,7 @@ /datum/status_effect/crusher_mark id = "crusher_mark" duration = 300 //if you leave for 30 seconds you lose the mark, deal with it - status_type = STATUS_EFFECT_REPLACE + status_type = STATUS_EFFECT_MULTIPLE alert_type = null var/mutable_appearance/marked_underlay var/obj/item/kinetic_crusher/hammer_synced @@ -373,9 +373,9 @@ QDEL_NULL(marked_underlay) return ..() -/datum/status_effect/crusher_mark/be_replaced() - owner.underlays -= marked_underlay //if this is being called, we should have an owner at this point. - ..() +//we will only clear ourselves if the crusher is the one that owns us. +/datum/status_effect/crusher_mark/before_remove(obj/item/kinetic_crusher/attacking_hammer) + return (attacking_hammer == hammer_synced) /datum/status_effect/stacking/saw_bleed id = "saw_bleed" diff --git a/code/datums/status_effects/debuffs/fire_stacks.dm b/code/datums/status_effects/debuffs/fire_stacks.dm index 2f32ff5b3bedfd0..5bf8269bbbfdace 100644 --- a/code/datums/status_effects/debuffs/fire_stacks.dm +++ b/code/datums/status_effects/debuffs/fire_stacks.dm @@ -30,8 +30,7 @@ qdel(src) return if(isbasicmob(owner)) - var/mob/living/basic/basic_owner = owner - if(!(basic_owner.basic_mob_flags & FLAMMABLE_MOB)) + if(!check_basic_mob_immunity(owner)) qdel(src) return @@ -94,6 +93,10 @@ stacks = max(0, min(stack_limit, stacks + new_stacks)) cache_stacks() +/// Checks if the applicable basic mob is immune to the status effect we're trying to apply. Returns TRUE if it is, FALSE if it isn't. +/datum/status_effect/fire_handler/proc/check_basic_mob_immunity(mob/living/basic/basic_owner) + return (basic_owner.basic_mob_flags & FLAMMABLE_MOB) + /** * Refresher for mob's fire_stacks */ @@ -272,11 +275,6 @@ overlays |= created_overlay -/obj/effect/dummy/lighting_obj/moblight/fire - name = "fire" - light_color = LIGHT_COLOR_FIRE - light_range = LIGHT_RANGE_FIRE - /datum/status_effect/fire_handler/wet_stacks id = "wet_stacks" @@ -292,3 +290,6 @@ if(particle_effect) return particle_effect = new(owner, /particles/droplets) + +/datum/status_effect/fire_handler/wet_stacks/check_basic_mob_immunity(mob/living/basic/basic_owner) + return !(basic_owner.basic_mob_flags & IMMUNE_TO_GETTING_WET) diff --git a/code/datums/status_effects/food_effects.dm b/code/datums/status_effects/food_effects.dm index e41ef67ad1059dc..deba7bf750b6b7e 100644 --- a/code/datums/status_effects/food_effects.dm +++ b/code/datums/status_effects/food_effects.dm @@ -3,37 +3,24 @@ id = "food_buff" duration = 5 MINUTES // Same as food mood buffs status_type = STATUS_EFFECT_REPLACE // Only one food buff allowed + alert_type = /atom/movable/screen/alert/status_effect/food /// Buff power var/strength /datum/status_effect/food/on_creation(mob/living/new_owner, timeout_mod = 1, strength = 1) src.strength = strength //Generate alert when not specified - if(alert_type == /atom/movable/screen/alert/status_effect) - alert_type = "/atom/movable/screen/alert/status_effect/food/buff_[strength]" if(isnum(timeout_mod)) duration *= timeout_mod . = ..() + if(istype(linked_alert, /atom/movable/screen/alert/status_effect/food)) + linked_alert.icon_state = "[linked_alert.base_icon_state]_[strength]" /atom/movable/screen/alert/status_effect/food name = "Hand-crafted meal" desc = "Eating it made me feel better." icon_state = "food_buff_1" - -/atom/movable/screen/alert/status_effect/food/buff_1 - icon_state = "food_buff_1" - -/atom/movable/screen/alert/status_effect/food/buff_2 - icon_state = "food_buff_2" - -/atom/movable/screen/alert/status_effect/food/buff_3 - icon_state = "food_buff_3" - -/atom/movable/screen/alert/status_effect/food/buff_4 - icon_state = "food_buff_4" - -/atom/movable/screen/alert/status_effect/food/buff_5 - icon_state = "food_buff_5" + base_icon_state = "food_buff" /// Makes you gain a trait /datum/status_effect/food/trait diff --git a/code/datums/status_effects/neutral.dm b/code/datums/status_effects/neutral.dm index 3f267cb3bad019b..9efc867a043e5f0 100644 --- a/code/datums/status_effects/neutral.dm +++ b/code/datums/status_effects/neutral.dm @@ -562,7 +562,7 @@ return ..() /datum/status_effect/tinlux_light/on_apply() - mob_light_obj = owner.mob_light(2) + mob_light_obj = owner.mob_light(2, 1.5, "#ccff33") return TRUE /datum/status_effect/tinlux_light/on_remove() diff --git a/code/datums/status_effects/song_effects.dm b/code/datums/status_effects/song_effects.dm index 066ac457a9f42ee..f61253c987d77f8 100644 --- a/code/datums/status_effects/song_effects.dm +++ b/code/datums/status_effects/song_effects.dm @@ -44,7 +44,7 @@ var/obj/effect/dummy/lighting_obj/moblight/mob_light_obj /datum/status_effect/song/light/on_apply() - mob_light_obj = owner.mob_light(3, color = LIGHT_COLOR_DIM_YELLOW) + mob_light_obj = owner.mob_light(3, 1.5, color = LIGHT_COLOR_DIM_YELLOW) playsound(owner, 'sound/weapons/fwoosh.ogg', 75, FALSE) return TRUE diff --git a/code/datums/stock_market_events.dm b/code/datums/stock_market_events.dm index 81142d2300224dc..4907bf784f63af0 100644 --- a/code/datums/stock_market_events.dm +++ b/code/datums/stock_market_events.dm @@ -83,7 +83,7 @@ /datum/stock_market_event/large_boost name = "Large Boost!" trend_value = MARKET_TREND_UPWARD - trend_duration = 3 + trend_duration = 4 circumstance = list( "has just released a new product that raised the price of ", "discovered a new valuable use for ", @@ -93,14 +93,14 @@ /datum/stock_market_event/large_boost/start_event() . = ..() var/price_units = SSstock_market.materials_prices[mat] - SSstock_market.materials_prices[mat] += round(gaussian(price_units * 0.5, price_units * 0.1)) + SSstock_market.materials_prices[mat] += round(gaussian(price_units, price_units * 0.15)) SSstock_market.materials_prices[mat] = clamp(SSstock_market.materials_prices[mat], price_minimum * mat.value_per_unit, price_maximum * mat.value_per_unit) create_news() /datum/stock_market_event/large_drop name = "Large Drop!" trend_value = MARKET_TREND_DOWNWARD - trend_duration = 5 + trend_duration = 4 circumstance = list( "'s latest product has seen major controversy, and resulted in a price drop for ", "has been hit with a major lawsuit, resulting in a price drop for ", @@ -110,6 +110,42 @@ /datum/stock_market_event/large_drop/start_event() . = ..() var/price_units = SSstock_market.materials_prices[mat] - SSstock_market.materials_prices[mat] -= round(gaussian(price_units * 1.5, price_units * 0.1)) + SSstock_market.materials_prices[mat] -= round(gaussian(price_units * 1.5, price_units * 0.15)) SSstock_market.materials_prices[mat] = clamp(SSstock_market.materials_prices[mat], price_minimum * mat.value_per_unit, price_maximum * mat.value_per_unit) create_news() + +/datum/stock_market_event/hotcakes + name = "Selling like Hotcakes!" + trend_value = MARKET_TREND_UPWARD + trend_duration = 1 + circumstance = list( + "has just released a new product that is dominating the market for ", + "is hitting it big! Dramatically stocking and raising the price of ", + ", in a surprise move, monopolized supply and has raised the price of ", + ) + +/datum/stock_market_event/hotcakes/start_event() + . = ..() + SSstock_market.materials_prices[mat] = round(price_maximum * mat.value_per_unit) + create_news() + +/datum/stock_market_event/lockdown + name = "Lockdown!" + trend_value = MARKET_TREND_DOWNWARD + trend_duration = 2 + circumstance = list( + "is being investigated by the Galactic Trade Commission, resulting in a halt of trade for ", + ", in a stunning move, has been embargoed by TerraGov, resulting in a halt of trade of ", + ) + +/datum/stock_market_event/lockdown/handle() + . = ..() + SSstock_market.materials_quantity[mat] = 0 //Force the material to be unavailable. + +/datum/stock_market_event/lockdown/end_event() + . = ..() + SSstock_market.materials_quantity[mat] = initial(mat.tradable_base_quantity) //Force the material to be available again. + SSstock_market.materials_prices[mat] = initial(mat.value_per_unit) * SHEET_MATERIAL_AMOUNT //Force the price to be reset once the lockdown is over. + create_news() + + diff --git a/code/datums/wires/collar_bomb.dm b/code/datums/wires/collar_bomb.dm new file mode 100644 index 000000000000000..574a3d52dbcfbf1 --- /dev/null +++ b/code/datums/wires/collar_bomb.dm @@ -0,0 +1,33 @@ +/datum/wires/collar_bomb + proper_name = "Collar Bomb" + randomize = TRUE // Only one wire, no need for blueprints + holder_type = /obj/item/clothing/neck/collar_bomb + wires = list(WIRE_ACTIVATE) + +/datum/wires/collar_bomb/interactable(mob/user) + . = ..() + if(user.get_item_by_slot(ITEM_SLOT_NECK) == holder) + return FALSE + +/datum/wires/collar_bomb/on_pulse(wire, mob/user) + var/obj/item/clothing/neck/collar_bomb/collar = holder + if(collar.active) + return ..() + collar.explosive_countdown(ticks_left = 5) + if(!ishuman(collar.loc)) + return ..() + var/mob/living/carbon/human/brian = collar.loc + if(brian.get_item_by_slot(ITEM_SLOT_NECK) != collar) + return ..() + var/mob/living/triggerer = user + var/obj/item/assembly/assembly + if(isnull(triggerer)) + assembly = assemblies[colors[1]] + if(assembly) + triggerer = get_mob_by_key(assembly.fingerprintslast) + brian.investigate_log("has had their [collar] triggered [triggerer ? "by [user || assembly][assembly ? " last touched by triggerer" : ""]" : ""].", INVESTIGATE_DEATHS) + return ..() + +///I'd rather not get people killed by EMP here. +/datum/wires/collar_bomb/emp_pulse() + return diff --git a/code/game/area/areas/away_content.dm b/code/game/area/areas/away_content.dm index db4900a1edd0e01..86d1ade828c00ea 100644 --- a/code/game/area/areas/away_content.dm +++ b/code/game/area/areas/away_content.dm @@ -35,6 +35,10 @@ Unused icons for new areas are "awaycontent1" ~ "awaycontent30" sound_environment = SOUND_ENVIRONMENT_PLAIN ambientsounds = list('sound/ambience/shore.ogg', 'sound/ambience/ambiodd.ogg','sound/ambience/ambinice.ogg') +/area/awaymission/museum/cafeteria + name = "Nanotrasen Museum Cafeteria" + sound_environment = SOUND_ENVIRONMENT_ROOM + /area/awaymission/errorroom name = "Super Secret Room" static_lighting = FALSE diff --git a/code/game/area/areas/ruins/lavaland.dm b/code/game/area/areas/ruins/lavaland.dm index c16d65059ff5c83..3d4c0fa41722677 100644 --- a/code/game/area/areas/ruins/lavaland.dm +++ b/code/game/area/areas/ruins/lavaland.dm @@ -10,6 +10,9 @@ name = "\improper Clown Biodome" ambientsounds = list('sound/ambience/clown.ogg') +/area/ruin/lizard_gaslava + name = "\improper Lizard's Gas(Lava)" + /area/ruin/unpowered/gaia name = "\improper Patch of Eden" diff --git a/code/game/atom/_atom.dm b/code/game/atom/_atom.dm index 71b86bafe722113..ad841856c64622e 100644 --- a/code/game/atom/_atom.dm +++ b/code/game/atom/_atom.dm @@ -794,6 +794,10 @@ /atom/proc/setClosed() return +///Called after the atom is 'tamed' for type-specific operations, Usually called by the tameable component but also other things. +/atom/proc/tamed(mob/living/tamer, obj/item/food) + return + /** * Used to attempt to charge an object with a payment component. * diff --git a/code/game/atom/atom_tool_acts.dm b/code/game/atom/atom_tool_acts.dm index 078615dba75ee03..4b91f396095fdc4 100644 --- a/code/game/atom/atom_tool_acts.dm +++ b/code/game/atom/atom_tool_acts.dm @@ -25,8 +25,8 @@ return early_sig_return var/interact_return = is_left_clicking \ - ? tool.interact_with_atom(src, user) \ - : tool.interact_with_atom_secondary(src, user) + ? tool.interact_with_atom(src, user, modifiers) \ + : tool.interact_with_atom_secondary(src, user, modifiers) if(interact_return) return interact_return @@ -92,7 +92,7 @@ * Return an ITEM_INTERACT_ flag in the event the interaction was handled, to cancel further interaction code. * Return NONE to allow default interaction / tool handling. */ -/obj/item/proc/interact_with_atom(atom/interacting_with, mob/living/user) +/obj/item/proc/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) return NONE /** @@ -104,8 +104,8 @@ * Return an ITEM_INTERACT_ flag in the event the interaction was handled, to cancel further interaction code. * Return NONE to allow default interaction / tool handling. */ -/obj/item/proc/interact_with_atom_secondary(atom/interacting_with, mob/living/user) - return interact_with_atom(interacting_with, user) +/obj/item/proc/interact_with_atom_secondary(atom/interacting_with, mob/living/user, list/modifiers) + return interact_with_atom(interacting_with, user, modifiers) /* * Tool-specific behavior procs. diff --git a/code/game/atoms_movable.dm b/code/game/atoms_movable.dm index 9603e87067d802f..582df12516f5d78 100644 --- a/code/game/atoms_movable.dm +++ b/code/game/atoms_movable.dm @@ -425,7 +425,7 @@ if(z_move_flags & ZMOVE_CAN_FLY_CHECKS && !(movement_type & (FLYING|FLOATING)) && has_gravity(start)) if(z_move_flags & ZMOVE_FEEDBACK) if(rider) - to_chat(rider, span_warning("[src] is is not capable of flight.")) + to_chat(rider, span_warning("[src] [p_are()] incapable of flight.")) else to_chat(src, span_warning("You are not Superman.")) return FALSE diff --git a/code/game/machinery/autolathe.dm b/code/game/machinery/autolathe.dm index ba9667b3e5809dd..a0e2eab029b6dfd 100644 --- a/code/game/machinery/autolathe.dm +++ b/code/game/machinery/autolathe.dm @@ -95,10 +95,19 @@ /obj/machinery/autolathe/proc/AfterMaterialInsert(container, obj/item/item_inserted, last_inserted_id, mats_consumed, amount_inserted, atom/context) SIGNAL_HANDLER - flick("autolathe_[item_inserted.has_material_type(/datum/material/glass) ? "r" : "o"]", src) - //we use initial(active_power_usage) because higher tier parts will have higher active usage but we have no benifit from it - directly_use_power(ROUND_UP((amount_inserted / (MAX_STACK_SIZE * SHEET_MATERIAL_AMOUNT)) * 0.01 * initial(active_power_usage))) + if(directly_use_power(ROUND_UP((amount_inserted / (MAX_STACK_SIZE * SHEET_MATERIAL_AMOUNT)) * 0.02 * initial(active_power_usage)))) + flick_overlay_view(mutable_appearance('icons/obj/machines/lathes.dmi', "autolathe_mat"), 1 SECONDS) + + var/datum/material/highest_mat_ref + var/highest_mat = 0 + for(var/datum/material/mat as anything in mats_consumed) + var/present_mat = mats_consumed[mat] + if(present_mat > highest_mat) + highest_mat = present_mat + highest_mat_ref = mat + + flick_overlay_view(material_insertion_animation(highest_mat_ref.greyscale_colors), 1 SECONDS) /obj/machinery/autolathe/ui_interact(mob/user, datum/tgui/ui) if(!is_operational) diff --git a/code/game/machinery/buttons.dm b/code/game/machinery/buttons.dm index 5824f93dcc736da..429ecd70b664903 100644 --- a/code/game/machinery/buttons.dm +++ b/code/game/machinery/buttons.dm @@ -21,6 +21,7 @@ armor_type = /datum/armor/machinery_button idle_power_usage = BASE_MACHINE_IDLE_CONSUMPTION * 0.02 resistance_flags = LAVA_PROOF | FIRE_PROOF + interaction_flags_machine = parent_type::interaction_flags_machine | INTERACT_MACHINE_OPEN /obj/machinery/button/indestructible resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF diff --git a/code/game/machinery/camera/camera.dm b/code/game/machinery/camera/camera.dm index 69c01a22f62c7df..9dc50ff9ce7c0ae 100644 --- a/code/game/machinery/camera/camera.dm +++ b/code/game/machinery/camera/camera.dm @@ -185,7 +185,8 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/camera/xray, 0) /obj/machinery/camera/proc/on_saboteur(datum/source, disrupt_duration) SIGNAL_HANDLER - emp_act(EMP_LIGHT, reset_time = disrupt_duration) + //lasts twice as much so we don't have to constantly shoot cameras just to be S T E A L T H Y + emp_act(EMP_LIGHT, reset_time = disrupt_duration * 2) return COMSIG_SABOTEUR_SUCCESS /obj/machinery/camera/proc/post_emp_reset(thisemp, previous_network) diff --git a/code/game/machinery/computer/accounting.dm b/code/game/machinery/computer/accounting.dm index 475bf404c1ce057..d804b8efe5d942a 100644 --- a/code/game/machinery/computer/accounting.dm +++ b/code/game/machinery/computer/accounting.dm @@ -21,10 +21,9 @@ for(var/current_account as anything in SSeconomy.bank_accounts_by_id) var/datum/bank_account/current_bank_account = SSeconomy.bank_accounts_by_id[current_account] - var/job_title = current_bank_account.account_job?.title player_accounts += list(list( "name" = current_bank_account.account_holder, - "job" = job_title ? job_title : "No Job", // because this can be null + "job" = current_bank_account.account_job?.title || "No job", // because this can be null "balance" = round(current_bank_account.account_balance), "modifier" = round((current_bank_account.payday_modifier * 0.9), 0.1), )) @@ -32,4 +31,3 @@ data["AuditLog"] = audit_list data["Crashing"] = HAS_TRAIT(SSeconomy, TRAIT_MARKET_CRASHING) return data - diff --git a/code/game/machinery/computer/buildandrepair.dm b/code/game/machinery/computer/buildandrepair.dm index 157a3a77fbee91b..f3b43e07caa98df 100644 --- a/code/game/machinery/computer/buildandrepair.dm +++ b/code/game/machinery/computer/buildandrepair.dm @@ -10,7 +10,6 @@ . = ..() AddComponent(/datum/component/simple_rotation) register_context() - update_appearance(UPDATE_ICON_STATE) /obj/structure/frame/computer/deconstruct(disassembled = TRUE) if(!(obj_flags & NO_DECONSTRUCTION)) diff --git a/code/game/machinery/computer/camera.dm b/code/game/machinery/computer/camera.dm index 37514c142fe8ab7..da807f52764e2ed 100644 --- a/code/game/machinery/computer/camera.dm +++ b/code/game/machinery/computer/camera.dm @@ -50,7 +50,7 @@ /obj/machinery/computer/security/ui_interact(mob/user, datum/tgui/ui) . = ..() - if(!user.can_perform_action(src, NEED_DEXTERITY)) //prevents monkeys from using camera consoles + if(!user.client) //prevents errors by trying to pass clients that don't exist. return // Update UI ui = SStgui.try_update_ui(user, src, ui) diff --git a/code/game/machinery/computer/orders/order_items/mining/order_pka.dm b/code/game/machinery/computer/orders/order_items/mining/order_pka.dm index 251343e6f8e2c6a..f239e9f2a7eaf9d 100644 --- a/code/game/machinery/computer/orders/order_items/mining/order_pka.dm +++ b/code/game/machinery/computer/orders/order_items/mining/order_pka.dm @@ -40,3 +40,7 @@ /datum/orderable_item/accelerator/minebot_passthrough item_path = /obj/item/borg/upgrade/modkit/minebot_passthrough cost_per_order = 800 + +/datum/orderable_item/accelerator/friendly_fire + item_path = /obj/item/borg/upgrade/modkit/human_passthrough + cost_per_order = 750 diff --git a/code/game/machinery/computer/records/records.dm b/code/game/machinery/computer/records/records.dm index 531e1725e332545..baf0560b5f6a0db 100644 --- a/code/game/machinery/computer/records/records.dm +++ b/code/game/machinery/computer/records/records.dm @@ -35,6 +35,7 @@ return FALSE var/value = trim(params["value"], MAX_BROADCAST_LEN) + investigate_log("[key_name(usr)] changed the field: \"[field]\" with value: \"[target.vars[field]]\" to new value: \"[value || "Unknown"]\"", INVESTIGATE_RECORDS) target.vars[field] = value || "Unknown" return TRUE @@ -56,6 +57,7 @@ if("login") authenticated = secure_login(usr) + investigate_log("[key_name(usr)] [authenticated ? "successfully logged" : "failed to log"] into the [src].", INVESTIGATE_RECORDS) return TRUE if("logout") diff --git a/code/game/machinery/computer/records/security.dm b/code/game/machinery/computer/records/security.dm index 0064cf570a69105..ec2bec3d2669006 100644 --- a/code/game/machinery/computer/records/security.dm +++ b/code/game/machinery/computer/records/security.dm @@ -163,6 +163,7 @@ return TRUE if("delete_record") + investigate_log("[usr] deleted record: \"[target]\".", INVESTIGATE_RECORDS) qdel(target) return TRUE @@ -179,8 +180,9 @@ return TRUE if("set_note") - var/note = params["note"] - target.security_note = trim(note, MAX_MESSAGE_LEN) + var/note = trim(params["note"], MAX_MESSAGE_LEN) + investigate_log("[usr] has changed the security note of record: \"[target]\" from \"[target.security_note]\" to \"[note]\".") + target.security_note = note return TRUE if("set_wanted") @@ -243,14 +245,19 @@ return FALSE if(user != editing_crime.author && !has_armory_access(user)) // only warden/hos/command can edit crimes they didn't author + investigate_log("[user] attempted to edit crime: \"[editing_crime.name]\" for target: \"[target.name]\" but failed due to lacking armoury access and not being the author of the crime.", INVESTIGATE_RECORDS) return FALSE if(params["name"] && length(params["name"]) > 2 && params["name"] != editing_crime.name) - editing_crime.name = trim(params["name"], MAX_CRIME_NAME_LEN) + var/new_name = trim(params["name"], MAX_CRIME_NAME_LEN) + investigate_log("[user] edited crime: \"[editing_crime.name]\" for target: \"[target.name]\", changing the name to: \"[new_name]\".", INVESTIGATE_RECORDS) + editing_crime.name = new_name return TRUE if(params["details"] && length(params["description"]) > 2 && params["name"] != editing_crime.name) - editing_crime.details = trim(params["details"], MAX_MESSAGE_LEN) + var/new_details = trim(params["details"], MAX_MESSAGE_LEN) + investigate_log("[user] edited crime \"[editing_crime.name]\" for target: \"[target.name]\", changing the details to: \"[new_details]\" from: \"[editing_crime.details]\".", INVESTIGATE_RECORDS) + editing_crime.details = new_details return TRUE return FALSE diff --git a/code/game/machinery/constructable_frame.dm b/code/game/machinery/constructable_frame.dm index e624e3f33d705a5..b3c1e055679d0ac 100644 --- a/code/game/machinery/constructable_frame.dm +++ b/code/game/machinery/constructable_frame.dm @@ -13,6 +13,10 @@ /// The current (de/con)struction state of the frame var/state = FRAME_STATE_EMPTY +/obj/structure/frame/Initialize(mapload) + . = ..() + update_appearance(UPDATE_ICON_STATE) + /obj/structure/frame/examine(user) . = ..() if(circuit) diff --git a/code/game/machinery/doors/door.dm b/code/game/machinery/doors/door.dm index db09a0db5603660..aa7e66824023f85 100644 --- a/code/game/machinery/doors/door.dm +++ b/code/game/machinery/doors/door.dm @@ -239,7 +239,7 @@ var/obj/item/I = AM if(!density || (I.w_class < WEIGHT_CLASS_NORMAL && !LAZYLEN(I.GetAccess()))) return - if(check_access(I)) + if(requiresID() && check_access(I)) open() else do_animate("deny") diff --git a/code/game/machinery/machine_frame.dm b/code/game/machinery/machine_frame.dm index a3c074937f0f765..5a6ff12c3d10231 100644 --- a/code/game/machinery/machine_frame.dm +++ b/code/game/machinery/machine_frame.dm @@ -12,7 +12,6 @@ /obj/structure/frame/machine/Initialize(mapload) . = ..() register_context() - update_appearance(UPDATE_ICON_STATE) /obj/structure/frame/machine/Destroy() QDEL_LIST(components) @@ -26,8 +25,8 @@ return ..() /obj/structure/frame/machine/try_dissassemble(mob/living/user, obj/item/tool, disassemble_time) - if(anchored) - balloon_alert(user, "must be unsecured first!") + if(anchored && state == FRAME_STATE_EMPTY) //when using a screwdriver on an incomplete frame(missing components) no point checking for this + balloon_alert(user, "must be unanchored first!") return FALSE return ..() @@ -36,14 +35,15 @@ if(isnull(held_item)) return + if(held_item.tool_behaviour == TOOL_WRENCH && !circuit?.needs_anchored) + context[SCREENTIP_CONTEXT_LMB] = "[anchored ? "Un" : ""]anchor" + return CONTEXTUAL_SCREENTIP_SET + switch(state) if(FRAME_STATE_EMPTY) if(istype(held_item, /obj/item/stack/cable_coil)) context[SCREENTIP_CONTEXT_LMB] = "Wire Frame" return CONTEXTUAL_SCREENTIP_SET - else if(held_item.tool_behaviour == TOOL_WRENCH) - context[SCREENTIP_CONTEXT_LMB] = "[anchored ? "Un" : ""]anchor" - return CONTEXTUAL_SCREENTIP_SET else if(held_item.tool_behaviour == TOOL_WELDER) context[SCREENTIP_CONTEXT_LMB] = "Unweld frame" return CONTEXTUAL_SCREENTIP_SET @@ -61,11 +61,6 @@ if(held_item.tool_behaviour == TOOL_CROWBAR) context[SCREENTIP_CONTEXT_LMB] = "Pry out components" return CONTEXTUAL_SCREENTIP_SET - else if(held_item.tool_behaviour == TOOL_WRENCH) - if(!circuit.needs_anchored) - context[SCREENTIP_CONTEXT_LMB] = "[anchored ? "Un" : ""]anchor" - return CONTEXTUAL_SCREENTIP_SET - return NONE else if(held_item.tool_behaviour == TOOL_SCREWDRIVER) var/needs_components = FALSE for(var/component in req_components) @@ -470,5 +465,6 @@ return TRUE /obj/structure/frame/machine/secured + icon_state = "box_1" state = FRAME_STATE_WIRED anchored = TRUE diff --git a/code/game/machinery/pipe/construction.dm b/code/game/machinery/pipe/construction.dm index af6b477e90ba86d..d9e3787fd9ead12 100644 --- a/code/game/machinery/pipe/construction.dm +++ b/code/game/machinery/pipe/construction.dm @@ -248,7 +248,7 @@ Buildable meters return TRUE // no conflicts found - var/obj/machinery/atmospherics/built_machine = new pipe_type(loc, , , p_init_dir) + var/obj/machinery/atmospherics/built_machine = new pipe_type(loc, null, fixed_dir(), p_init_dir) build_pipe(built_machine) built_machine.on_construction(user, pipe_color, piping_layer) transfer_fingerprints_to(built_machine) @@ -356,9 +356,6 @@ Buildable meters return FALSE /obj/item/pipe/proc/build_pipe(obj/machinery/atmospherics/A) - A.setDir(fixed_dir()) - A.set_init_directions(p_init_dir) - if(pipename) A.name = pipename if(A.on) diff --git a/code/game/machinery/porta_turret/portable_turret.dm b/code/game/machinery/porta_turret/portable_turret.dm index 809171af1efa7cd..f5f8327607af3f3 100644 --- a/code/game/machinery/porta_turret/portable_turret.dm +++ b/code/game/machinery/porta_turret/portable_turret.dm @@ -103,6 +103,8 @@ DEFINE_BITFIELD(turret_flags, list( var/datum/action/turret_toggle/toggle_action /// Mob that is remotely controlling the turret var/mob/remote_controller + /// While the cooldown is still going on, it cannot be re-enabled. + COOLDOWN_DECLARE(disabled_time) /datum/armor/machinery_porta_turret melee = 50 @@ -133,18 +135,32 @@ DEFINE_BITFIELD(turret_flags, list( if(!has_cover) INVOKE_ASYNC(src, PROC_REF(popUp)) + RegisterSignal(src, COMSIG_HIT_BY_SABOTEUR, PROC_REF(on_saboteur)) + AddElement(/datum/element/hostile_machine) -/obj/machinery/porta_turret/proc/toggle_on(set_to) - var/current = on - if (!isnull(set_to)) - on = set_to - else - on = !on - if (current != on) - check_should_process() - if (!on) - popDown() +///Toggles the turret on or off depending on the value of the turn_on arg. +/obj/machinery/porta_turret/proc/toggle_on(turn_on = TRUE) + if(on == turn_on) + return + if(on && !COOLDOWN_FINISHED(src, disabled_time)) + return + on = turn_on + check_should_process() + if (!on) + popDown() + +///Prevents turned from being turned on for a duration, then restarts them after that if the second ard is true. +/obj/machinery/porta_turret/proc/set_disabled(duration = 6 SECONDS, will_restart = on) + COOLDOWN_START(src, disabled_time, duration) + if(will_restart) + addtimer(CALLBACK(src, PROC_REF(toggle_on), TRUE), duration + 1) //the cooldown isn't over until the tick after its end. + toggle_on(FALSE) + +/obj/machinery/porta_turret/proc/on_saboteur(datum/source, disrupt_duration) + SIGNAL_HANDLER + INVOKE_ASYNC(src, PROC_REF(set_disabled), disrupt_duration) + return COMSIG_SABOTEUR_SUCCESS /obj/machinery/porta_turret/proc/check_should_process() if (datum_flags & DF_ISPROCESSING) @@ -256,7 +272,7 @@ DEFINE_BITFIELD(turret_flags, list( switch(action) if("power") if(anchored) - toggle_on() + toggle_on(!on) return TRUE else to_chat(usr, span_warning("It has to be secured first!")) @@ -364,10 +380,8 @@ DEFINE_BITFIELD(turret_flags, list( audible_message(span_hear("[src] hums oddly...")) obj_flags |= EMAGGED controllock = TRUE - toggle_on(FALSE) //turns off the turret temporarily + set_disabled(6 SECONDS) update_appearance() - //6 seconds for the traitor to gtfo of the area before the turret decides to ruin his shit - addtimer(CALLBACK(src, PROC_REF(toggle_on), TRUE), 6 SECONDS) //turns it back on. The cover popUp() popDown() are automatically called in process(), no need to define it here return TRUE @@ -385,11 +399,9 @@ DEFINE_BITFIELD(turret_flags, list( if(prob(20)) turret_flags |= TURRET_FLAG_SHOOT_ALL // Shooting everyone is a pretty big deal, so it's least likely to get turned on - toggle_on(FALSE) + set_disabled(rand(6 SECONDS, 20 SECONDS)) remove_control() - addtimer(CALLBACK(src, PROC_REF(toggle_on), TRUE), rand(60,600)) - /obj/machinery/porta_turret/take_damage(damage_amount, damage_type = BRUTE, damage_flag = "", sound_effect = TRUE, attack_dir, armour_penetration = 0) . = ..() if(. && atom_integrity > 0) //damage received @@ -1186,17 +1198,14 @@ DEFINE_BITFIELD(turret_flags, list( installation = /obj/item/gun/energy/laser/bluetag team_color = "blue" -/obj/machinery/porta_turret/lasertag/bullet_act(obj/projectile/P) +/obj/machinery/porta_turret/lasertag/bullet_act(obj/projectile/projectile) . = ..() - if(on) - if(team_color == "blue") - if(istype(P, /obj/projectile/beam/lasertag/redtag)) - toggle_on(FALSE) - addtimer(CALLBACK(src, PROC_REF(toggle_on), TRUE), 10 SECONDS) - else if(team_color == "red") - if(istype(P, /obj/projectile/beam/lasertag/bluetag)) - toggle_on(FALSE) - addtimer(CALLBACK(src, PROC_REF(toggle_on), TRUE), 10 SECONDS) + if(!on) + return + if(team_color == "blue" && istype(projectile, /obj/projectile/beam/lasertag/redtag)) + set_disabled(10 SECONDS) + else if(team_color == "red" && istype(projectile, /obj/projectile/beam/lasertag/bluetag)) + set_disabled(10 SECONDS) #undef TURRET_STUN #undef TURRET_LETHAL diff --git a/code/game/machinery/recycler.dm b/code/game/machinery/recycler.dm index 1014393c008362a..5d4fd671c9623de 100644 --- a/code/game/machinery/recycler.dm +++ b/code/game/machinery/recycler.dm @@ -19,22 +19,9 @@ var/datum/component/material_container/materials /obj/machinery/recycler/Initialize(mapload) - var/list/allowed_materials = list( - /datum/material/iron, - /datum/material/glass, - /datum/material/silver, - /datum/material/plasma, - /datum/material/gold, - /datum/material/diamond, - /datum/material/plastic, - /datum/material/uranium, - /datum/material/bananium, - /datum/material/titanium, - /datum/material/bluespace - ) materials = AddComponent( /datum/component/material_container, \ - allowed_materials, \ + SSmaterials.materials_by_category[MAT_CATEGORY_SILO], \ INFINITY, \ MATCONTAINER_NO_INSERT \ ) diff --git a/code/game/objects/effects/decals/cleanable/misc.dm b/code/game/objects/effects/decals/cleanable/misc.dm index 7fe6c59075f3fd1..f21bfc4788426ed 100644 --- a/code/game/objects/effects/decals/cleanable/misc.dm +++ b/code/game/objects/effects/decals/cleanable/misc.dm @@ -124,11 +124,28 @@ desc = "You know who to call." light_power = 2 +/obj/effect/decal/cleanable/greenglow/radioactive + name = "radioactive goo" + desc = "Holy crap, stop looking at this and move away immediately! It's radioactive!" + light_power = 5 + light_range = 3 + light_color = LIGHT_COLOR_NUCLEAR + +/obj/effect/decal/cleanable/greenglow/radioactive/Initialize(mapload, list/datum/disease/diseases) + . = ..() + AddComponent( + /datum/component/radioactive_emitter, \ + cooldown_time = 5 SECONDS, \ + range = 4, \ + threshold = RAD_MEDIUM_INSULATION, \ + ) + /obj/effect/decal/cleanable/cobweb name = "cobweb" desc = "Somebody should remove that." gender = NEUTER layer = WALL_OBJ_LAYER + icon = 'icons/effects/web.dmi' icon_state = "cobweb1" resistance_flags = FLAMMABLE beauty = -100 diff --git a/code/game/objects/effects/effect_system/effects_sparks.dm b/code/game/objects/effects/effect_system/effects_sparks.dm index c3fad6d26b61d7b..874c53fa83c7db3 100644 --- a/code/game/objects/effects/effect_system/effects_sparks.dm +++ b/code/game/objects/effects/effect_system/effects_sparks.dm @@ -17,8 +17,8 @@ icon_state = "sparks" anchored = TRUE light_system = OVERLAY_LIGHT - light_range = 2 - light_power = 0.5 + light_range = 1.5 + light_power = 0.8 light_color = LIGHT_COLOR_FIRE /obj/effect/particle_effect/sparks/Initialize(mapload) diff --git a/code/game/objects/effects/effects.dm b/code/game/objects/effects/effects.dm index 377c8470480be93..0c050579de45b23 100644 --- a/code/game/objects/effects/effects.dm +++ b/code/game/objects/effects/effects.dm @@ -48,6 +48,7 @@ ///The abstract effect ignores even more effects and is often typechecked for atoms that should truly not be fucked with. /obj/effect/abstract + resistance_flags = parent_type::resistance_flags | SHUTTLE_CRUSH_PROOF /obj/effect/abstract/singularity_pull() return diff --git a/code/game/objects/effects/landmarks.dm b/code/game/objects/effects/landmarks.dm index f6151a3cbf602c0..2a6d1c039ad1516 100644 --- a/code/game/objects/effects/landmarks.dm +++ b/code/game/objects/effects/landmarks.dm @@ -36,7 +36,7 @@ INITIALIZE_IMMEDIATE(/obj/effect/landmark) /obj/effect/landmark/start/proc/after_round_start() // We'd like to keep these around for unit tests, so we can check that they exist. -#ifndef UNIT_TESTS +#if !defined(UNIT_TESTS) && !defined(MAP_TEST) if(delete_after_roundstart) qdel(src) #endif diff --git a/code/game/objects/effects/lighting.dm b/code/game/objects/effects/lighting.dm index 1de9fad39eee42c..caeedbd22bb89b5 100644 --- a/code/game/objects/effects/lighting.dm +++ b/code/game/objects/effects/lighting.dm @@ -37,6 +37,7 @@ name = "mob fire lighting" light_color = LIGHT_COLOR_FIRE light_range = LIGHT_RANGE_FIRE + light_power = 2 /obj/effect/dummy/lighting_obj/moblight/species name = "species lighting" diff --git a/code/game/objects/effects/material_insert.dm b/code/game/objects/effects/material_insert.dm new file mode 100644 index 000000000000000..9ca86226b24b911 --- /dev/null +++ b/code/game/objects/effects/material_insert.dm @@ -0,0 +1,22 @@ +/** + * Creates a mutable appearance with the material color applied for its insertion animation into an autolathe or techfab + * Arguments + * + * * color - the material color that will be applied + */ +/proc/material_insertion_animation(color) + RETURN_TYPE(/mutable_appearance) + + var/static/list/mutable_appearance/apps = list() + + var/mutable_appearance/cached_app = apps[color] + if(isnull(cached_app)) + var/icon/modified_icon = icon('icons/obj/machines/research.dmi', "material_insertion") + + //assuming most of the icon is white we find what ratio to scale the intensity of each part roughly + var/list/rgb_list = rgb2num(color) + modified_icon.SetIntensity(rgb_list[1] / 255, rgb_list[2] / 255, rgb_list[3] / 255) + cached_app = mutable_appearance(modified_icon, "material_insertion") + + apps[color] = cached_app + return cached_app diff --git a/code/game/objects/effects/posters/contraband.dm b/code/game/objects/effects/posters/contraband.dm index 2bb2fcce50e4696..52528c251b65979 100644 --- a/code/game/objects/effects/posters/contraband.dm +++ b/code/game/objects/effects/posters/contraband.dm @@ -625,3 +625,35 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/structure/sign/poster/contraband/blood_geometer icon_state = "singletank_bomb" MAPPING_DIRECTIONAL_HELPERS(/obj/structure/sign/poster/contraband/singletank_bomb, 32) + +///a special poster meant to fool people into thinking this is a bombable wall at a glance. +/obj/structure/sign/poster/contraband/fake_bombable + name = "fake bombable poster" + desc = "We do a little trolling." + icon_state = "fake_bombable" + never_random = TRUE + +/obj/structure/sign/poster/contraband/fake_bombable/Initialize(mapload) + . = ..() + var/turf/our_wall = get_turf_pixel(src) + name = our_wall.name + +/obj/structure/sign/poster/contraband/fake_bombable/examine(mob/user) + var/turf/our_wall = get_turf_pixel(src) + . = our_wall.examine(user) + . += span_notice("It seems to be slightly cracked...") + +/obj/structure/sign/poster/contraband/fake_bombable/ex_act(severity, target) + addtimer(CALLBACK(src, PROC_REF(fall_off_wall)), 2.5 SECONDS) + return FALSE + +/obj/structure/sign/poster/contraband/fake_bombable/proc/fall_off_wall() + if(QDELETED(src) || !isturf(loc)) + return + var/turf/our_wall = get_turf_pixel(src) + our_wall.balloon_alert_to_viewers("it was a ruse!") + roll_and_drop(loc) + playsound(loc, 'sound/items/handling/paper_drop.ogg', 50, TRUE) + + +MAPPING_DIRECTIONAL_HELPERS(/obj/structure/sign/poster/contraband/fake_bombable, 32) diff --git a/code/game/objects/effects/posters/poster.dm b/code/game/objects/effects/posters/poster.dm index 75a3a26ce26f28f..c4703d700c4a45f 100644 --- a/code/game/objects/effects/posters/poster.dm +++ b/code/game/objects/effects/posters/poster.dm @@ -180,7 +180,7 @@ qdel(src) else to_chat(user, span_notice("You carefully remove the poster from the wall.")) - roll_and_drop(Adjacent(user) ? get_turf(user) : loc) + roll_and_drop(Adjacent(user) ? get_turf(user) : loc, user) /obj/structure/sign/poster/attack_hand(mob/user, list/modifiers) . = ..() @@ -207,11 +207,12 @@ return FALSE return !user.gloves || !(user.gloves.body_parts_covered & HANDS) || HAS_TRAIT(user, TRAIT_FINGERPRINT_PASSTHROUGH) || HAS_TRAIT(user.gloves, TRAIT_FINGERPRINT_PASSTHROUGH) -/obj/structure/sign/poster/proc/roll_and_drop(atom/location) +/obj/structure/sign/poster/proc/roll_and_drop(atom/location, mob/user) pixel_x = 0 pixel_y = 0 var/obj/item/poster/rolled_poster = new poster_item_type(location, src) // /obj/structure/sign/poster/wanted/roll_and_drop() has some snowflake handling due to icon memes, if you make a major change to this, don't forget to update it too. <3 - forceMove(rolled_poster) + if(!user?.put_in_hands(rolled_poster)) + forceMove(rolled_poster) return rolled_poster //separated to reduce code duplication. Moved here for ease of reference and to unclutter r_wall/attackby() @@ -246,7 +247,7 @@ var/turf/user_drop_location = get_turf(user) //cache this so it just falls to the ground if they move. also no tk memes allowed. if(!do_after(user, PLACE_SPEED, placed_poster, extra_checks = CALLBACK(placed_poster, TYPE_PROC_REF(/obj/structure/sign/poster, snowflake_closed_turf_check), src))) - placed_poster.roll_and_drop(user_drop_location) + placed_poster.roll_and_drop(user_drop_location, user) return placed_poster.on_placed_poster(user) diff --git a/code/game/objects/effects/spawners/random/ai_module.dm b/code/game/objects/effects/spawners/random/ai_module.dm index 1ca7a05f2e94d72..b63efa178e28a5c 100644 --- a/code/game/objects/effects/spawners/random/ai_module.dm +++ b/code/game/objects/effects/spawners/random/ai_module.dm @@ -40,6 +40,7 @@ /obj/item/ai_module/remove, /obj/item/ai_module/core/full/dagothbot, // SKYRAT EDIT - EDITION /obj/item/ai_module/core/full/texas, // SKYRAT EDIT - EDITION + /obj/item/ai_module/core/full/emperor, // SKYRAT EDIT - EDITION ) /obj/effect/spawner/random/aimodule/harmful diff --git a/code/game/objects/effects/spawners/random/contraband.dm b/code/game/objects/effects/spawners/random/contraband.dm index ca5acbdbe6767b6..e65a73cfe4ce7e4 100644 --- a/code/game/objects/effects/spawners/random/contraband.dm +++ b/code/game/objects/effects/spawners/random/contraband.dm @@ -21,22 +21,20 @@ /obj/item/storage/fancy/cigarettes/cigpack_syndicate = 10, /obj/item/storage/fancy/cigarettes/cigpack_shadyjims = 10, /obj/item/storage/box/donkpockets = 10, + /obj/effect/spawner/random/contraband/plus = 10, /obj/item/reagent_containers/pill/maintenance = 5, - /obj/effect/spawner/random/contraband/plus = 5, ) /obj/effect/spawner/random/contraband/plus name = "contraband loot spawner plus" desc = "Where'd ya find this?" loot = list( - /obj/effect/spawner/random/contraband/prison = 40, /obj/item/clothing/under/syndicate = 20, /obj/item/reagent_containers/cup/bottle/thermite = 20, - /obj/item/reagent_containers/pill/maintenance = 10, /obj/item/restraints/legcuffs/beartrap = 10, - /obj/effect/spawner/random/contraband/narcotics = 10, - /obj/item/seeds/kronkus = 5, - /obj/item/seeds/odious_puffball = 5, + /obj/item/food/drug/saturnx = 5, + /obj/item/reagent_containers/cup/blastoff_ampoule = 5, + /obj/item/food/drug/moon_rock = 5, /obj/item/grenade/empgrenade = 5, /obj/effect/spawner/random/contraband/armory = 1, ) diff --git a/code/game/objects/effects/spawners/random/vending.dm b/code/game/objects/effects/spawners/random/vending.dm index 74ece7f24f93d8c..014f07d2967c458 100644 --- a/code/game/objects/effects/spawners/random/vending.dm +++ b/code/game/objects/effects/spawners/random/vending.dm @@ -18,6 +18,11 @@ loot_type_path = /obj/machinery/vending/snack loot = list() +/obj/effect/spawner/random/vending/snackvend/Initialize(mapload) + if(check_holidays(HOTDOG_DAY)) + loot += /obj/machinery/vending/hotdog + return ..() + /obj/effect/spawner/random/vending/colavend name = "spawn random cola vending machine" desc = "Automagically transforms into a random cola vendor. If you see this while in a shift, please create a bug report." diff --git a/code/game/objects/effects/spiderwebs.dm b/code/game/objects/effects/spiderwebs.dm index 5023f9bd8254e7c..2d0f1b9b14de219 100644 --- a/code/game/objects/effects/spiderwebs.dm +++ b/code/game/objects/effects/spiderwebs.dm @@ -1,7 +1,8 @@ -//generic procs copied from obj/effect/alien +#define SPIDER_WEB_TINT "web_colour_tint" + /obj/structure/spider name = "web" - icon = 'icons/effects/effects.dmi' + icon = 'icons/effects/web.dmi' desc = "It's stringy and sticky." anchored = TRUE density = FALSE @@ -22,7 +23,7 @@ damage_amount *= 1.25 if(BRUTE) damage_amount *= 0.25 - . = ..() + return ..() /obj/structure/spider/should_atmos_process(datum/gas_mixture/air, exposed_temperature) return exposed_temperature > 350 @@ -31,17 +32,37 @@ take_damage(5, BURN, 0, 0) /obj/structure/spider/stickyweb + plane = FLOOR_PLANE + layer = MID_TURF_LAYER + icon = 'icons/obj/smooth_structures/stickyweb.dmi' + base_icon_state = "stickyweb" + icon_state = "stickyweb-0" + smoothing_flags = SMOOTH_BITMASK + smoothing_groups = SMOOTH_GROUP_SPIDER_WEB + canSmoothWith = SMOOTH_GROUP_SPIDER_WEB + SMOOTH_GROUP_WALLS ///Whether or not the web is from the genetics power var/genetic = FALSE ///Whether or not the web is a sealed web var/sealed = FALSE - icon_state = "stickyweb1" + ///Do we need to offset this based on a sprite frill? + var/has_frill = TRUE + /// Chance that someone will get stuck when trying to cross this tile + var/stuck_chance = 50 + /// Chance that a bullet will hit this instead of flying through it + var/projectile_stuck_chance = 30 + +/obj/structure/spider/stickyweb/Initialize(mapload) + // Offset on init so that they look nice in the map editor + if (has_frill) + pixel_x = -9 + pixel_y = -9 + return ..() /obj/structure/spider/stickyweb/attack_hand(mob/user, list/modifiers) .= ..() if(.) return - if(!HAS_TRAIT(user,TRAIT_WEB_WEAVER)) + if(!HAS_TRAIT(user, TRAIT_WEB_WEAVER)) return loc.balloon_alert_to_viewers("weaving...") if(!do_after(user, 2 SECONDS)) @@ -51,11 +72,6 @@ var/obj/item/stack/sheet/cloth/woven_cloth = new /obj/item/stack/sheet/cloth user.put_in_hands(woven_cloth) -/obj/structure/spider/stickyweb/Initialize(mapload) - if(!sealed && prob(50)) - icon_state = "stickyweb2" - . = ..() - /obj/structure/spider/stickyweb/CanAllowThrough(atom/movable/mover, border_dir) . = ..() if(genetic) @@ -67,65 +83,125 @@ return TRUE if(mover.pulledby && HAS_TRAIT(mover.pulledby, TRAIT_WEB_SURFER)) return TRUE - if(prob(50)) - loc.balloon_alert(mover, "stuck in web!") + if(prob(stuck_chance)) + stuck_react(mover) return FALSE - else if(isprojectile(mover)) - return prob(30) - -/obj/structure/spider/stickyweb/sealed - name = "sealed web" - desc = "A solid thick wall of web, airtight enough to block air flow." - icon_state = "sealedweb" - sealed = TRUE - can_atmos_pass = ATMOS_PASS_NO + return . + if(isprojectile(mover)) + return prob(projectile_stuck_chance) + return . -/obj/structure/spider/stickyweb/sealed/Initialize(mapload) - . = ..() - air_update_turf(TRUE, TRUE) +/// Show some feedback when you can't pass through something +/obj/structure/spider/stickyweb/proc/stuck_react(atom/movable/stuck_guy) + loc.balloon_alert(stuck_guy, "stuck in web!") + stuck_guy.Shake(duration = 0.1 SECONDS) -/obj/structure/spider/stickyweb/genetic //for the spider genes in genetics +/// Web made by geneticists, needs special handling to allow them to pass through their own webs +/obj/structure/spider/stickyweb/genetic genetic = TRUE + desc = "It's stringy, sticky, and came out of your coworker." + /// Mob with special permission to cross this web var/mob/living/allowed_mob /obj/structure/spider/stickyweb/genetic/Initialize(mapload, allowedmob) - allowed_mob = allowedmob . = ..() + // Tint it purple so that spiders don't get confused about why they can't cross this one + add_filter(SPIDER_WEB_TINT, 10, list("type" = "outline", "color" = "#ffaaf8ff", "size" = 0.1)) + +/obj/structure/spider/stickyweb/genetic/Initialize(mapload, allowedmob) + allowed_mob = allowedmob + return ..() /obj/structure/spider/stickyweb/genetic/CanAllowThrough(atom/movable/mover, border_dir) - . = ..() //this is the normal spider web return aka a spider would make this TRUE + . = ..() if(mover == allowed_mob) return TRUE else if(isliving(mover)) //we change the spider to not be able to go through here if(mover.pulledby == allowed_mob) return TRUE if(prob(50)) - loc.balloon_alert(mover, "stuck in web!") + stuck_react(mover) return FALSE else if(isprojectile(mover)) return prob(30) + return . -/obj/structure/spider/solid - name = "solid web" - icon = 'icons/effects/effects.dmi' - desc = "A solid wall of web, thick enough to block air flow." - icon_state = "solidweb" +/// Web with a 100% chance to intercept movement +/obj/structure/spider/stickyweb/very_sticky + max_integrity = 20 + desc = "Extremely sticky silk, you're not easily getting through there." + stuck_chance = 100 + projectile_stuck_chance = 100 + +/obj/structure/spider/stickyweb/very_sticky/Initialize(mapload) + . = ..() + add_filter(SPIDER_WEB_TINT, 10, list("type" = "outline", "color" = "#ffffaaff", "size" = 0.1)) + +/obj/structure/spider/stickyweb/very_sticky/update_overlays() + . = ..() + var/mutable_appearance/web_overlay = mutable_appearance(icon = 'icons/effects/web.dmi', icon_state = "sticky_overlay", layer = layer + 1) + web_overlay.pixel_x -= pixel_x + web_overlay.pixel_y -= pixel_y + . += web_overlay + + +/// Web 'wall' +/obj/structure/spider/stickyweb/sealed + name = "sealed web" + desc = "A solid wall of web, dense enough to block air flow." + icon = 'icons/obj/smooth_structures/webwall.dmi' + base_icon_state = "webwall" + icon_state = "webwall-0" + smoothing_groups = SMOOTH_GROUP_SPIDER_WEB_WALL + canSmoothWith = SMOOTH_GROUP_SPIDER_WEB_WALL + plane = GAME_PLANE + layer = OBJ_LAYER + sealed = TRUE + has_frill = FALSE can_atmos_pass = ATMOS_PASS_NO + +/obj/structure/spider/stickyweb/sealed/Initialize(mapload) + . = ..() + air_update_turf(TRUE, TRUE) + +/// Walls which reflects lasers +/obj/structure/spider/stickyweb/sealed/reflector + name = "reflective silk screen" + desc = "Hardened webbing treated with special chemicals which cause it to repel projectiles." + icon = 'icons/obj/smooth_structures/webwall_reflector.dmi' + base_icon_state = "webwall_reflector" + icon_state = "webwall_reflector-0" + smoothing_groups = SMOOTH_GROUP_SPIDER_WEB_WALL_MIRROR + canSmoothWith = SMOOTH_GROUP_SPIDER_WEB_WALL_MIRROR + max_integrity = 30 + opacity = TRUE + flags_ricochet = RICOCHET_SHINY | RICOCHET_HARD + receive_ricochet_chance_mod = INFINITY + +/// Opaque and durable web 'wall' +/obj/structure/spider/stickyweb/sealed/tough + name = "hardened web" + desc = "Webbing hardened through a chemical process into a durable barrier." + icon = 'icons/obj/smooth_structures/webwall_dark.dmi' + base_icon_state = "webwall_dark" + icon_state = "webwall_dark-0" + smoothing_groups = SMOOTH_GROUP_SPIDER_WEB_WALL_TOUGH + canSmoothWith = SMOOTH_GROUP_SPIDER_WEB_WALL_TOUGH opacity = TRUE - density = TRUE max_integrity = 90 layer = ABOVE_MOB_LAYER resistance_flags = FIRE_PROOF | FREEZE_PROOF -/obj/structure/spider/solid/Initialize(mapload) - . = ..() - air_update_turf(TRUE, TRUE) - +/// Web 'door', blocks atmos but not movement /obj/structure/spider/passage name = "web passage" - icon = 'icons/effects/effects.dmi' - desc = "A messy connection of webs blocking the other side, but not solid enough to prevent passage." - icon_state = "webpassage" + desc = "An opaque curtain of web which seals in air but doesn't impede passage." + icon = 'icons/obj/smooth_structures/stickyweb_rotated.dmi' + base_icon_state = "stickyweb_rotated" + icon_state = "stickyweb_rotated-0" + smoothing_flags = SMOOTH_BITMASK + smoothing_groups = SMOOTH_GROUP_SPIDER_WEB_ROOF + canSmoothWith = SMOOTH_GROUP_SPIDER_WEB_ROOF + SMOOTH_GROUP_WALLS can_atmos_pass = ATMOS_PASS_NO opacity = TRUE max_integrity = 60 @@ -135,7 +211,10 @@ /obj/structure/spider/passage/Initialize(mapload) . = ..() + pixel_x = -9 + pixel_y = -9 air_update_turf(TRUE, TRUE) + add_filter(SPIDER_WEB_TINT, 10, list("type" = "outline", "color" = "#ffffffff", "alpha" = 0.8, "size" = 0.1)) /obj/structure/spider/cocoon name = "cocoon" @@ -165,56 +244,31 @@ A.forceMove(T) return ..() -/obj/structure/spider/sticky - name = "sticky web" - icon = 'icons/effects/effects.dmi' - desc = "Extremely soft and sticky silk." - icon_state = "verystickyweb" - max_integrity = 20 - -/obj/structure/spider/sticky/CanAllowThrough(atom/movable/mover, border_dir) - . = ..() - if(HAS_TRAIT(mover, TRAIT_WEB_SURFER)) - return TRUE - if(!isliving(mover)) - return - if(!isnull(mover.pulledby) && HAS_TRAIT(mover.pulledby, TRAIT_WEB_SURFER)) - return TRUE - loc.balloon_alert(mover, "stuck in web!") - return FALSE - +/// Web caltrops /obj/structure/spider/spikes name = "web spikes" - icon = 'icons/effects/effects.dmi' desc = "Silk hardened into small yet deadly spikes." - icon_state = "webspikes1" + plane = FLOOR_PLANE + layer = MID_TURF_LAYER + icon = 'icons/obj/smooth_structures/stickyweb_spikes.dmi' + base_icon_state = "stickyweb_spikes" + icon_state = "stickyweb_spikes-0" + smoothing_flags = SMOOTH_BITMASK + smoothing_groups = SMOOTH_GROUP_SPIDER_WEB + canSmoothWith = SMOOTH_GROUP_SPIDER_WEB + SMOOTH_GROUP_WALLS max_integrity = 40 /obj/structure/spider/spikes/Initialize(mapload) . = ..() + pixel_x = -9 + pixel_y = -9 + add_filter(SPIDER_WEB_TINT, 10, list("type" = "outline", "color" = "#ac0000ff", "size" = 0.1)) AddComponent(/datum/component/caltrop, min_damage = 20, max_damage = 30, flags = CALTROP_NOSTUN | CALTROP_BYPASS_SHOES) -/obj/structure/spider/reflector - name = "Reflective silk screen" - icon = 'icons/effects/effects.dmi' - desc = "Made up of an extremly reflective silk material looking at it hurts." - icon_state = "reflector" - max_integrity = 30 - density = TRUE - opacity = TRUE - anchored = TRUE - flags_ricochet = RICOCHET_SHINY | RICOCHET_HARD - receive_ricochet_chance_mod = INFINITY - -/obj/structure/spider/reflector/Initialize(mapload) - . = ..() - air_update_turf(TRUE, TRUE) - /obj/structure/spider/effigy name = "web effigy" - icon = 'icons/effects/effects.dmi' desc = "A giant spider! Fortunately, this one is just a statue of hardened webbing." - icon_state = "webcarcass" + icon_state = "effigy" max_integrity = 125 density = TRUE anchored = FALSE @@ -222,3 +276,5 @@ /obj/structure/spider/effigy/Initialize(mapload) . = ..() AddElement(/datum/element/temporary_atom, 1 MINUTES) + +#undef SPIDER_WEB_TINT diff --git a/code/game/objects/effects/wanted_poster.dm b/code/game/objects/effects/wanted_poster.dm index 6859a185d6eaa3d..6cb36838fbcacae 100644 --- a/code/game/objects/effects/wanted_poster.dm +++ b/code/game/objects/effects/wanted_poster.dm @@ -93,9 +93,10 @@ poster_icon.Blend(letter_icon, ICON_OVERLAY) startX = startX + 4 -/obj/structure/sign/poster/wanted/roll_and_drop(atom/location) +/obj/structure/sign/poster/wanted/roll_and_drop(atom/location, mob/user) pixel_x = 0 pixel_y = 0 var/obj/item/poster/rolled_poster = new poster_item_type(location, original_icon, wanted_name, desc, posterHeaderText, posterHeaderColor) - forceMove(rolled_poster) + if(!user?.put_in_hands(rolled_poster)) + forceMove(rolled_poster) return rolled_poster diff --git a/code/game/objects/items/busts_and_figurines.dm b/code/game/objects/items/busts_and_figurines.dm new file mode 100644 index 000000000000000..afc4a58334e9050 --- /dev/null +++ b/code/game/objects/items/busts_and_figurines.dm @@ -0,0 +1,139 @@ +/obj/item/statuebust + name = "bust" + desc = "A priceless ancient marble bust, the kind that belongs in a museum." //or you can hit people with it + icon = 'icons/obj/art/statue.dmi' + icon_state = "bust" + force = 15 + throwforce = 10 + throw_speed = 5 + throw_range = 2 + attack_verb_continuous = list("busts") + attack_verb_simple = list("bust") + var/impressiveness = 45 + +/obj/item/statuebust/Initialize(mapload) + . = ..() + AddElement(/datum/element/art, impressiveness) + AddElement(/datum/element/beauty, 1000) + +/obj/item/statuebust/hippocratic + name = "hippocrates bust" + desc = "A bust of the famous Greek physician Hippocrates of Kos, often referred to as the father of western medicine." + icon_state = "hippocratic" + impressiveness = 50 + // If it hits the prob(reference_chance) chance, this is set to TRUE. Adds medical HUD when wielded, but has a 10% slower attack speed and is too bloody to make an oath with. + var/reference = FALSE + // Chance for above. + var/reference_chance = 1 + // Minimum time inbetween oaths. + COOLDOWN_DECLARE(oath_cd) + +/obj/item/statuebust/hippocratic/evil + reference_chance = 100 + +/obj/item/statuebust/hippocratic/Initialize(mapload) + . = ..() + if(prob(reference_chance)) + name = "Solemn Vow" + desc = "Art lovers will cherish the bust of Hippocrates, commemorating a time when medics still thought doing no harm was a good idea." + attack_speed = CLICK_CD_SLOW + reference = TRUE + +/obj/item/statuebust/hippocratic/examine(mob/user) + . = ..() + if(reference) + . += span_notice("You could activate the bust in-hand to swear or forswear a Hippocratic Oath... but it seems like somebody decided it was more of a Hippocratic Suggestion. This thing is caked with bits of blood and gore.") + return + . += span_notice("You can activate the bust in-hand to swear or forswear a Hippocratic Oath! This has no effects except pacifism or bragging rights. Does not remove other sources of pacifism. Do not eat.") + +/obj/item/statuebust/hippocratic/equipped(mob/living/carbon/human/user, slot) + ..() + if(!(slot & ITEM_SLOT_HANDS)) + return + var/datum/atom_hud/our_hud = GLOB.huds[DATA_HUD_MEDICAL_ADVANCED] + our_hud.show_to(user) + ADD_TRAIT(user, TRAIT_MEDICAL_HUD, type) + +/obj/item/statuebust/hippocratic/dropped(mob/living/carbon/human/user) + ..() + if(HAS_TRAIT_NOT_FROM(user, TRAIT_MEDICAL_HUD, type)) + return + var/datum/atom_hud/our_hud = GLOB.huds[DATA_HUD_MEDICAL_ADVANCED] + our_hud.hide_from(user) + REMOVE_TRAIT(user, TRAIT_MEDICAL_HUD, type) + +/obj/item/statuebust/hippocratic/attack_self(mob/user) + if(!iscarbon(user)) + to_chat(user, span_warning("You remember how the Hippocratic Oath specifies 'my fellow human beings' and realize that it's completely meaningless to you.")) + return + + if(reference) + to_chat(user, span_warning("As you prepare yourself to swear the Oath, you realize that doing so on a blood-caked bust is probably not a good idea.")) + return + + if(!COOLDOWN_FINISHED(src, oath_cd)) + to_chat(user, span_warning("You've sworn or forsworn an oath too recently to undo your decisions. The bust looks at you with disgust.")) + return + + COOLDOWN_START(src, oath_cd, 5 MINUTES) + + if(HAS_TRAIT_FROM(user, TRAIT_PACIFISM, type)) + to_chat(user, span_warning("You've already sworn a vow. You start preparing to rescind it...")) + if(do_after(user, 5 SECONDS, target = user)) + user.say("Yeah this Hippopotamus thing isn't working out. I quit!", forced = "hippocratic hippocrisy") + REMOVE_TRAIT(user, TRAIT_PACIFISM, type) + + // they can still do it for rp purposes + if(HAS_TRAIT_NOT_FROM(user, TRAIT_PACIFISM, type)) + to_chat(user, span_warning("You already don't want to harm people, this isn't going to do anything!")) + + + to_chat(user, span_notice("You remind yourself of the Hippocratic Oath's contents and prepare to swear yourself to it...")) + if(do_after(user, 4 SECONDS, target = user)) + user.say("I swear to fulfill, to the best of my ability and judgment, this covenant:", forced = "hippocratic oath") + else + return fuck_it_up(user) + if(do_after(user, 2 SECONDS, target = user)) + user.say("I will apply, for the benefit of the sick, all measures that are required, avoiding those twin traps of overtreatment and therapeutic nihilism.", forced = "hippocratic oath") + else + return fuck_it_up(user) + if(do_after(user, 3 SECONDS, target = user)) + user.say("I will remember that I remain a member of society, with special obligations to all my fellow human beings, those sound of mind and body as well as the infirm.", forced = "hippocratic oath") + else + + return fuck_it_up(user) + if(do_after(user, 3 SECONDS, target = user)) + user.say("If I do not violate this oath, may I enjoy life and art, respected while I live and remembered with affection thereafter. May I always act so as to preserve the finest traditions of my calling and may I long experience the joy of healing those who seek my help.", forced = "hippocratic oath") + else + return fuck_it_up(user) + + to_chat(user, span_notice("Contentment, understanding, and purpose washes over you as you finish the oath. You consider for a second the concept of harm and shudder.")) + ADD_TRAIT(user, TRAIT_PACIFISM, type) + +// Bully the guy for fucking up. +/obj/item/statuebust/hippocratic/proc/fuck_it_up(mob/living/carbon/user) + to_chat(user, span_warning("You forget what comes next like a dumbass. The Hippocrates bust looks down on you, disappointed.")) + user.adjustOrganLoss(ORGAN_SLOT_BRAIN, 2) + COOLDOWN_RESET(src, oath_cd) + +/obj/item/maneki_neko + name = "Maneki-Neko" + desc = "A figurine of a cat holding a coin, said to bring fortune and wealth, and perpetually moving its paw in a beckoning gesture." + icon = 'icons/obj/fluff/general.dmi' + icon_state = "maneki-neko" + w_class = WEIGHT_CLASS_SMALL + force = 5 + throwforce = 5 + throw_speed = 3 + throw_range = 5 + attack_verb_continuous = list("bashes", "beckons", "hit") + attack_verb_simple = list("bash", "beckon", "hit") + +/obj/item/maneki_neko/Initialize(mapload) + . = ..() + //Not compatible with greyscale configs because it's animated. + color = pick_weight(list(COLOR_WHITE = 3, COLOR_GOLD = 2, COLOR_DARK = 1)) + var/mutable_appearance/neko_overlay = mutable_appearance(icon, "maneki-neko-overlay", appearance_flags = RESET_COLOR) + add_overlay(neko_overlay) + AddElement(/datum/element/art, GOOD_ART) + AddElement(/datum/element/beauty, 800) diff --git a/code/game/objects/items/cards_ids.dm b/code/game/objects/items/cards_ids.dm index f655842e7caeb6f..d8b30eaa070eec5 100644 --- a/code/game/objects/items/cards_ids.dm +++ b/code/game/objects/items/cards_ids.dm @@ -125,9 +125,8 @@ /obj/item/card/id/Initialize(mapload) . = ..() - var/datum/bank_account/blank_bank_account = new /datum/bank_account("Unassigned", player_account = FALSE) + var/datum/bank_account/blank_bank_account = new("Unassigned", SSjob.GetJobType(/datum/job/unassigned), player_account = FALSE) registered_account = blank_bank_account - blank_bank_account.account_job = new /datum/job/unassigned registered_account.replaceable = TRUE // Applying the trim updates the label and icon, so don't do this twice. @@ -446,7 +445,7 @@ context[SCREENTIP_CONTEXT_RMB] = "Project pay stand" if(isnull(registered_account) || registered_account.replaceable) //Same check we use when we check if we can assign an account context[SCREENTIP_CONTEXT_ALT_RMB] = "Assign account" - if(!registered_account.replaceable || registered_account.account_balance > 0) + else if(registered_account.account_balance > 0) context[SCREENTIP_CONTEXT_ALT_LMB] = "Withdraw credits" return CONTEXTUAL_SCREENTIP_SET @@ -1234,7 +1233,7 @@ /obj/item/card/id/advanced/debug/Initialize(mapload) . = ..() registered_account = SSeconomy.get_dep_account(ACCOUNT_CAR) - registered_account.account_job = new /datum/job/admin // so we can actually use this account without being filtered as a "departmental" card + registered_account.account_job = SSjob.GetJobType(/datum/job/admin) // so we can actually use this account without being filtered as a "departmental" card /obj/item/card/id/advanced/prisoner name = "prisoner ID card" diff --git a/code/game/objects/items/cigs_lighters.dm b/code/game/objects/items/cigs_lighters.dm index a46732f171a518b..fef95b9b8226a44 100644 --- a/code/game/objects/items/cigs_lighters.dm +++ b/code/game/objects/items/cigs_lighters.dm @@ -744,7 +744,7 @@ CIGARETTE PACKETS ARE IN FANCY.DM custom_price = PAYCHECK_CREW * 1.1 light_system = OVERLAY_LIGHT light_range = 2 - light_power = 0.6 + light_power = 1.3 light_color = LIGHT_COLOR_FIRE light_on = FALSE /// Whether the lighter is lit. diff --git a/code/game/objects/items/devices/flashlight.dm b/code/game/objects/items/devices/flashlight.dm index 6ea3b516069f8e3..907bdbc9e22eefc 100644 --- a/code/game/objects/items/devices/flashlight.dm +++ b/code/game/objects/items/devices/flashlight.dm @@ -20,6 +20,7 @@ custom_materials = list(/datum/material/iron= SMALL_MATERIAL_AMOUNT * 0.5, /datum/material/glass= SMALL_MATERIAL_AMOUNT * 0.2) actions_types = list(/datum/action/item_action/toggle_light) light_system = OVERLAY_LIGHT_DIRECTIONAL + light_color = COLOR_LIGHT_ORANGE light_range = 4 light_power = 1 light_on = FALSE @@ -95,7 +96,7 @@ return light_on != old_light_on // If the value of light_on didn't change, return false. Otherwise true. /obj/item/flashlight/attack_self(mob/user) - toggle_light(user) + return toggle_light(user) /obj/item/flashlight/attack_hand_secondary(mob/user, list/modifiers) attack_self(user) @@ -295,6 +296,8 @@ w_class = WEIGHT_CLASS_TINY obj_flags = CONDUCTS_ELECTRICITY light_range = 2 + light_power = 0.8 + light_color = "#CCFFFF" COOLDOWN_DECLARE(holosign_cooldown) /obj/item/flashlight/pen/afterattack(atom/target, mob/user, proximity_flag) @@ -352,6 +355,8 @@ righthand_file = 'icons/mob/inhands/equipment/security_righthand.dmi' force = 9 // Not as good as a stun baton. light_range = 5 // A little better than the standard flashlight. + light_power = 0.8 + light_color = "#99ccff" hitsound = 'sound/weapons/genhit1.ogg' // the desk lamps are a bit special @@ -398,6 +403,7 @@ heat = 1000 light_color = LIGHT_COLOR_FLARE light_system = OVERLAY_LIGHT + light_power = 2 grind_results = list(/datum/reagent/sulfur = 15) sound_on = 'sound/items/match_strike.ogg' toggle_context = FALSE @@ -416,7 +422,7 @@ /obj/item/flashlight/flare/Initialize(mapload) . = ..() if(randomize_fuel) - fuel = rand(25 MINUTES, 35 MINUTES) + fuel = rand(10 MINUTES, 15 MINUTES) if(light_on) attack_verb_continuous = string_list(list("burns", "singes")) attack_verb_simple = string_list(list("burn", "singe")) @@ -523,8 +529,9 @@ righthand_file = 'icons/mob/inhands/items_righthand.dmi' w_class = WEIGHT_CLASS_TINY heat = 1000 - light_color = LIGHT_COLOR_FIRE light_range = 2 + light_power = 1.5 + light_color = LIGHT_COLOR_FIRE fuel = 35 MINUTES randomize_fuel = FALSE trash_type = /obj/item/trash/candle @@ -638,6 +645,7 @@ name = "torch" desc = "A torch fashioned from some leaves and a log." light_range = 4 + light_power = 1.3 icon_state = "torch" inhand_icon_state = "torch" lefthand_file = 'icons/mob/inhands/items_lefthand.dmi' @@ -655,20 +663,24 @@ lefthand_file = 'icons/mob/inhands/equipment/mining_lefthand.dmi' righthand_file = 'icons/mob/inhands/equipment/mining_righthand.dmi' desc = "A mining lantern." - light_range = 6 // luminosity when on + light_range = 5 // luminosity when on + light_power = 1.5 + light_color = "#ffcc66" light_system = OVERLAY_LIGHT /obj/item/flashlight/lantern/heirloom_moth name = "old lantern" desc = "An old lantern that has seen plenty of use." - light_range = 4 + light_range = 3.5 /obj/item/flashlight/lantern/syndicate name = "suspicious lantern" desc = "A suspicious looking lantern." icon_state = "syndilantern" inhand_icon_state = "syndilantern" - light_range = 10 + light_range = 6 + light_power = 2 + light_color = "#ffffe6" /obj/item/flashlight/lantern/jade name = "jade lantern" @@ -686,7 +698,8 @@ w_class = WEIGHT_CLASS_SMALL slot_flags = ITEM_SLOT_BELT custom_materials = null - light_range = 7 //luminosity when on + light_range = 6 //luminosity when on + light_color = "#ffff66" light_system = OVERLAY_LIGHT /obj/item/flashlight/emp @@ -746,13 +759,14 @@ emp_cur_charges = 100 // Glowsticks, in the uncomfortable range of similar to flares, -// but not similar enough to make it worth a refactor +// Flares need to process (for hotspots) tho so this becomes irrelevant /obj/item/flashlight/glowstick name = "glowstick" desc = "A military-grade glowstick." custom_price = PAYCHECK_LOWER w_class = WEIGHT_CLASS_SMALL - light_range = 4 + light_range = 3.5 + light_power = 2 light_system = OVERLAY_LIGHT color = LIGHT_COLOR_GREEN icon_state = "glowstick" @@ -764,35 +778,74 @@ toggle_context = FALSE /// How many seconds of fuel we have left var/fuel = 0 + /// How much max fuel we have + var/max_fuel = 0 + /// The timer id powering our burning + var/timer_id = TIMER_ID_NULL /obj/item/flashlight/glowstick/Initialize(mapload) - fuel = rand(50 MINUTES, 60 MINUTES) + fuel = rand(20 MINUTES, 25 MINUTES) + max_fuel = fuel set_light_color(color) return ..() -/obj/item/flashlight/glowstick/Destroy() - STOP_PROCESSING(SSobj, src) - return ..() - -/obj/item/flashlight/glowstick/process(seconds_per_tick) - fuel = max(fuel - seconds_per_tick * (1 SECONDS), 0) - if(fuel <= 0) +/// Burns down the glowstick by the specified time +/// Returns the amount of time we need to burn before a visual change will occur +/obj/item/flashlight/glowstick/proc/burn_down(amount = 0) + fuel -= amount + var/fuel_target = 0 + if(fuel >= max_fuel) + fuel_target = max_fuel * 0.4 + else if(fuel >= max_fuel * 0.4) + fuel_target = max_fuel * 0.3 + set_light_range(3) + set_light_power(1.5) + else if(fuel >= max_fuel * 0.3) + fuel_target = max_fuel * 0.2 + set_light_range(2) + set_light_power(1.25) + else if(fuel >= max_fuel * 0.2) + fuel_target = max_fuel * 0.1 + set_light_power(1) + else if(fuel >= max_fuel * 0.1) + fuel_target = 0 + set_light_range(1.5) + set_light_power(0.5) + + var/time_to_burn = round(fuel - fuel_target) + // Less then a ds? go home + if(time_to_burn <= 0) turn_off() - STOP_PROCESSING(SSobj, src) + + return time_to_burn + +/obj/item/flashlight/glowstick/proc/burn_loop(amount = 0) + timer_id = TIMER_ID_NULL + var/burn_next = burn_down(amount) + if(burn_next <= 0) + return + timer_id = addtimer(CALLBACK(src, PROC_REF(burn_loop), burn_next), burn_next, TIMER_UNIQUE|TIMER_STOPPABLE|TIMER_OVERRIDE) + +/obj/item/flashlight/glowstick/proc/turn_on() + set_light_on(TRUE) // Just in case + var/datum/action/toggle = locate(/datum/action/item_action/toggle_light) in actions + // No sense having a toggle light action that we don't use eh? + if(toggle) + remove_item_action(toggle) + burn_loop() /obj/item/flashlight/glowstick/proc/turn_off() + var/datum/action/toggle = locate(/datum/action/item_action/toggle_light) in actions + if(fuel && !toggle) + add_item_action(/datum/action/item_action/toggle_light) + if(timer_id != TIMER_ID_NULL) + var/expected_burn_time = burn_down(0) // This is dumb I'm sorry + burn_down(expected_burn_time - timeleft(timer_id)) + deltimer(timer_id) + timer_id = TIMER_ID_NULL set_light_on(FALSE) update_appearance(UPDATE_ICON) -/obj/item/flashlight/glowstick/update_appearance(updates=ALL) - . = ..() - if(fuel <= 0) - set_light_on(FALSE) - return - if(light_on) - set_light_on(TRUE) - return - /obj/item/flashlight/glowstick/update_icon_state() . = ..() icon_state = "[base_icon_state][(fuel <= 0) ? "-empty" : ""]" @@ -807,6 +860,13 @@ glowstick_overlay.color = color . += glowstick_overlay +/obj/item/flashlight/glowstick/toggle_light(mob/user) + if(fuel <= 0) + return FALSE + if(light_on) + return FALSE + return ..() + /obj/item/flashlight/glowstick/attack_self(mob/user) if(fuel <= 0) balloon_alert(user, "glowstick is spent!") @@ -818,7 +878,7 @@ . = ..() if(.) user.visible_message(span_notice("[user] cracks and shakes [src]."), span_notice("You crack and shake [src], turning it on!")) - START_PROCESSING(SSobj, src) + turn_on() /obj/item/flashlight/glowstick/suicide_act(mob/living/carbon/human/user) if(!fuel) @@ -829,7 +889,7 @@ user.visible_message(span_suicide("[user] is trying to squirt [src]'s fluids into [user.p_their()] eyes... but [user.p_they()] don't have any!")) return SHAME user.visible_message(span_suicide("[user] is squirting [src]'s fluids into [user.p_their()] eyes! It looks like [user.p_theyre()] trying to commit suicide!")) - fuel = 0 + burn_loop(fuel) return FIRELOSS /obj/item/flashlight/glowstick/red @@ -862,7 +922,7 @@ icon_state = null light_system = OVERLAY_LIGHT light_range = 4 - light_power = 10 + light_power = 2 alpha = 0 plane = FLOOR_PLANE anchored = TRUE @@ -907,9 +967,6 @@ /obj/item/flashlight/eyelight name = "eyelight" desc = "This shouldn't exist outside of someone's head, how are you seeing this?" - light_system = OVERLAY_LIGHT - light_range = 15 - light_power = 1 obj_flags = CONDUCTS_ELECTRICITY item_flags = DROPDEL actions_types = list() diff --git a/code/game/objects/items/devices/radio/headset.dm b/code/game/objects/items/devices/radio/headset.dm index 08bf47dcc073ee1..4d6b8edbd2dd20b 100644 --- a/code/game/objects/items/devices/radio/headset.dm +++ b/code/game/objects/items/devices/radio/headset.dm @@ -250,6 +250,14 @@ GLOBAL_LIST_INIT(channel_tokens, list( worn_icon_state = "com_headset" keyslot = /obj/item/encryptionkey/heads/hos +/obj/item/radio/headset/heads/hos/advisor + name = "\proper the veteran security advisor headset" + desc = "The headset of the man who was in charge of keeping order and protecting the station..." + icon_state = "com_headset" + worn_icon_state = "com_headset" + keyslot = /obj/item/encryptionkey/heads/hos + command = FALSE + /obj/item/radio/headset/heads/hos/alt name = "\proper the head of security's bowman headset" desc = "The headset of the man in charge of keeping order and protecting the station. Protects ears from flashbangs." diff --git a/code/game/objects/items/devices/radio/radio.dm b/code/game/objects/items/devices/radio/radio.dm index 85a027935fd6404..72e50014ca2799a 100644 --- a/code/game/objects/items/devices/radio/radio.dm +++ b/code/game/objects/items/devices/radio/radio.dm @@ -120,6 +120,8 @@ slapcraft_recipes = list(/datum/crafting_recipe/improv_explosive)\ ) + RegisterSignal(src, COMSIG_HIT_BY_SABOTEUR, PROC_REF(on_saboteur)) + /obj/item/radio/Destroy() remove_radio_all(src) //Just to be sure QDEL_NULL(wires) @@ -127,6 +129,12 @@ QDEL_NULL(keyslot) return ..() +/obj/item/radio/proc/on_saboteur(datum/source, disrupt_duration) + SIGNAL_HANDLER + if(broadcasting) //no broadcasting but it can still be used to send radio messages. + set_broadcasting(FALSE) + return COMSIG_SABOTEUR_SUCCESS + /obj/item/radio/proc/set_frequency(new_frequency) SEND_SIGNAL(src, COMSIG_RADIO_NEW_FREQUENCY, args) remove_radio(src, frequency) diff --git a/code/game/objects/items/devices/scanners/health_analyzer.dm b/code/game/objects/items/devices/scanners/health_analyzer.dm index 8c90569bb91d0cc..7f672e7d32a53fc 100644 --- a/code/game/objects/items/devices/scanners/health_analyzer.dm +++ b/code/game/objects/items/devices/scanners/health_analyzer.dm @@ -33,7 +33,8 @@ /obj/item/healthanalyzer/examine(mob/user) . = ..() - . += span_notice("Alt-click [src] to toggle the limb damage readout.") + if(src.mode != SCANNER_NO_MODE) + . += span_notice("Alt-click [src] to toggle the limb damage readout.") /obj/item/healthanalyzer/suicide_act(mob/living/carbon/user) user.visible_message(span_suicide("[user] begins to analyze [user.p_them()]self with [src]! The display shows that [user.p_theyre()] dead!")) diff --git a/code/game/objects/items/extinguisher.dm b/code/game/objects/items/extinguisher.dm index b571688f1a877e1..5a6dc49b09b6eb9 100644 --- a/code/game/objects/items/extinguisher.dm +++ b/code/game/objects/items/extinguisher.dm @@ -279,13 +279,8 @@ /obj/item/extinguisher/proc/EmptyExtinguisher(mob/user) if(loc == user && reagents.total_volume) + reagents.expose(user.loc, TOUCH) reagents.clear_reagents() - - var/turf/T = get_turf(loc) - if(isopenturf(T)) - var/turf/open/theturf = T - theturf.MakeSlippery(TURF_WET_WATER, min_wet_time = 10 SECONDS, wet_time_to_add = 5 SECONDS) - user.visible_message(span_notice("[user] empties out \the [src] onto the floor using the release valve."), span_info("You quietly empty out \the [src] using its release valve.")) //firebot assembly @@ -297,3 +292,10 @@ user.put_in_hands(new /obj/item/bot_assembly/firebot) else ..() + +/obj/item/extinguisher/anti + name = "fire extender" + desc = "A traditional red fire extinguisher. Made in Britain... wait, what?" + chem = /datum/reagent/fuel + tanktype = /obj/structure/reagent_dispensers/fueltank + cooling_power = 0 diff --git a/code/game/objects/items/flamethrower.dm b/code/game/objects/items/flamethrower.dm index 1a31c5d58a219d7..1564e4e40298add 100644 --- a/code/game/objects/items/flamethrower.dm +++ b/code/game/objects/items/flamethrower.dm @@ -16,6 +16,9 @@ resistance_flags = FIRE_PROOF trigger_guard = TRIGGER_GUARD_NORMAL light_system = OVERLAY_LIGHT + light_color = LIGHT_COLOR_FLARE + light_range = 2 + light_power = 2 light_on = FALSE var/status = FALSE var/lit = FALSE //on or off @@ -82,12 +85,13 @@ return // too close if(HAS_TRAIT(user, TRAIT_PACIFISM)) to_chat(user, span_warning("You can't bring yourself to fire \the [src]! You don't want to risk harming anyone...")) + log_combat(user, target, "attempted to flamethrower", src, "with gas mixture: {[print_gas_mixture(ptank.return_analyzable_air())]}, flamethrower: \"[name]\" ([src]), igniter: \"[igniter.name]\", tank: \"[ptank.name]\" and tank distribution pressure: \"[siunit(1000 * ptank.distribute_pressure, unit = "Pa", maxdecimals = INFINITY)]\"" + lit ? " while lit" : "" + " but failed due to pacifism.") return if(user && user.get_active_held_item() == src) // Make sure our user is still holding us var/turf/target_turf = get_turf(target) if(target_turf) var/turflist = get_line(user, target_turf) - log_combat(user, target, "flamethrowered", src) + log_combat(user, target, "flamethrowered", src, "with gas mixture: {[print_gas_mixture(ptank.return_analyzable_air())]}, flamethrower: \"[name]\", igniter: \"[igniter.name]\", tank: \"[ptank.name]\" and tank distribution pressure: \"[siunit(1000 * ptank.distribute_pressure, unit = "Pa", maxdecimals = INFINITY)]\"" + lit ? " while lit." : ".") flame_turf(turflist) /obj/item/flamethrower/wrench_act(mob/living/user, obj/item/tool) diff --git a/code/game/objects/items/food/bread.dm b/code/game/objects/items/food/bread.dm index ba1845bb40da4a1..0f95aac6d852855 100644 --- a/code/game/objects/items/food/bread.dm +++ b/code/game/objects/items/food/bread.dm @@ -481,6 +481,7 @@ foodtypes = GRAIN | DAIRY w_class = WEIGHT_CLASS_SMALL crafting_complexity = FOOD_COMPLEXITY_2 + custom_price = PAYCHECK_CREW /obj/item/food/butterdog/Initialize(mapload) . = ..() diff --git a/code/game/objects/items/food/frozen.dm b/code/game/objects/items/food/frozen.dm index 0bd0cd3a60620d8..27052507bfd4a88 100644 --- a/code/game/objects/items/food/frozen.dm +++ b/code/game/objects/items/food/frozen.dm @@ -12,6 +12,7 @@ foodtypes = GRAIN | DAIRY | SUGAR food_flags = FOOD_FINGER_FOOD crafting_complexity = FOOD_COMPLEXITY_2 + crafted_food_buff = /datum/status_effect/food/chilling /obj/item/food/strawberryicecreamsandwich name = "strawberry ice cream sandwich" @@ -27,7 +28,7 @@ foodtypes = FRUIT | DAIRY | SUGAR food_flags = FOOD_FINGER_FOOD crafting_complexity = FOOD_COMPLEXITY_3 - + crafted_food_buff = /datum/status_effect/food/chilling /obj/item/food/spacefreezy name = "space freezy" @@ -43,6 +44,7 @@ tastes = list("blue cherries" = 2, "ice cream" = 2) foodtypes = FRUIT | DAIRY | SUGAR crafting_complexity = FOOD_COMPLEXITY_3 + crafted_food_buff = /datum/status_effect/food/chilling /obj/item/food/spacefreezy/make_edible() . = ..() @@ -62,6 +64,7 @@ tastes = list("ice cream" = 1, "banana" = 1) foodtypes = FRUIT | DAIRY | SUGAR crafting_complexity = FOOD_COMPLEXITY_3 + crafted_food_buff = /datum/status_effect/food/chilling /obj/item/food/sundae/make_edible() . = ..() @@ -81,6 +84,7 @@ tastes = list("ice cream" = 1, "banana" = 1, "a bad joke" = 1) foodtypes = FRUIT | DAIRY | SUGAR crafting_complexity = FOOD_COMPLEXITY_4 + crafted_food_buff = /datum/status_effect/food/chilling /obj/item/food/honkdae/make_edible() . = ..() @@ -104,6 +108,7 @@ foodtypes = SUGAR //We use SUGAR as a base line to act in as junkfood, other wise we use fruit food_flags = FOOD_FINGER_FOOD crafting_complexity = FOOD_COMPLEXITY_2 + crafted_food_buff = /datum/status_effect/food/chilling /obj/item/food/snowcones/lime name = "lime snowcone" @@ -330,6 +335,7 @@ foodtypes = DAIRY | SUGAR food_flags = FOOD_FINGER_FOOD crafting_complexity = FOOD_COMPLEXITY_3 + crafted_food_buff = /datum/status_effect/food/chilling var/overlay_state = "creamsicle_o" //This is the edible part of the popsicle. var/bite_states = 4 //This value value is used for correctly setting the bite_consumption to ensure every bite changes the sprite. Do not set to zero. @@ -434,6 +440,7 @@ foodtypes = DAIRY | SUGAR venue_value = FOOD_PRICE_NORMAL crafting_complexity = FOOD_COMPLEXITY_3 + crafted_food_buff = /datum/status_effect/food/chilling /obj/item/food/popsicle/meatsicle name = "Meatsicle" diff --git a/code/game/objects/items/food/lizard.dm b/code/game/objects/items/food/lizard.dm index 729ad4d38a97154..47b5ff751091685 100644 --- a/code/game/objects/items/food/lizard.dm +++ b/code/game/objects/items/food/lizard.dm @@ -34,6 +34,7 @@ foodtypes = MEAT w_class = WEIGHT_CLASS_SMALL crafting_complexity = FOOD_COMPLEXITY_2 + custom_price = PAYCHECK_CREW /obj/item/food/raw_headcheese name = "raw headcheese block" diff --git a/code/game/objects/items/food/martian.dm b/code/game/objects/items/food/martian.dm index 2441ac0f67478c6..7ceaf1878176c6b 100644 --- a/code/game/objects/items/food/martian.dm +++ b/code/game/objects/items/food/martian.dm @@ -732,6 +732,7 @@ foodtypes = MEAT | VEGETABLES | FRUIT | PINEAPPLE w_class = WEIGHT_CLASS_SMALL crafting_complexity = FOOD_COMPLEXITY_4 + custom_price = PAYCHECK_CREW * 1.2 /obj/item/food/salt_chilli_fries name = "salt n' chilli fries" @@ -1210,6 +1211,7 @@ foodtypes = FRUIT | MEAT | PINEAPPLE | VEGETABLES | GRAIN w_class = WEIGHT_CLASS_SMALL crafting_complexity = FOOD_COMPLEXITY_4 //Uses Sambal + custom_price = PAYCHECK_CREW * 2 /obj/item/food/frickles name = "frickles" diff --git a/code/game/objects/items/food/meatdish.dm b/code/game/objects/items/food/meatdish.dm index b9a6c34df04edd1..537c7688d2dd4ac 100644 --- a/code/game/objects/items/food/meatdish.dm +++ b/code/game/objects/items/food/meatdish.dm @@ -554,6 +554,7 @@ w_class = WEIGHT_CLASS_SMALL venue_value = FOOD_PRICE_CHEAP crafting_complexity = FOOD_COMPLEXITY_2 + custom_price = PAYCHECK_CREW * 0.6 /obj/item/food/sausage/make_processable() AddElement(/datum/element/processable, TOOL_KNIFE, /obj/item/food/salami, 6, 3 SECONDS, table_required = TRUE, screentip_verb = "Slice") @@ -734,6 +735,7 @@ foodtypes = MEAT | DAIRY | GRAIN w_class = WEIGHT_CLASS_TINY crafting_complexity = FOOD_COMPLEXITY_3 + custom_price = PAYCHECK_CREW /obj/item/food/bbqribs name = "bbq ribs" @@ -750,19 +752,6 @@ foodtypes = MEAT | SUGAR crafting_complexity = FOOD_COMPLEXITY_2 -///Special private component to handle how bbq is grilled, not meant to be used anywhere else -/datum/component/grillable/bbq - -/datum/component/grillable/bbq/finish_grilling(atom/grill_source) - //when on a grill allow it to roast without deleting itself - if(istype(grill_source, /obj/machinery/grill)) - grill_source.visible_message(span_notice("[parent] is grilled to perfection!")) - else //when on a girddle allow it to burn into an mouldy mess - return ..() - -/obj/item/food/bbqribs/make_grillable() - AddComponent(/datum/component/grillable/bbq, /obj/item/food/badrecipe, rand(30 SECONDS, 40 SECONDS), FALSE) - /obj/item/food/meatclown name = "meat clown" desc = "A delicious, round piece of meat clown. How horrifying." diff --git a/code/game/objects/items/food/pastries.dm b/code/game/objects/items/food/pastries.dm index 277e6efaff8950b..e1449007b71d482 100644 --- a/code/game/objects/items/food/pastries.dm +++ b/code/game/objects/items/food/pastries.dm @@ -77,6 +77,10 @@ w_class = WEIGHT_CLASS_SMALL crafting_complexity = FOOD_COMPLEXITY_2 +/obj/item/food/waffles/make_edible() + . = ..() + AddComponent(/datum/component/ice_cream_holder, max_scoops = 1, x_offset = -2) + /obj/item/food/soylentgreen name = "\improper Soylent Green" desc = "Not made of people. Honest." //Totally people. @@ -123,6 +127,10 @@ w_class = WEIGHT_CLASS_SMALL crafting_complexity = FOOD_COMPLEXITY_3 +/obj/item/food/rofflewaffles/make_edible() + . = ..() + AddComponent(/datum/component/ice_cream_holder, max_scoops = 1, x_offset = -2) + ////////////////////////////////////////////OTHER//////////////////////////////////////////// /obj/item/food/cookie @@ -356,7 +364,7 @@ bite_consumption = 4 foodtypes = DAIRY | SUGAR food_flags = FOOD_FINGER_FOOD - crafting_complexity = FOOD_COMPLEXITY_3 + crafting_complexity = FOOD_COMPLEXITY_2 max_volume = 10 //The max volumes scales up with the number of scoops of ice cream served. /// These two variables are used by the ice cream vat. Latter is the one that shows on the UI. var/list/ingredients = list( @@ -371,14 +379,10 @@ */ var/list/prefill_flavours -/obj/item/food/icecream/New(loc, list/prefill_flavours) +/obj/item/food/icecream/Initialize(mapload, list/prefill_flavours) if(ingredients) ingredients_text = "Requires: [reagent_paths_list_to_text(ingredients)]" - return ..() - -/obj/item/food/icecream/Initialize(mapload, list/prefill_flavours) - if(prefill_flavours) - src.prefill_flavours = prefill_flavours + src.prefill_flavours = prefill_flavours return ..() /obj/item/food/icecream/make_edible() @@ -398,7 +402,6 @@ /datum/reagent/consumable/sugar, /datum/reagent/consumable/coco, ) - crafting_complexity = FOOD_COMPLEXITY_3 /obj/item/food/icecream/korta name = "korta cone" diff --git a/code/game/objects/items/food/sandwichtoast.dm b/code/game/objects/items/food/sandwichtoast.dm index c6488f67a1ed501..e440a1039e6d177 100644 --- a/code/game/objects/items/food/sandwichtoast.dm +++ b/code/game/objects/items/food/sandwichtoast.dm @@ -152,6 +152,7 @@ w_class = WEIGHT_CLASS_SMALL venue_value = FOOD_PRICE_CHEAP crafting_complexity = FOOD_COMPLEXITY_3 + custom_price = PAYCHECK_CREW * 0.7 // Used for unit tests, do not delete /obj/item/food/hotdog/debug @@ -174,6 +175,7 @@ w_class = WEIGHT_CLASS_SMALL venue_value = FOOD_PRICE_NORMAL crafting_complexity = FOOD_COMPLEXITY_4 + custom_price = PAYCHECK_CREW /obj/item/food/sandwich/blt name = "\improper BLT" diff --git a/code/game/objects/items/implants/implant_explosive.dm b/code/game/objects/items/implants/implant_explosive.dm index 25966a24c68ead9..51564799f6e44fc 100644 --- a/code/game/objects/items/implants/implant_explosive.dm +++ b/code/game/objects/items/implants/implant_explosive.dm @@ -19,6 +19,8 @@ var/active = FALSE ///The final countdown (delay before we explode) var/delay = MICROBOMB_DELAY + ///If the delay is equal or lower to MICROBOMB_DELAY (0.7 sec), the explosion will be instantaneous. + var/instant_explosion = TRUE ///Radius of weak devastation explosive impact var/explosion_light = MICROBOMB_EXPLOSION_LIGHT ///Radius of medium devastation explosive impact @@ -33,7 +35,8 @@ var/no_paralyze = FALSE ///Do we override other explosive implants? var/master_implant = FALSE - + ///Will this implant notify ghosts when activated? + var/notify_ghosts = TRUE /obj/item/implant/explosive/proc/on_death(datum/source, gibbed) SIGNAL_HANDLER @@ -73,7 +76,7 @@ var/turf/boomturf = get_turf(imp_in) message_admins("[ADMIN_LOOKUPFLW(imp_in)] has activated their [name] at [ADMIN_VERBOSEJMP(boomturf)], with cause of [cause].") //If the delay is shorter or equal to the default delay, just blow up already jeez - if(delay <= MICROBOMB_DELAY) + if(delay <= MICROBOMB_DELAY && instant_explosion) explode() return timed_explosion() @@ -119,14 +122,15 @@ /obj/item/implant/explosive/proc/timed_explosion() imp_in.visible_message(span_warning("[imp_in] starts beeping ominously!")) - notify_ghosts( - "[imp_in] is about to detonate their explosive implant!", - source = src, - header = "Tick Tick Tick...", - notify_flags = NOTIFY_CATEGORY_NOFLASH, - ghost_sound = 'sound/machines/warning-buzzer.ogg', - notify_volume = 75, - ) + if(notify_ghosts) + notify_ghosts( + "[imp_in] is about to detonate their explosive implant!", + source = src, + header = "Tick Tick Tick...", + notify_flags = NOTIFY_CATEGORY_NOFLASH, + ghost_sound = 'sound/machines/warning-buzzer.ogg', + notify_volume = 75, + ) playsound(loc, 'sound/items/timer.ogg', 30, FALSE) if(!panic_beep_sound) @@ -203,6 +207,13 @@ if(source.health < source.crit_threshold) INVOKE_ASYNC(src, PROC_REF(activate), "deniability") +/obj/item/implant/explosive/deathmatch + name = "deathmatch microbomb implant" + delay = 0.5 SECONDS + actions_types = null + instant_explosion = FALSE + notify_ghosts = FALSE + /obj/item/implanter/explosive name = "implanter (microbomb)" imp_type = /obj/item/implant/explosive diff --git a/code/game/objects/items/melee/baton.dm b/code/game/objects/items/melee/baton.dm index d79714c1b68d8e0..907176bc9b90824 100644 --- a/code/game/objects/items/melee/baton.dm +++ b/code/game/objects/items/melee/baton.dm @@ -454,6 +454,7 @@ else cell = new preload_cell_type(src) RegisterSignal(src, COMSIG_ATOM_ATTACKBY, PROC_REF(convert)) + RegisterSignal(src, COMSIG_HIT_BY_SABOTEUR, PROC_REF(on_saboteur)) update_appearance() /obj/item/melee/baton/security/get_cell() @@ -488,6 +489,14 @@ qdel(item) qdel(src) +/obj/item/melee/baton/security/proc/on_saboteur(datum/source, disrupt_duration) + SIGNAL_HANDLER + if(!active) + return + toggle_light() + active = FALSE + update_appearance() + return COMSIG_SABOTEUR_SUCCESS /obj/item/melee/baton/security/Exited(atom/movable/mov_content) . = ..() if(mov_content == cell) diff --git a/code/game/objects/items/piggy_bank.dm b/code/game/objects/items/piggy_bank.dm new file mode 100644 index 000000000000000..012ff91b0216c84 --- /dev/null +++ b/code/game/objects/items/piggy_bank.dm @@ -0,0 +1,129 @@ +/** + * Piggy banks. They store your hard-earned money until you or someone destroys it. + * If the persistence id is set, money will be carried between rounds until broken. + */ +/obj/item/piggy_bank + name = "piggy bank" + desc = "A pig-shaped money container made of porkelain, oink. Do not throw." //pun very intended. + icon = 'icons/obj/fluff/general.dmi' + icon_state = "piggy_bank" + max_integrity = 8 + w_class = WEIGHT_CLASS_NORMAL + force = 12 + throwforce = 15 + throw_speed = 3 + throw_range = 7 + greyscale_config = /datum/greyscale_config/piggy_bank + ///Some piggy banks are persistent, meaning they carry dosh between rounds. + var/persistence_id + ///Callback to execute upon roundend to save the current amount of cash it has stored, IF persistent. + var/datum/callback/persistence_cb + ///How much dosh can this piggy bank hold. + var/maximum_value = PAYCHECK_COMMAND * 20 + ///How much dosh this piggy bank spawns with. + var/initial_value = 0 + +/obj/item/piggy_bank/Initialize(mapload) + if(!greyscale_colors) + greyscale_colors = pick(COLOR_PINK, + COLOR_LIGHT_ORANGE, + COLOR_GREEN_GRAY, + COLOR_PALE_BLUE_GRAY, + COLOR_DARK_MODERATE_LIME_GREEN, + COLOR_OFF_WHITE, + ) + + . = ..() + + AddElement(/datum/element/can_shatter, shattering_sound = SFX_SHATTER, shatters_as_weapon = TRUE) + AddElement(/datum/element/beauty, 500) + if(!persistence_id) + if(initial_value) + new /obj/item/holochip(src, initial_value) + return + + SSpersistence.load_piggy_bank(src) + persistence_cb = CALLBACK(src, PROC_REF(save_cash)) + SSticker.OnRoundend(persistence_cb) + + if(initial_value && initial_value + calculate_dosh_amount() <= maximum_value) + new /obj/item/holochip(src, initial_value) + +/obj/item/piggy_bank/proc/save_cash() + SSpersistence.save_piggy_bank(src) + +/obj/item/piggy_bank/Destroy() + if(persistence_cb) + LAZYREMOVE(SSticker.round_end_events, persistence_cb) //cleanup the callback. + persistence_cb = null + return ..() + +/obj/item/piggy_bank/deconstruct(disassembled = TRUE) + for(var/obj/item/thing as anything in contents) + thing.forceMove(loc) + //Smashing the piggy after the round is over doesn't count. + if(persistence_id && SSticker.current_state < GAME_STATE_FINISHED) + LAZYADD(SSpersistence.queued_broken_piggy_ids, persistence_id) + return ..() + +/obj/item/piggy_bank/attack_self(mob/user, modifiers) + . = ..() + if(DOING_INTERACTION_WITH_TARGET(user, src)) + return + balloon_alert(user, "rattle rattle...") + if(!do_after(user, 0.5 SECONDS, src)) + return + var/percentile = round(calculate_dosh_amount()/maximum_value * 100, 1) + if(percentile >= 10) + playsound(src, SFX_RATTLE, percentile * 0.5, FALSE, FALSE) + switch(percentile) + if(0) + balloon_alert(user, "it's empty") + if(1 to 9) + balloon_alert(user, "it's almost empty") + if(10 to 25) + balloon_alert(user, "it's some cash") + if(25 to 45) + balloon_alert(user, "it's plenty of cash") + if(45 to 70) + balloon_alert(user, "it feels almost full") + if(70 to 95) + balloon_alert(user, "it feels full") + if(95 to INFINITY) + balloon_alert(user, "brimming with cash") + +/obj/item/piggy_bank/attackby(obj/item/item, mob/user, params) + var/creds_value = item.get_item_credit_value() + if(isnull(creds_value)) + return ..() + + var/dosh_amount = calculate_dosh_amount() + + if(dosh_amount >= maximum_value) + balloon_alert(user, "it's full!") + else if(dosh_amount + creds_value > maximum_value) + balloon_alert(user, "too much cash!") + else if(!user.transferItemToLoc(item, src)) + balloon_alert(user, "stuck in your hands!") + else + balloon_alert(user, "inserted [creds_value] creds") + return TRUE + +///Returns the total amount of credits that its contents amount to. +/obj/item/piggy_bank/proc/calculate_dosh_amount() + var/total_value = 0 + for(var/obj/item/item in contents) + total_value += item.get_item_credit_value() + return total_value + +/obj/item/piggy_bank/museum + name = "Pigston Swinelord VI" + desc = "The museum's mascot piggy bank and favorite embezzler, known to carry donations between shifts without paying taxes. The space IRS hates him." + persistence_id = "museum_piggy" + greyscale_colors = COLOR_PINK + maximum_value = PAYCHECK_COMMAND * 100 + initial_value = PAYCHECK_COMMAND * 4 + +/obj/item/piggy_bank/museum/Initialize(mapload) + . = ..() + AddComponent(/datum/component/areabound) //do not steal. diff --git a/code/game/objects/items/plushes.dm b/code/game/objects/items/plushes.dm index ca669a9733e1221..90790a75ea20beb 100644 --- a/code/game/objects/items/plushes.dm +++ b/code/game/objects/items/plushes.dm @@ -44,7 +44,7 @@ /obj/item/toy/plush/Initialize(mapload) . = ..() AddComponent(/datum/component/squeak, squeak_override) - AddElement(/datum/element/bed_tuckable, 6, -5, 90) + AddElement(/datum/element/bed_tuckable, mapload, 6, -5, 90) //have we decided if Pinocchio goes in the blue or pink aisle yet? if(gender == NEUTER) diff --git a/code/game/objects/items/puzzle_pieces.dm b/code/game/objects/items/puzzle_pieces.dm index 7ac22d00897eac5..dca3fe172159a64 100644 --- a/code/game/objects/items/puzzle_pieces.dm +++ b/code/game/objects/items/puzzle_pieces.dm @@ -289,28 +289,47 @@ // literally just buttons // -/obj/machinery/puzzle_button - name = "control panel" - desc = "A panel that controls something nearby. I'm sure it being covered in hazard stripes is fine." +/obj/machinery/puzzle + name = "abstract puzzle gizmo" icon = 'icons/obj/machines/wallmounts.dmi' - icon_state = "lockdown0" resistance_flags = INDESTRUCTIBLE | FIRE_PROOF | ACID_PROOF | LAVA_PROOF - base_icon_state = "lockdown" /// have we been pressed already? var/used = FALSE /// can we be pressed only once? var/single_use = TRUE /// puzzle id we send on press - var/id = "0" //null would literally open every puzzle door without an id + var/id //null would literally open every puzzle door without an id /// queue size, must match count of objects this activates! var/queue_size = 2 + /// should the puzzle machinery perform the final step of the queue link on LateInitialize? An alternative to queue size + var/late_initialize_pop = FALSE -/obj/machinery/puzzle_button/Initialize(mapload) +/obj/machinery/puzzle/Initialize(mapload) . = ..() if(!isnull(id)) - SSqueuelinks.add_to_queue(src, id, queue_size) + SSqueuelinks.add_to_queue(src, id, late_initialize_pop ? 0 : queue_size) + return late_initialize_pop ? INITIALIZE_HINT_LATELOAD : . + +/obj/machinery/puzzle/LateInitialize() + . = ..() + if(late_initialize_pop && id && SSqueuelinks.queues[id]) + SSqueuelinks.pop_link(id) + +/obj/machinery/puzzle/proc/on_puzzle_complete() //incase someone wants to make this do something else for some reason + SEND_SIGNAL(src, COMSIG_PUZZLE_COMPLETED) + +/obj/machinery/puzzle/update_icon_state() + icon_state = "[base_icon_state][used]" + return ..() + +/obj/machinery/puzzle/button + name = "control panel" + desc = "A panel that controls something nearby. I'm sure it being covered in hazard stripes is fine." + icon = 'icons/obj/machines/wallmounts.dmi' + icon_state = "lockdown0" + base_icon_state = "lockdown" -/obj/machinery/puzzle_button/attack_hand(mob/user, list/modifiers) +/obj/machinery/puzzle/button/attack_hand(mob/user, list/modifiers) . = ..() if(.) return @@ -320,37 +339,17 @@ update_icon_state() visible_message(span_notice("[user] presses a button on [src]."), span_notice("You press a button on [src].")) playsound(src, 'sound/machines/terminal_button07.ogg', 45, TRUE) - open_doors() + on_puzzle_complete() -/obj/machinery/puzzle_button/proc/open_doors() //incase someone wants to make this do something else for some reason - SEND_SIGNAL(src, COMSIG_PUZZLE_COMPLETED) - -/obj/machinery/puzzle_button/update_icon_state() - icon_state = "[base_icon_state][used]" - return ..() +MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/puzzle/button, 32) -MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/puzzle_button, 32) - -/obj/machinery/puzzle_keycardpad +/obj/machinery/puzzle/keycardpad name = "keycard panel" desc = "A panel that controls something nearby. Accepts keycards." - icon = 'icons/obj/machines/wallmounts.dmi' icon_state = "keycardpad0" - resistance_flags = INDESTRUCTIBLE | FIRE_PROOF | ACID_PROOF | LAVA_PROOF base_icon_state = "keycardpad" - /// were we used successfully? - var/used = FALSE - /// puzzle id we send if the correct card is swiped - var/id = "0" - /// queue size, must match count of objects this activates! - var/queue_size = 2 - -/obj/machinery/puzzle_keycardpad/Initialize(mapload) - . = ..() - if(!isnull(id)) - SSqueuelinks.add_to_queue(src, id, queue_size) -/obj/machinery/puzzle_keycardpad/attackby(obj/item/attacking_item, mob/user, params) +/obj/machinery/puzzle/keycardpad/attackby(obj/item/attacking_item, mob/user, params) . = ..() if(!istype(attacking_item, /obj/item/keycard) || used) return @@ -363,13 +362,75 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/puzzle_button, 32) used = TRUE update_icon_state() playsound(src, 'sound/machines/beep.ogg', 45, TRUE) - SEND_SIGNAL(src, COMSIG_PUZZLE_COMPLETED) + on_puzzle_complete() + +MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/puzzle/keycardpad, 32) + +/obj/machinery/puzzle/password + name = "password panel" + desc = "A panel that controls something nearby. This one requires a (case-sensitive) password, and it's not \"Swordfish\"." + icon_state = "passpad0" + base_icon_state = "passpad" + ///The password to this door. + var/password = "" + ///The text shown in the tgui input popup + var/tgui_text = "Please enter the password." + ///The title of the tgui input popup + var/tgui_title = "What's the password?" + ///Decides whether the max length of the input is MAX_NAME_LEN or the length of the password. + var/input_max_len_is_pass = FALSE + +/obj/machinery/puzzle/password/interact(mob/user, list/modifiers) + if(used && single_use) + return + if(!user.can_perform_action(src, ALLOW_SILICON_REACH) || !user.can_interact_with(src)) + return + var/pass_input = tgui_input_text(user, tgui_text, tgui_title, max_length = input_max_len_is_pass ? length(password) : MAX_NAME_LEN) + if(isnull(pass_input) || !user.can_perform_action(src, ALLOW_SILICON_REACH) || !user.can_interact_with(src)) + return + var/correct = pass_input == password + balloon_alert_to_viewers("[correct ? "correct" : "wrong"] password[correct ? "" : "!"]") + if(!correct) + playsound(src, 'sound/machines/buzz-sigh.ogg', 45, TRUE) + return + used = single_use + update_icon_state() + playsound(src, 'sound/machines/terminal_button07.ogg', 45, TRUE) + on_puzzle_complete() -/obj/machinery/puzzle_keycardpad/update_icon_state() - icon_state = "[base_icon_state][used]" - return ..() +MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/puzzle/password, 32) -MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/puzzle_keycardpad, 32) +/obj/machinery/puzzle/password/pin + desc = "A panel that controls something nearby. This one requires a PIN password, so let's start by typing in 1234..." + tgui_text = "Please enter the PIN code." + tgui_title = "What's the PIN code?" + input_max_len_is_pass = TRUE + ///The length of the PIN. Suggestion: something between 4 and 12. + var/pin_length = 6 + ///associate a color to each digit that may be found in the password. + var/list/digit_to_color = list() + +/obj/machinery/puzzle/password/pin/Initialize(mapload) + . = ..() + + for(var/iteration in 1 to pin_length) + password += "[rand(1, 9)]" + + var/list/possible_colors = list( + "white", + "black", + "red", + "green", + "blue", + "yellow", + "orange", + "brown", + "gray", + ) + for(var/digit in 0 to 9) + digit_to_color["[digit]"] = pick_n_take(possible_colors) + +MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/puzzle/password/pin, 32) // // blockade @@ -445,7 +506,7 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/puzzle_keycardpad, 32) if(isnull(id) || isnull(queue_id)) log_mapping("[src] id:[id] has no id or door id and has been deleted") return INITIALIZE_HINT_QDEL - + SSqueuelinks.add_to_queue(src, queue_id) /obj/effect/puzzle_poddoor_open/MatchedLinks(id, list/partners) @@ -461,3 +522,99 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/puzzle_keycardpad, 32) if(isnull(openclose)) openclose = door.density INVOKE_ASYNC(door, openclose ? TYPE_PROC_REF(/obj/machinery/door/poddoor, open) : TYPE_PROC_REF(/obj/machinery/door/poddoor, close)) + +#define MAX_PUZZLE_DOTS_PER_ROW 4 +#define PUZZLE_DOTS_VERTICAL_OFFSET 7 +#define PUZZLE_DOTS_HORIZONTAL_OFFSET 7 + +///A dotted board that can be used as clue for PIN puzzle machinery +/obj/effect/decal/puzzle_dots + name = "dotted board" + desc = "A board filled with colored dots. What could this mean?" + icon = 'icons/obj/fluff/puzzle_small.dmi' + icon_state = "puzzle_dots" + plane = GAME_PLANE //visible over walls + resistance_flags = INDESTRUCTIBLE | FIRE_PROOF | UNACIDABLE | LAVA_PROOF + flags_1 = UNPAINTABLE_1 + ///The id of the puzzle we're linked to. + var/id + +/obj/effect/decal/puzzle_dots/Initialize(mapload) + . = ..() + if(id) + SSqueuelinks.add_to_queue(src, id) + +/obj/effect/decal/puzzle_dots/MatchedLinks(id, partners) + var/obj/machinery/puzzle/password/pin/pad = locate() in partners + var/list/pass_digits = splittext(pad.password, "") + var/pass_len = length(pass_digits) + var/extra_rows = CEILING((pass_len/MAX_PUZZLE_DOTS_PER_ROW)-1, 1) + if(extra_rows) + pixel_y += round(extra_rows*(PUZZLE_DOTS_VERTICAL_OFFSET*0.5)) + for(var/i in 1 to extra_rows) + var/mutable_appearance/row = mutable_appearance(icon, icon_state) + row.pixel_y = -i*PUZZLE_DOTS_VERTICAL_OFFSET + add_overlay(row) + for(var/i in 1 to pass_len) + var/mutable_appearance/colored_dot = mutable_appearance(icon, "puzzle_dot_single") + colored_dot.color = pad.digit_to_color[pass_digits[i]] + colored_dot.pixel_x = PUZZLE_DOTS_HORIZONTAL_OFFSET * ((i-1)%MAX_PUZZLE_DOTS_PER_ROW) + colored_dot.pixel_y -= CEILING((i/MAX_PUZZLE_DOTS_PER_ROW)-1, 1)*PUZZLE_DOTS_VERTICAL_OFFSET + add_overlay(colored_dot) + +#undef MAX_PUZZLE_DOTS_PER_ROW +#undef PUZZLE_DOTS_VERTICAL_OFFSET +#undef PUZZLE_DOTS_HORIZONTAL_OFFSET + + +/obj/effect/decal/cleanable/crayon/puzzle + name = "Password character" + icon_state = "0" + ///The id of the puzzle we're linked to. + var/puzzle_id + +/obj/effect/decal/cleanable/crayon/puzzle/Initialize(mapload, main, type, e_name, graf_rot, alt_icon = null) + . = ..() + name = "number" + if(puzzle_id) + SSqueuelinks.add_to_queue(src, puzzle_id) + +/obj/effect/decal/cleanable/crayon/puzzle/MatchedLinks(id, partners) + var/obj/machinery/puzzle/password/pad = locate() in partners + var/list/pass_character = splittext(pad.password, "") + var/chosen_character = icon_state + if(!findtext(chosen_character, GLOB.is_alphanumeric)) + qdel(src) + return FALSE + icon_state = pick(pass_character) + if(!text2num(icon_state)) + name = "letter" + desc = "A letter vandalizing the station." + return TRUE + +/obj/effect/decal/cleanable/crayon/puzzle/pin + name = "PIN number" + +/obj/effect/decal/cleanable/crayon/puzzle/pin/MatchedLinks(id, partners) + . = ..() + var/obj/machinery/puzzle/password/pin/pad = locate() in partners + add_atom_colour(pad.digit_to_color[icon_state], FIXED_COLOUR_PRIORITY) + +/obj/item/paper/fluff/scrambled_pass + name = "gibberish note" + icon_state = "scrap" + ///The ID associated to the puzzle we're part of. + var/puzzle_id + +/obj/item/paper/fluff/scrambled_pass/Initialize(mapload) + . = ..() + if(mapload && puzzle_id) + SSqueuelinks.add_to_queue(src, puzzle_id) + +/obj/item/paper/fluff/scrambled_pass/MatchedLinks(id, partners) + var/obj/machinery/puzzle/password/pad = locate() in partners + var/scrambled_text = "" + var/list/pass_characters = splittext(pad.password, "") + for(var/i in 1 to rand(200, 300)) + scrambled_text += pick(pass_characters) + add_raw_text(scrambled_text) diff --git a/code/game/objects/items/rcd/RCD.dm b/code/game/objects/items/rcd/RCD.dm index 9570614b400b3b8..025571a90a78269 100644 --- a/code/game/objects/items/rcd/RCD.dm +++ b/code/game/objects/items/rcd/RCD.dm @@ -219,7 +219,10 @@ delay *= FREQUENT_USE_DEBUFF_MULTIPLIER current_active_effects += 1 - _rcd_create_effect(target, user, delay, rcd_results) + var/target_name = target.name //Store the name before it gets mutated due to deconstruction. + var/target_path = target.type + if(_rcd_create_effect(target, user, delay, rcd_results)) + log_tool("used RCD with design path: \"[rcd_results["[RCD_DESIGN_MODE]"] == RCD_DECONSTRUCT ? "deconstruction" : rcd_results["[RCD_DESIGN_PATH]"]]\" with delay: \"[delay / (1 SECONDS)]s\" at target: \"[target_name] ([target_path])\" in location: \"[AREACOORD(target)]\".", user) current_active_effects -= 1 /** diff --git a/code/game/objects/items/robot/items/food.dm b/code/game/objects/items/robot/items/food.dm index a747f813ace869f..0ecfefa589d10e3 100644 --- a/code/game/objects/items/robot/items/food.dm +++ b/code/game/objects/items/robot/items/food.dm @@ -60,10 +60,7 @@ if(DISPENSE_LOLLIPOP_MODE) food_item = new /obj/item/food/lollipop/cyborg(turf_to_dispense_to) if(DISPENSE_ICECREAM_MODE) - food_item = new /obj/item/food/icecream( - loc = turf_to_dispense_to, - prefill_flavours = list(ICE_CREAM_VANILLA), - ) + food_item = new /obj/item/food/icecream(turf_to_dispense_to, list(ICE_CREAM_VANILLA)) food_item.desc = "Eat the ice cream." var/into_hands = FALSE diff --git a/code/game/objects/items/shrapnel.dm b/code/game/objects/items/shrapnel.dm index cdc786fc8db5633..c07bc780c9128a1 100644 --- a/code/game/objects/items/shrapnel.dm +++ b/code/game/objects/items/shrapnel.dm @@ -35,6 +35,9 @@ wound_bonus = 30 embedding = list(embed_chance=70, ignore_throwspeed_threshold=TRUE, fall_chance=1) +/obj/projectile/bullet/shrapnel/short_range + range = 5 + /obj/projectile/bullet/shrapnel/mega name = "flying shrapnel hunk" range = 45 diff --git a/code/game/objects/items/stacks/bscrystal.dm b/code/game/objects/items/stacks/bscrystal.dm index 19b518157c8c286..75c35eabb181841 100644 --- a/code/game/objects/items/stacks/bscrystal.dm +++ b/code/game/objects/items/stacks/bscrystal.dm @@ -74,7 +74,7 @@ attack_verb_simple = list("bluespace polybash", "bluespace polybatter", "bluespace polybludgeon", "bluespace polythrash", "bluespace polysmash") novariants = TRUE grind_results = list(/datum/reagent/bluespace = 20) - point_value = 30 + point_value = 90 merge_type = /obj/item/stack/sheet/bluespace_crystal material_type = /datum/material/bluespace var/crystal_type = /obj/item/stack/ore/bluespace_crystal/refined 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 514ab36ed66d3cb..43cd135904f8764 100644 --- a/code/game/objects/items/stacks/golem_food/golem_status_effects.dm +++ b/code/game/objects/items/stacks/golem_food/golem_status_effects.dm @@ -433,15 +433,14 @@ var/glow_range = 3 var/glow_power = 1 var/glow_color = LIGHT_COLOR_DEFAULT - var/datum/component/overlay_lighting/lightbulb + var/obj/effect/dummy/lighting_obj/moblight/lightbulb /datum/status_effect/golem_lightbulb/on_apply() . = ..() if (!.) return to_chat(owner, span_notice("You start to emit a healthy glow.")) - owner.light_system = OVERLAY_LIGHT - lightbulb = owner.AddComponent(/datum/component/overlay_lighting, _range = glow_range, _power = glow_power, _color = glow_color) + lightbulb = owner.mob_light(glow_range, glow_power, glow_color) owner.add_filter(LIGHTBULB_FILTER, 2, list("type" = "outline", "color" = glow_color, "alpha" = 60, "size" = 1)) /datum/status_effect/golem_lightbulb/on_remove() diff --git a/code/game/objects/items/stacks/sheets/glass.dm b/code/game/objects/items/stacks/sheets/glass.dm index 5a789d34350e297..d6bd65afe31e185 100644 --- a/code/game/objects/items/stacks/sheets/glass.dm +++ b/code/game/objects/items/stacks/sheets/glass.dm @@ -159,7 +159,7 @@ GLOBAL_LIST_INIT(reinforced_glass_recipes, list ( \ resistance_flags = ACID_PROOF merge_type = /obj/item/stack/sheet/rglass grind_results = list(/datum/reagent/silicon = 20, /datum/reagent/iron = 10) - point_value = 4 + point_value = 12 matter_amount = 6 tableVariant = /obj/structure/table/reinforced/rglass @@ -197,7 +197,7 @@ GLOBAL_LIST_INIT(prglass_recipes, list ( \ material_flags = NONE merge_type = /obj/item/stack/sheet/plasmarglass grind_results = list(/datum/reagent/silicon = 20, /datum/reagent/toxin/plasma = 10, /datum/reagent/iron = 10) - point_value = 23 + point_value = 69 matter_amount = 8 tableVariant = /obj/structure/table/reinforced/plasmarglass diff --git a/code/game/objects/items/stacks/sheets/mineral.dm b/code/game/objects/items/stacks/sheets/mineral.dm index 8eafe6d52e5ae65..0620d82cd9bf4f4 100644 --- a/code/game/objects/items/stacks/sheets/mineral.dm +++ b/code/game/objects/items/stacks/sheets/mineral.dm @@ -99,7 +99,7 @@ GLOBAL_LIST_INIT(sandbag_recipes, list ( \ sheettype = "diamond" mats_per_unit = list(/datum/material/diamond=SHEET_MATERIAL_AMOUNT) grind_results = list(/datum/reagent/carbon = 20) - point_value = 25 + point_value = 75 merge_type = /obj/item/stack/sheet/mineral/diamond material_type = /datum/material/diamond walltype = /turf/closed/wall/mineral/diamond @@ -124,7 +124,7 @@ GLOBAL_LIST_INIT(diamond_recipes, list ( \ sheettype = "uranium" mats_per_unit = list(/datum/material/uranium=SHEET_MATERIAL_AMOUNT) grind_results = list(/datum/reagent/uranium = 20) - point_value = 20 + point_value = 60 merge_type = /obj/item/stack/sheet/mineral/uranium material_type = /datum/material/uranium walltype = /turf/closed/wall/mineral/uranium @@ -157,7 +157,7 @@ GLOBAL_LIST_INIT(uranium_recipes, list ( \ max_integrity = 100 mats_per_unit = list(/datum/material/plasma=SHEET_MATERIAL_AMOUNT) grind_results = list(/datum/reagent/toxin/plasma = 20) - point_value = 20 + point_value = 60 merge_type = /obj/item/stack/sheet/mineral/plasma material_type = /datum/material/plasma walltype = /turf/closed/wall/mineral/plasma @@ -192,7 +192,7 @@ GLOBAL_LIST_INIT(plasma_recipes, list ( \ sheettype = "gold" mats_per_unit = list(/datum/material/gold=SHEET_MATERIAL_AMOUNT) grind_results = list(/datum/reagent/gold = 20) - point_value = 20 + point_value = 60 merge_type = /obj/item/stack/sheet/mineral/gold material_type = /datum/material/gold walltype = /turf/closed/wall/mineral/gold @@ -219,7 +219,7 @@ GLOBAL_LIST_INIT(gold_recipes, list ( \ sheettype = "silver" mats_per_unit = list(/datum/material/silver=SHEET_MATERIAL_AMOUNT) grind_results = list(/datum/reagent/silver = 20) - point_value = 20 + point_value = 60 merge_type = /obj/item/stack/sheet/mineral/silver material_type = /datum/material/silver tableVariant = /obj/structure/table/optable @@ -245,7 +245,7 @@ GLOBAL_LIST_INIT(silver_recipes, list ( \ sheettype = "bananium" mats_per_unit = list(/datum/material/bananium=SHEET_MATERIAL_AMOUNT) grind_results = list(/datum/reagent/consumable/banana = 20) - point_value = 50 + point_value = 150 merge_type = /obj/item/stack/sheet/mineral/bananium material_type = /datum/material/bananium walltype = /turf/closed/wall/mineral/bananium @@ -276,7 +276,7 @@ GLOBAL_LIST_INIT(bananium_recipes, list ( \ throw_range = 3 sheettype = "titanium" mats_per_unit = list(/datum/material/titanium=SHEET_MATERIAL_AMOUNT) - point_value = 20 + point_value = 60 merge_type = /obj/item/stack/sheet/mineral/titanium material_type = /datum/material/titanium walltype = /turf/closed/wall/mineral/titanium @@ -308,7 +308,7 @@ GLOBAL_LIST_INIT(titanium_recipes, list ( \ throw_range = 3 sheettype = "plastitanium" mats_per_unit = list(/datum/material/alloy/plastitanium=SHEET_MATERIAL_AMOUNT) - point_value = 45 + point_value = 135 material_type = /datum/material/alloy/plastitanium merge_type = /obj/item/stack/sheet/mineral/plastitanium material_flags = NONE @@ -482,7 +482,7 @@ GLOBAL_LIST_INIT(metalhydrogen_recipes, list( singular_name = "metal hydrogen sheet" w_class = WEIGHT_CLASS_NORMAL resistance_flags = FIRE_PROOF | LAVA_PROOF | ACID_PROOF | INDESTRUCTIBLE - point_value = 100 + point_value = 300 mats_per_unit = list(/datum/material/metalhydrogen = SHEET_MATERIAL_AMOUNT) material_type = /datum/material/metalhydrogen merge_type = /obj/item/stack/sheet/mineral/metal_hydrogen @@ -497,7 +497,7 @@ GLOBAL_LIST_INIT(metalhydrogen_recipes, list( inhand_icon_state = "sheet-zaukerite" singular_name = "zaukerite crystal" w_class = WEIGHT_CLASS_NORMAL - point_value = 120 + point_value = 360 mats_per_unit = list(/datum/material/zaukerite = SHEET_MATERIAL_AMOUNT) merge_type = /obj/item/stack/sheet/mineral/zaukerite material_type = /datum/material/zaukerite diff --git a/code/game/objects/items/stacks/sheets/sheet_types.dm b/code/game/objects/items/stacks/sheets/sheet_types.dm index 8b5fa16e5800eb6..4d02057d30a0527 100644 --- a/code/game/objects/items/stacks/sheets/sheet_types.dm +++ b/code/game/objects/items/stacks/sheets/sheet_types.dm @@ -48,6 +48,11 @@ GLOBAL_LIST_INIT(metal_recipes, list ( \ new /datum/stack_recipe("bench (left)", /obj/structure/chair/sofa/bench/left, one_per_turf = TRUE, on_solid_ground = TRUE, category = CAT_FURNITURE), \ new /datum/stack_recipe("bench (right)", /obj/structure/chair/sofa/bench/right, one_per_turf = TRUE, on_solid_ground = TRUE, category = CAT_FURNITURE), \ new /datum/stack_recipe("bench (corner)", /obj/structure/chair/sofa/bench/corner, one_per_turf = TRUE, on_solid_ground = TRUE, category = CAT_FURNITURE), \ + new /datum/stack_recipe("tram bench (solo)", /obj/structure/chair/sofa/bench/tram/solo, one_per_turf = TRUE, on_solid_ground = TRUE, category = CAT_FURNITURE), \ + new /datum/stack_recipe("tram bench (middle)", /obj/structure/chair/sofa/bench/tram, one_per_turf = TRUE, on_solid_ground = TRUE, category = CAT_FURNITURE), \ + new /datum/stack_recipe("tram bench (left)", /obj/structure/chair/sofa/bench/tram/left, one_per_turf = TRUE, on_solid_ground = TRUE, category = CAT_FURNITURE), \ + new /datum/stack_recipe("tram bench (right)", /obj/structure/chair/sofa/bench/tram/right, one_per_turf = TRUE, on_solid_ground = TRUE, category = CAT_FURNITURE), \ + new /datum/stack_recipe("tram bench (corner)", /obj/structure/chair/sofa/bench/tram/corner, one_per_turf = TRUE, on_solid_ground = TRUE, category = CAT_FURNITURE), \ )), \ new /datum/stack_recipe_list("chess pieces", list( \ new /datum/stack_recipe("White Pawn", /obj/structure/chess/whitepawn, 2, time = 1 SECONDS, one_per_turf = TRUE, on_solid_ground = TRUE, category = CAT_ENTERTAINMENT), \ @@ -145,7 +150,7 @@ GLOBAL_LIST_INIT(metal_recipes, list ( \ resistance_flags = FIRE_PROOF merge_type = /obj/item/stack/sheet/iron grind_results = list(/datum/reagent/iron = 20) - point_value = 2 + point_value = 6 tableVariant = /obj/structure/table material_type = /datum/material/iron matter_amount = 4 @@ -272,7 +277,7 @@ GLOBAL_LIST_INIT(plasteel_recipes, list ( \ resistance_flags = FIRE_PROOF merge_type = /obj/item/stack/sheet/plasteel grind_results = list(/datum/reagent/iron = 20, /datum/reagent/toxin/plasma = 20) - point_value = 23 + point_value = 69 tableVariant = /obj/structure/table/reinforced material_flags = NONE matter_amount = 12 @@ -780,7 +785,8 @@ GLOBAL_LIST_INIT(bronze_recipes, list ( \ ) GLOBAL_LIST_INIT(plastic_recipes, list( new /datum/stack_recipe("plastic floor tile", /obj/item/stack/tile/plastic, 1, 4, 20, time = 2 SECONDS, check_density = FALSE, category = CAT_TILES), \ - new /datum/stack_recipe("thermoplastic tram tile", /obj/item/stack/thermoplastic, 1, 2, time = 4 SECONDS, check_density = FALSE, placement_checks = STACK_CHECK_TRAM_EXCLUSIVE, category = CAT_TILES), \ + new /datum/stack_recipe("light tram tile", /obj/item/stack/thermoplastic/light, 1, 4, 20, time = 2 SECONDS, check_density = FALSE, category = CAT_TILES), \ + new /datum/stack_recipe("dark tram tile", /obj/item/stack/thermoplastic, 1, 4, 20, time = 2 SECONDS, check_density = FALSE, category = CAT_TILES), \ new /datum/stack_recipe("folding plastic chair", /obj/structure/chair/plastic, 2, check_density = FALSE, category = CAT_FURNITURE), \ new /datum/stack_recipe("plastic flaps", /obj/structure/plasticflaps, 5, one_per_turf = TRUE, on_solid_ground = TRUE, time = 4 SECONDS, category = CAT_FURNITURE), \ new /datum/stack_recipe("water bottle", /obj/item/reagent_containers/cup/glass/waterbottle/empty, check_density = FALSE, category = CAT_CONTAINERS), \ diff --git a/code/game/objects/items/sticker.dm b/code/game/objects/items/sticker.dm deleted file mode 100644 index 459c8d211e4d949..000000000000000 --- a/code/game/objects/items/sticker.dm +++ /dev/null @@ -1,131 +0,0 @@ -/// parent type for all other stickers. do not spawn directly -/obj/item/sticker - name = "sticker" - desc = "A sticker with some strong adhesive on the back, sticks to stuff!" - item_flags = NOBLUDGEON | XENOMORPH_HOLDABLE //funny - resistance_flags = FLAMMABLE - icon = 'icons/obj/toys/stickers.dmi' - w_class = WEIGHT_CLASS_TINY - throw_range = 3 - vis_flags = VIS_INHERIT_DIR | VIS_INHERIT_PLANE | VIS_INHERIT_LAYER - ///If not null, pick an icon_state from this list - var/icon_states - /// If the sticker should be disincluded from normal sticker boxes. - var/contraband = FALSE - -/obj/item/sticker/Initialize(mapload) - . = ..() - if(icon_states) - icon_state = pick(icon_states) - pixel_y = rand(-3,3) - pixel_x = rand(-3,3) - AddElement(/datum/element/sticker) - -/obj/item/sticker/smile - name = "smiley sticker" - icon_state = "smile" - -/obj/item/sticker/frown - name = "frowny sticker" - icon_state = "frown" - -/obj/item/sticker/left_arrow - name = "left arrow sticker" - icon_state = "larrow" - -/obj/item/sticker/right_arrow - name = "right arrow sticker" - icon_state = "rarrow" - -/obj/item/sticker/star - name = "star sticker" - icon_state = "star1" - icon_states = list("star1","star2") - -/obj/item/sticker/heart - name = "heart sticker" - icon_state = "heart" - -/obj/item/sticker/googly - name = "googly eye sticker" - icon_state = "googly1" - icon_states = list("googly1","googly2") - -/obj/item/sticker/rev - name = "blue R sticker" - desc = "A sticker of FUCK THE SYSTEM, the galaxy's premiere hardcore punk band." - icon_state = "revhead" - -/obj/item/sticker/pslime - name = "slime plushie sticker" - icon_state = "pslime" - -/obj/item/sticker/pliz - name = "lizard plushie sticker" - icon_state = "plizard" - -/obj/item/sticker/pbee - name = "bee plushie sticker" - icon_state = "pbee" - -/obj/item/sticker/psnake - name = "snake plushie sticker" - icon_state = "psnake" - -/obj/item/sticker/robot - name = "bot sticker" - icon_state = "tile" - icon_states = list("tile","medbot","clean") - -/obj/item/sticker/toolbox - name = "toolbox sticker" - icon_state = "toolbox" - -/obj/item/sticker/clown - name = "clown sticker" - icon_state = "honkman" - -/obj/item/sticker/mime - name = "mime sticker" - icon_state = "silentman" - -/obj/item/sticker/assistant - name = "assistant sticker" - icon_state = "tider" - -/obj/item/sticker/syndicate - name = "syndicate sticker" - icon_state = "synd" - contraband = TRUE - -/obj/item/sticker/syndicate/c4 - name = "C-4 sticker" - icon_state = "c4" - -/obj/item/sticker/syndicate/bomb - name = "syndicate bomb sticker" - icon_state = "sbomb" - -/obj/item/sticker/syndicate/apc - name = "broken APC sticker" - icon_state = "milf" - -/obj/item/sticker/syndicate/larva - name = "larva sticker" - icon_state = "larva" - -/obj/item/sticker/syndicate/cult - name = "bloody paper sticker" - icon_state = "cult" - -/obj/item/sticker/syndicate/flash - name = "flash sticker" - icon_state = "flash" - -/obj/item/sticker/syndicate/op - name = "operative sticker" - icon_state = "newcop" - -/obj/item/sticker/syndicate/trap - name = "bear trap sticker" - icon_state = "trap" diff --git a/code/game/objects/items/stickers.dm b/code/game/objects/items/stickers.dm new file mode 100644 index 000000000000000..c7288bed2dd5fac --- /dev/null +++ b/code/game/objects/items/stickers.dm @@ -0,0 +1,195 @@ +#define MAX_STICKER_COUNT 15 + +/** + * What stickers can do? + * + * - They can be attached to any object. + * - They inherit cursor position when attached. + * - They are unclickable by mouse, I suppose? + * - They can be washed off. + * - They can be burnt off. + * - They can be attached to the object they collided with. + * - They play "attack" animation when attached. + * + */ + +/obj/item/sticker + name = "sticker" + desc = "A sticker with some strong adhesive on the back, sticks to stuff!" + + icon = 'icons/obj/toys/stickers.dmi' + + max_integrity = 50 + resistance_flags = FLAMMABLE + + throw_range = 3 + pressure_resistance = 0 + + item_flags = NOBLUDGEON | XENOMORPH_HOLDABLE //funny ~Jimmyl + w_class = WEIGHT_CLASS_TINY + + /// `list` or `null`, contains possible alternate `icon_states`. + var/list/icon_states + /// Whether sticker is legal and allowed to generate inside non-syndicate boxes. + var/contraband = FALSE + +/obj/item/sticker/Initialize(mapload) + . = ..() + + if(length(icon_states)) + icon_state = pick(icon_states) + +/obj/item/sticker/Bump(atom/bumped_atom) + if(prob(50) && attempt_attach(bumped_atom)) + bumped_atom.balloon_alert_to_viewers("sticker landed on sticky side!") + +/obj/item/sticker/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) + if(!isatom(interacting_with)) + return NONE + + var/cursor_x = text2num(LAZYACCESS(modifiers, ICON_X)) + var/cursor_y = text2num(LAZYACCESS(modifiers, ICON_Y)) + + if(isnull(cursor_x) || isnull(cursor_y)) + return NONE + + if(attempt_attach(interacting_with, user, cursor_x, cursor_y)) + return ITEM_INTERACT_SUCCESS + + return NONE + +/** + * Attempts to attach sticker to an object. Returns `FALSE` if atom has more than + * `MAX_STICKER_COUNT` stickers, `TRUE` otherwise. If no `px` or `py` were passed + * picks random coordinates based on a `target`'s icon. + */ +/obj/item/sticker/proc/attempt_attach(atom/target, mob/user, px, py) + if(COUNT_TRAIT_SOURCES(target, TRAIT_STICKERED) >= MAX_STICKER_COUNT) + balloon_alert_to_viewers("sticker won't stick!") + return FALSE + + if(isnull(px) || isnull(py)) + var/icon/target_mask = icon(target.icon, target.icon_state) + + if(isnull(px)) + px = rand(1, target_mask.Width()) + + if(isnull(py)) + py = rand(1, target_mask.Height()) + + if(!isnull(user)) + user.do_attack_animation(target, used_item = src) + target.balloon_alert(user, "sticker sticked") + + target.AddComponent(/datum/component/sticker, src, user, get_dir(target, src), px, py) + return TRUE + +#undef MAX_STICKER_COUNT + +/obj/item/sticker/smile + name = "smiley sticker" + icon_state = "smile" + +/obj/item/sticker/frown + name = "frowny sticker" + icon_state = "frown" + +/obj/item/sticker/left_arrow + name = "left arrow sticker" + icon_state = "arrow-left" + +/obj/item/sticker/right_arrow + name = "right arrow sticker" + icon_state = "arrow-right" + +/obj/item/sticker/star + name = "star sticker" + icon_state = "star" + +/obj/item/sticker/heart + name = "heart sticker" + icon_state = "heart" + +/obj/item/sticker/googly + name = "googly eye sticker" + icon_state = "googly" + icon_states = list("googly", "googly-alt") + +/obj/item/sticker/rev + name = "blue R sticker" + desc = "A sticker of FUCK THE SYSTEM, the galaxy's premiere hardcore punk band." + icon_state = "revhead" + +/obj/item/sticker/pslime + name = "slime plushie sticker" + icon_state = "pslime" + +/obj/item/sticker/pliz + name = "lizard plushie sticker" + icon_state = "plizard" + +/obj/item/sticker/pbee + name = "bee plushie sticker" + icon_state = "pbee" + +/obj/item/sticker/psnake + name = "snake plushie sticker" + icon_state = "psnake" + +/obj/item/sticker/robot + name = "bot sticker" + icon_state = "tile" + icon_states = list("tile", "medbot", "clean") + +/obj/item/sticker/toolbox + name = "toolbox sticker" + icon_state = "soul" + +/obj/item/sticker/clown + name = "clown sticker" + icon_state = "honkman" + +/obj/item/sticker/mime + name = "mime sticker" + icon_state = "silentman" + +/obj/item/sticker/assistant + name = "assistant sticker" + icon_state = "tider" + +/obj/item/sticker/syndicate + name = "syndicate sticker" + icon_state = "synd" + contraband = TRUE + +/obj/item/sticker/syndicate/c4 + name = "C-4 sticker" + icon_state = "c4" + +/obj/item/sticker/syndicate/bomb + name = "syndicate bomb sticker" + icon_state = "sbomb" + +/obj/item/sticker/syndicate/apc + name = "broken APC sticker" + icon_state = "milf" + +/obj/item/sticker/syndicate/larva + name = "larva sticker" + icon_state = "larva" + +/obj/item/sticker/syndicate/cult + name = "bloody paper sticker" + icon_state = "cult" + +/obj/item/sticker/syndicate/flash + name = "flash sticker" + icon_state = "flash" + +/obj/item/sticker/syndicate/op + name = "operative sticker" + icon_state = "newcop" + +/obj/item/sticker/syndicate/trap + name = "bear trap sticker" + icon_state = "trap" diff --git a/code/game/objects/items/storage/boxes/clothes_boxes.dm b/code/game/objects/items/storage/boxes/clothes_boxes.dm index 18a6ec31d87c927..ce4dfb6c5e535af 100644 --- a/code/game/objects/items/storage/boxes/clothes_boxes.dm +++ b/code/game/objects/items/storage/boxes/clothes_boxes.dm @@ -211,3 +211,11 @@ new /obj/item/clothing/gloves/combat/floortile(src) new /obj/item/clothing/shoes/jackboots/floortile(src) new /obj/item/storage/backpack/floortile(src) + +/obj/item/storage/box/collar_bomb + name = "collar bomb box" + desc = "A small print on the back reads 'For research purposes only. Handle with care. In case of emergency, call the following number:'... the rest is scratched out with a marker..." + +/obj/item/storage/box/collar_bomb/PopulateContents() + var/obj/item/collar_bomb_button/button = new(src) + new /obj/item/clothing/neck/collar_bomb(src, button) diff --git a/code/game/objects/items/storage/boxes/service_boxes.dm b/code/game/objects/items/storage/boxes/service_boxes.dm index 14656f0f5f71def..8dcc1f4f6b62f28 100644 --- a/code/game/objects/items/storage/boxes/service_boxes.dm +++ b/code/game/objects/items/storage/boxes/service_boxes.dm @@ -209,16 +209,21 @@ desc = "A box full of random stickers. Do give to the clown." /obj/item/storage/box/stickers/proc/generate_non_contraband_stickers_list() - . = list() + var/list/allowed_stickers = list() + for(var/obj/item/sticker/sticker_type as anything in subtypesof(/obj/item/sticker)) - if(!initial(sticker_type.contraband)) - . += sticker_type - return . + if(!sticker_type::contraband) + allowed_stickers += sticker_type + + return allowed_stickers + /obj/item/storage/box/stickers/PopulateContents() var/static/list/non_contraband - if(!non_contraband) + + if(isnull(non_contraband)) non_contraband = generate_non_contraband_stickers_list() - for(var/i in 1 to rand(4,8)) + + for(var/i in 1 to rand(4, 8)) var/type = pick(non_contraband) new type(src) diff --git a/code/game/objects/items/storage/fancy.dm b/code/game/objects/items/storage/fancy.dm index a7fbe6e7452f956..d83c80ed5651458 100644 --- a/code/game/objects/items/storage/fancy.dm +++ b/code/game/objects/items/storage/fancy.dm @@ -223,7 +223,7 @@ balloon_alert(user, "ooh, free coupon") var/obj/item/coupon/attached_coupon = new user.put_in_hands(attached_coupon) - attached_coupon.generate(rigged_omen ? COUPON_OMEN : null) + attached_coupon.generate(rigged_omen ? COUPON_OMEN : null, null, user) attached_coupon = null spawn_coupon = FALSE name = "discarded cigarette packet" diff --git a/code/game/objects/items/storage/storage.dm b/code/game/objects/items/storage/storage.dm index cfdfef8a4590c80..8631d62e79efd21 100644 --- a/code/game/objects/items/storage/storage.dm +++ b/code/game/objects/items/storage/storage.dm @@ -55,7 +55,6 @@ max_total_storage, list/canhold, list/canthold, - storage_type = /datum/storage, storage_type, ) // If no type was passed in, default to what we already have diff --git a/code/game/objects/items/storage/uplink_kits.dm b/code/game/objects/items/storage/uplink_kits.dm index 271fa8b03150fe0..aacf45e239de92c 100644 --- a/code/game/objects/items/storage/uplink_kits.dm +++ b/code/game/objects/items/storage/uplink_kits.dm @@ -10,6 +10,7 @@ #define KIT_SNIPER "sniper" #define KIT_NUKEOPS_METAGAME "metaops" #define KIT_LORD_SINGULOTH "lordsingulo" +#define KIT_REVOLUTIONARY "revolutionary" #define KIT_JAMES_BOND "bond" #define KIT_NINJA "ninja" @@ -19,6 +20,9 @@ #define KIT_BEES "bee" #define KIT_MR_FREEZE "mr_freeze" #define KIT_TRAITOR_2006 "ancient" +#define KIT_DEAD_MONEY "dead_money" +#define KIT_SAM_FISHER "sam_fisher" +#define KIT_PROP_HUNT "prop_hunt" /// last audited december 2022 /obj/item/storage/box/syndicate @@ -35,7 +39,8 @@ KIT_IMPLANTS = 1, KIT_HACKER = 3, KIT_SNIPER = 1, - KIT_NUKEOPS_METAGAME = 1 + KIT_NUKEOPS_METAGAME = 1, + KIT_REVOLUTIONARY = 2 ))) if(KIT_RECON) new /obj/item/clothing/glasses/thermal/xray(src) // ~8 tc? @@ -165,6 +170,18 @@ new /obj/item/card/emag(src) // 4 tc new /obj/item/card/emag/doorjack(src) // 3 tc + if(KIT_REVOLUTIONARY) + new /obj/item/healthanalyzer/rad_laser(src) // 3 TC + new /obj/item/assembly/flash/hypnotic(src) // 7 TC + new /obj/item/storage/pill_bottle/lsd(src) // ~1 TC + new /obj/item/pen/sleepy(src) // 4 TC + new /obj/item/gun/ballistic/revolver/nagant(src) // 13 TC comparable to 357. revolvers + new /obj/item/megaphone(src) + new /obj/item/bedsheet/rev(src) + new /obj/item/clothing/suit/armor/vest/russian_coat(src) + new /obj/item/clothing/head/helmet/rus_ushanka(src) + new /obj/item/storage/box/syndie_kit/poster_box(src) + /obj/item/storage/box/syndicate/bundle_b/PopulateContents() switch (pick_weight(list( KIT_JAMES_BOND = 2, @@ -174,7 +191,10 @@ KIT_MAD_SCIENTIST = 2, KIT_BEES = 1, KIT_MR_FREEZE = 2, - KIT_TRAITOR_2006 = 1 + KIT_DEAD_MONEY = 2, + KIT_TRAITOR_2006 = 1, + KIT_SAM_FISHER = 1, + KIT_PROP_HUNT = 1 ))) if(KIT_JAMES_BOND) new /obj/item/gun/ballistic/automatic/pistol(src) // 7 tc @@ -261,9 +281,37 @@ new /obj/item/gun/energy/laser/thermal/cryo(src) // ~6 tc new /obj/item/melee/energy/sword/saber/blue(src) //see see it fits the theme bc its blue and ice is blue, 8 tc - if(KIT_TRAITOR_2006) //A kit so old, it's probably older than you. //This bundle is filled with the entire unlink contents traitors had access to in 2006, from OpenSS13. Notably the esword was not a choice but existed in code. + if(KIT_TRAITOR_2006) //A kit so old, it's probably older than you. //This bundle is filled with the entire uplink contents traitors had access to in 2006, from OpenSS13. Notably the esword was not a choice but existed in code. new /obj/item/storage/toolbox/emergency/old/ancientbundle(src) //Items fit neatly into a classic toolbox just to remind you what the theme is. + if(KIT_DEAD_MONEY) + for(var/i in 1 to 4) + new /obj/item/clothing/neck/collar_bomb(src) // These let you remotely kill people with a signaler, though you have to get them first. + new /obj/item/storage/box/syndie_kit/signaler(src) + new /obj/item/mod/control/pre_equipped/responsory/inquisitory/syndie(src) // basically a snowflake yet better elite modsuit, so like, 8 + 5 tc. + new /obj/item/card/id/advanced/chameleon(src) // 2 tc + new /obj/item/clothing/mask/chameleon(src) + new /obj/item/melee/baton/telescopic/contractor_baton(src) // 7 tc + new /obj/item/jammer(src) // 5 tc + new /obj/item/pinpointer/crew(src) //priceless + + if(KIT_SAM_FISHER) + new /obj/item/clothing/under/syndicate/combat(src) + new /obj/item/clothing/suit/armor/vest/marine/pmc(src) //The armor kit is comparable to the infiltrator, 6 TC + new /obj/item/clothing/head/helmet/marine/pmc(src) + new /obj/item/clothing/mask/gas/sechailer(src) + new /obj/item/clothing/glasses/night(src) // 3~ TC + new /obj/item/clothing/gloves/krav_maga/combatglovesplus(src) //5TC + new /obj/item/clothing/shoes/jackboots(src) + new /obj/item/storage/belt/military/assault/fisher(src) //items in this belt easily costs 18 TC + + if(KIT_PROP_HUNT) + new /obj/item/chameleon(src) // 7 TC + new /obj/item/card/emag/doorjack(src) // 3 TC + new /obj/item/storage/box/syndie_kit/imp_stealth(src) //8 TC + new /obj/item/gun/ballistic/automatic/pistol(src) // 7 TC + new /obj/item/clothing/glasses/thermal(src) // 4 TC + /obj/item/storage/toolbox/emergency/old/ancientbundle/ //So the subtype works /obj/item/storage/toolbox/emergency/old/ancientbundle/PopulateContents() @@ -276,6 +324,17 @@ new /obj/item/implanter/freedom(src) // 5 tc new /obj/item/stack/telecrystal(src) //The failsafe/self destruct isn't an item we can physically include in the kit, but 1 TC is technically enough to buy the equivalent. +/obj/item/storage/belt/military/assault/fisher + +/obj/item/storage/belt/military/assault/fisher/PopulateContents() + new /obj/item/gun/ballistic/automatic/pistol/clandestine(src) // 7 TC + new /obj/item/suppressor(src) // 3 TC + new /obj/item/ammo_box/magazine/m10mm(src) // 1 TC + new /obj/item/ammo_box/magazine/m10mm(src) + new /obj/item/gun/energy/recharge/fisher(src) // Acquirable through black market, shit utility item 1 TC + new /obj/item/card/emag/doorjack(src) // 3 TC + new /obj/item/knife/combat(src) //comparable to the e-dagger, 2 TC + /obj/item/storage/box/syndie_kit name = "box" desc = "A sleek, sturdy box." @@ -628,6 +687,7 @@ /obj/item/storage/box/syndie_kit/stickers/PopulateContents() var/list/types = subtypesof(/obj/item/sticker/syndicate) + for(var/i in 1 to atom_storage.max_slots) var/type = pick(types) new type(src) @@ -807,6 +867,7 @@ #undef KIT_SNIPER #undef KIT_NUKEOPS_METAGAME #undef KIT_LORD_SINGULOTH +#undef KIT_REVOLUTIONARY #undef KIT_JAMES_BOND #undef KIT_NINJA @@ -816,3 +877,6 @@ #undef KIT_BEES #undef KIT_MR_FREEZE #undef KIT_TRAITOR_2006 +#undef KIT_DEAD_MONEY +#undef KIT_SAM_FISHER +#undef KIT_PROP_HUNT diff --git a/code/game/objects/items/tanks/tanks.dm b/code/game/objects/items/tanks/tanks.dm index a670a966805e780..e198f7d75d74de8 100644 --- a/code/game/objects/items/tanks/tanks.dm +++ b/code/game/objects/items/tanks/tanks.dm @@ -440,7 +440,7 @@ if(LAZYLEN(assembly.assemblies) == igniter_count) return - + if(isitem(loc)) // we are in a storage item balloon_alert(user, "can't reach!") return @@ -553,7 +553,7 @@ var/turf/T = get_turf(src) if(!T) return - log_atmos("[type] released its contents of ", air_contents) + log_atmos("[type] released its contents of ", removed) T.assume_air(removed) #undef ASSEMBLY_BOMB_BASE diff --git a/code/game/objects/items/tools/weldingtool.dm b/code/game/objects/items/tools/weldingtool.dm index c0fedb4380d6b7b..31efb0ef273f5cb 100644 --- a/code/game/objects/items/tools/weldingtool.dm +++ b/code/game/objects/items/tools/weldingtool.dm @@ -19,7 +19,7 @@ pickup_sound = 'sound/items/handling/weldingtool_pickup.ogg' light_system = OVERLAY_LIGHT light_range = 2 - light_power = 0.75 + light_power = 1.5 light_color = LIGHT_COLOR_FIRE light_on = FALSE throw_speed = 3 diff --git a/code/game/objects/items/vending_items.dm b/code/game/objects/items/vending_items.dm index 0383767ce66e8e9..7084b313dff5930 100644 --- a/code/game/objects/items/vending_items.dm +++ b/code/game/objects/items/vending_items.dm @@ -19,8 +19,10 @@ w_class = WEIGHT_CLASS_BULKY armor_type = /datum/armor/item_vending_refill - // Built automatically from the corresponding vending machine. - // If null, considered to be full. Otherwise, is list(/typepath = amount). + /** + * Built automatically from the corresponding vending machine. + * If null, considered to be full. Otherwise, is list(/typepath = amount). + */ var/list/products var/list/product_categories var/list/contraband diff --git a/code/game/objects/items/weaponry.dm b/code/game/objects/items/weaponry.dm index 059f78b80c90da9..c2f654f85530bcc 100644 --- a/code/game/objects/items/weaponry.dm +++ b/code/game/objects/items/weaponry.dm @@ -554,124 +554,6 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301 /obj/item/ectoplasm/mystic icon_state = "mysticplasm" -/obj/item/statuebust - name = "bust" - desc = "A priceless ancient marble bust, the kind that belongs in a museum." //or you can hit people with it - icon = 'icons/obj/art/statue.dmi' - icon_state = "bust" - force = 15 - throwforce = 10 - throw_speed = 5 - throw_range = 2 - attack_verb_continuous = list("busts") - attack_verb_simple = list("bust") - var/impressiveness = 45 - -/obj/item/statuebust/Initialize(mapload) - . = ..() - AddElement(/datum/element/art, impressiveness) - AddElement(/datum/element/beauty, 1000) - -/obj/item/statuebust/hippocratic - name = "hippocrates bust" - desc = "A bust of the famous Greek physician Hippocrates of Kos, often referred to as the father of western medicine." - icon_state = "hippocratic" - impressiveness = 50 - // If it hits the prob(reference_chance) chance, this is set to TRUE. Adds medical HUD when wielded, but has a 10% slower attack speed and is too bloody to make an oath with. - var/reference = FALSE - // Chance for above. - var/reference_chance = 1 - // Minimum time inbetween oaths. - COOLDOWN_DECLARE(oath_cd) - -/obj/item/statuebust/hippocratic/evil - reference_chance = 100 - -/obj/item/statuebust/hippocratic/Initialize(mapload) - . = ..() - if(prob(reference_chance)) - name = "Solemn Vow" - desc = "Art lovers will cherish the bust of Hippocrates, commemorating a time when medics still thought doing no harm was a good idea." - attack_speed = CLICK_CD_SLOW - reference = TRUE - -/obj/item/statuebust/hippocratic/examine(mob/user) - . = ..() - if(reference) - . += span_notice("You could activate the bust in-hand to swear or forswear a Hippocratic Oath... but it seems like somebody decided it was more of a Hippocratic Suggestion. This thing is caked with bits of blood and gore.") - return - . += span_notice("You can activate the bust in-hand to swear or forswear a Hippocratic Oath! This has no effects except pacifism or bragging rights. Does not remove other sources of pacifism. Do not eat.") - -/obj/item/statuebust/hippocratic/equipped(mob/living/carbon/human/user, slot) - ..() - if(!(slot & ITEM_SLOT_HANDS)) - return - var/datum/atom_hud/our_hud = GLOB.huds[DATA_HUD_MEDICAL_ADVANCED] - our_hud.show_to(user) - ADD_TRAIT(user, TRAIT_MEDICAL_HUD, type) - -/obj/item/statuebust/hippocratic/dropped(mob/living/carbon/human/user) - ..() - if(HAS_TRAIT_NOT_FROM(user, TRAIT_MEDICAL_HUD, type)) - return - var/datum/atom_hud/our_hud = GLOB.huds[DATA_HUD_MEDICAL_ADVANCED] - our_hud.hide_from(user) - REMOVE_TRAIT(user, TRAIT_MEDICAL_HUD, type) - -/obj/item/statuebust/hippocratic/attack_self(mob/user) - if(!iscarbon(user)) - to_chat(user, span_warning("You remember how the Hippocratic Oath specifies 'my fellow human beings' and realize that it's completely meaningless to you.")) - return - - if(reference) - to_chat(user, span_warning("As you prepare yourself to swear the Oath, you realize that doing so on a blood-caked bust is probably not a good idea.")) - return - - if(!COOLDOWN_FINISHED(src, oath_cd)) - to_chat(user, span_warning("You've sworn or forsworn an oath too recently to undo your decisions. The bust looks at you with disgust.")) - return - - COOLDOWN_START(src, oath_cd, 5 MINUTES) - - if(HAS_TRAIT_FROM(user, TRAIT_PACIFISM, type)) - to_chat(user, span_warning("You've already sworn a vow. You start preparing to rescind it...")) - if(do_after(user, 5 SECONDS, target = user)) - user.say("Yeah this Hippopotamus thing isn't working out. I quit!", forced = "hippocratic hippocrisy") - REMOVE_TRAIT(user, TRAIT_PACIFISM, type) - - // they can still do it for rp purposes - if(HAS_TRAIT_NOT_FROM(user, TRAIT_PACIFISM, type)) - to_chat(user, span_warning("You already don't want to harm people, this isn't going to do anything!")) - - - to_chat(user, span_notice("You remind yourself of the Hippocratic Oath's contents and prepare to swear yourself to it...")) - if(do_after(user, 4 SECONDS, target = user)) - user.say("I swear to fulfill, to the best of my ability and judgment, this covenant:", forced = "hippocratic oath") - else - return fuck_it_up(user) - if(do_after(user, 2 SECONDS, target = user)) - user.say("I will apply, for the benefit of the sick, all measures that are required, avoiding those twin traps of overtreatment and therapeutic nihilism.", forced = "hippocratic oath") - else - return fuck_it_up(user) - if(do_after(user, 3 SECONDS, target = user)) - user.say("I will remember that I remain a member of society, with special obligations to all my fellow human beings, those sound of mind and body as well as the infirm.", forced = "hippocratic oath") - else - - return fuck_it_up(user) - if(do_after(user, 3 SECONDS, target = user)) - user.say("If I do not violate this oath, may I enjoy life and art, respected while I live and remembered with affection thereafter. May I always act so as to preserve the finest traditions of my calling and may I long experience the joy of healing those who seek my help.", forced = "hippocratic oath") - else - return fuck_it_up(user) - - to_chat(user, span_notice("Contentment, understanding, and purpose washes over you as you finish the oath. You consider for a second the concept of harm and shudder.")) - ADD_TRAIT(user, TRAIT_PACIFISM, type) - -// Bully the guy for fucking up. -/obj/item/statuebust/hippocratic/proc/fuck_it_up(mob/living/carbon/user) - to_chat(user, span_warning("You forget what comes next like a dumbass. The Hippocrates bust looks down on you, disappointed.")) - user.adjustOrganLoss(ORGAN_SLOT_BRAIN, 2) - COOLDOWN_RESET(src, oath_cd) - /obj/item/tailclub name = "tail club" desc = "For the beating to death of lizards with their own tails." @@ -909,26 +791,28 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301 hitsound = 'sound/effects/snap.ogg' w_class = WEIGHT_CLASS_SMALL /// Things in this list will be instantly splatted. Flyman weakness is handled in the flyman species weakness proc. - var/list/splattable + var/static/list/splattable /// Things in this list which take a lot more damage from the fly swatter, but not be necessarily killed by it. - var/list/strong_against + var/static/list/strong_against /// How much extra damage the fly swatter does against mobs it is strong against var/extra_strength_damage = 24 /obj/item/melee/flyswatter/Initialize(mapload) . = ..() - splattable = typecacheof(list( - /mob/living/basic/ant, - /mob/living/basic/butterfly, - /mob/living/basic/cockroach, - /mob/living/basic/spider/growing/spiderling, - /mob/living/basic/bee, - /obj/effect/decal/cleanable/ants, - /obj/item/queen_bee, - )) - strong_against = typecacheof(list( - /mob/living/basic/spider/giant, - )) + if (isnull(splattable)) + splattable = typecacheof(list( + /mob/living/basic/ant, + /mob/living/basic/butterfly, + /mob/living/basic/cockroach, + /mob/living/basic/spider/growing/spiderling, + /mob/living/basic/bee, + /obj/effect/decal/cleanable/ants, + /obj/item/queen_bee, + )) + if (isnull(strong_against)) + strong_against = typecacheof(list( + /mob/living/basic/spider, + )) /obj/item/melee/flyswatter/afterattack(atom/target, mob/user, proximity_flag) diff --git a/code/game/objects/structures/bedsheet_bin.dm b/code/game/objects/structures/bedsheet_bin.dm index f80042f5679a758..50fcae8dec1382c 100644 --- a/code/game/objects/structures/bedsheet_bin.dm +++ b/code/game/objects/structures/bedsheet_bin.dm @@ -35,7 +35,7 @@ LINEN BINS /obj/item/bedsheet/Initialize(mapload) . = ..() AddComponent(/datum/component/surgery_initiator) - AddElement(/datum/element/bed_tuckable, 0, 0, 0) + AddElement(/datum/element/bed_tuckable, mapload, 0, 0, 0) if(bedsheet_type == BEDSHEET_DOUBLE) stack_amount *= 2 dying_key = DYE_REGISTRY_DOUBLE_BEDSHEET diff --git a/code/game/objects/structures/crates_lockers/closets.dm b/code/game/objects/structures/crates_lockers/closets.dm index b3d3c7085bd50da..d2df088e06f7306 100644 --- a/code/game/objects/structures/crates_lockers/closets.dm +++ b/code/game/objects/structures/crates_lockers/closets.dm @@ -94,6 +94,11 @@ GLOBAL_LIST_EMPTY(roundstart_station_closets) /// Volume of the internal air var/air_volume = TANK_STANDARD_VOLUME * 3 + /// How many pixels the closet can shift on the x axis when shaking + var/x_shake_pixel_shift = 2 + /// how many pixels the closet can shift on the y axes when shaking + var/y_shake_pixel_shift = 1 + /datum/armor/structure_closet melee = 20 bullet = 10 @@ -1031,6 +1036,9 @@ GLOBAL_LIST_EMPTY(roundstart_station_closets) user.visible_message(span_warning("[src] begins to shake violently!"), \ span_notice("You lean on the back of [src] and start pushing the door open... (this will take about [DisplayTimeText(breakout_time)].)"), \ span_hear("You hear banging from [src].")) + + addtimer(CALLBACK(src, PROC_REF(check_if_shake)), 1 SECONDS) + if(do_after(user,(breakout_time), target = src)) if(!user || user.stat != CONSCIOUS || user.loc != src || opened || (!locked && !welded) ) return @@ -1045,6 +1053,23 @@ GLOBAL_LIST_EMPTY(roundstart_station_closets) /obj/structure/closet/relay_container_resist_act(mob/living/user, obj/container) container.container_resist_act() +/// Check if someone is still resisting inside, and choose to either keep shaking or stop shaking the closet +/obj/structure/closet/proc/check_if_shake() + // Assuming we decide to shake again, how long until we check to shake again + var/next_check_time = 1 SECONDS + + // How long we shake between different calls of Shake(), so that it starts shaking and stops, instead of a steady shake + var/shake_duration = 0.3 SECONDS + + for(var/mob/living/mob in contents) + if(DOING_INTERACTION_WITH_TARGET(mob, src)) + // Shake and queue another check_if_shake + Shake(x_shake_pixel_shift, y_shake_pixel_shift, shake_duration, shake_interval = 0.1 SECONDS) + addtimer(CALLBACK(src, PROC_REF(check_if_shake)), next_check_time) + return TRUE + + // If we reach here, nobody is resisting, so dont shake + return FALSE /obj/structure/closet/proc/bust_open() SIGNAL_HANDLER diff --git a/code/game/objects/structures/crates_lockers/crates.dm b/code/game/objects/structures/crates_lockers/crates.dm index 89b6245a6a0b127..c081804d36ba37c 100644 --- a/code/game/objects/structures/crates_lockers/crates.dm +++ b/code/game/objects/structures/crates_lockers/crates.dm @@ -18,6 +18,8 @@ drag_slowdown = 0 door_anim_time = 0 // no animation pass_flags_self = PASSSTRUCTURE | LETPASSTHROW + x_shake_pixel_shift = 1 + y_shake_pixel_shift = 2 /// Mobs standing on it are nudged up by this amount. var/elevation = 14 /// The same, but when the crate is open diff --git a/code/game/objects/structures/girders.dm b/code/game/objects/structures/girders.dm index d5cc2cb177fc76d..ada42ff40d55a48 100644 --- a/code/game/objects/structures/girders.dm +++ b/code/game/objects/structures/girders.dm @@ -409,11 +409,10 @@ max_integrity = 350 /obj/structure/girder/tram - name = "tram frame" + name = "tram girder" desc = "Titanium framework to construct tram walls. Can be plated with titanium glass or other wall materials." icon_state = "tram" state = GIRDER_TRAM - density = FALSE obj_flags = CAN_BE_HIT | BLOCK_Z_OUT_DOWN /obj/structure/girder/tram/corner diff --git a/code/game/objects/structures/gym/punching_bag.dm b/code/game/objects/structures/gym/punching_bag.dm index 9c67bd89cfc09bc..f441887f2c191c2 100644 --- a/code/game/objects/structures/gym/punching_bag.dm +++ b/code/game/objects/structures/gym/punching_bag.dm @@ -44,17 +44,22 @@ flick("[icon_state]-punch", src) playsound(loc, pick(hit_sounds), 25, TRUE, -1) + if(!iscarbon(user)) + return + + var/is_heavy_gravity = user.has_gravity() > STANDARD_GRAVITY + var/stamina_exhaustion = 3 if(ishuman(user)) var/mob/living/carbon/human/boxer = user var/obj/item/clothing/gloves/boxing/boxing_gloves = boxer.get_item_by_slot(ITEM_SLOT_GLOVES) if(istype(boxing_gloves)) stamina_exhaustion = 2 + if (is_heavy_gravity) + stamina_exhaustion *= 1.5 - if(!iscarbon(user)) - return user.adjustStaminaLoss(stamina_exhaustion) - user.mind?.adjust_experience(/datum/skill/fitness, 0.1) + user.mind?.adjust_experience(/datum/skill/fitness, is_heavy_gravity ? 0.2 : 0.1) user.apply_status_effect(/datum/status_effect/exercised) /obj/structure/punching_bag/wrench_act_secondary(mob/living/user, obj/item/tool) diff --git a/code/game/objects/structures/gym/weight_machine.dm b/code/game/objects/structures/gym/weight_machine.dm index 055c9788c95da08..d3614ee6815bc91 100644 --- a/code/game/objects/structures/gym/weight_machine.dm +++ b/code/game/objects/structures/gym/weight_machine.dm @@ -133,8 +133,9 @@ user.adjust_nutrition(-5) // feel the burn if(iscarbon(user)) + var/gravity_modifier = user.has_gravity() > STANDARD_GRAVITY ? 2 : 1 // remember the real xp gain is from sleeping after working out - user.mind.adjust_experience(/datum/skill/fitness, WORKOUT_XP) + user.mind.adjust_experience(/datum/skill/fitness, WORKOUT_XP * gravity_modifier) user.apply_status_effect(/datum/status_effect/exercised, EXERCISE_STATUS_DURATION) end_workout() @@ -161,8 +162,13 @@ if(!iscarbon(user) || isnull(user.mind)) return TRUE + + var/affected_gravity = user.has_gravity() + if (!affected_gravity) + return TRUE // No weight? I could do this all day + var/gravity_modifier = affected_gravity > STANDARD_GRAVITY ? 0.75 : 1 // the amount of workouts you can do before you hit stamcrit - var/workout_reps = total_workout_reps[user.mind.get_skill_level(/datum/skill/fitness)] + var/workout_reps = total_workout_reps[user.mind.get_skill_level(/datum/skill/fitness)] * gravity_modifier // total stamina drain of 1 workout calculated based on the workout length var/stamina_exhaustion = FLOOR(user.maxHealth / workout_reps / WORKOUT_LENGTH, 0.1) user.adjustStaminaLoss(stamina_exhaustion * seconds_per_tick) diff --git a/code/game/objects/structures/lavaland/ore_vent.dm b/code/game/objects/structures/lavaland/ore_vent.dm index 08a4394346af945..70ab15427b75987 100644 --- a/code/game/objects/structures/lavaland/ore_vent.dm +++ b/code/game/objects/structures/lavaland/ore_vent.dm @@ -21,6 +21,8 @@ var/discovered = FALSE /// Is this type of vent exempt from the map's vent budget/limit? Think the free iron/glass vent or boss vents. This also causes it to not roll for random mineral breakdown. var/unique_vent = FALSE + /// Does this vent spawn a node drone when tapped? Currently unique to boss vents so try not to VV it. + var/spawn_drone_on_tap = TRUE /// What icon_state do we use when the ore vent has been tapped? var/icon_state_tapped = "ore_vent_active" /// A weighted list of what minerals are contained in this vent, with weight determining how likely each mineral is to be picked in produced boulders. @@ -40,9 +42,7 @@ /// What string do we use to warn the player about the excavation event? var/excavation_warning = "Are you ready to excavate this ore vent?" - ///Are we currently spawning mobs? - var/spawning_mobs = FALSE - /// A list of mobs that can be spawned by this vent during a wave defense event. + /// A list of mobs that can be spawned by this vent during a wave defense event. var/list/defending_mobs = list( /mob/living/basic/mining/goliath, /mob/living/basic/mining/legion/spawner_made, @@ -198,6 +198,34 @@ /obj/structure/ore_vent/proc/ore_quantity_function(ore_floor) return SHEET_MATERIAL_AMOUNT * round(boulder_size * (log(rand(1 + ore_floor, 4 + ore_floor)) ** -1)) +/** + * This confirms that the user wants to start the wave defense event, and that they can start it. + */ +/obj/structure/ore_vent/proc/pre_wave_defense(mob/user, spawn_drone = TRUE) + if(tgui_alert(user, excavation_warning, "Begin defending ore vent?", list("Yes", "No")) != "Yes") + return FALSE + if(!can_interact(user)) + return FALSE + if(!COOLDOWN_FINISHED(src, wave_cooldown) || node) + return FALSE + //This is where we start spitting out mobs. + Shake(duration = 3 SECONDS) + if(spawn_drone) + node = new /mob/living/basic/node_drone(loc) + node.arrive(src) + RegisterSignal(node, COMSIG_QDELETING, PROC_REF(handle_wave_conclusion)) + particles = new /particles/smoke/ash() + for(var/i in 1 to 5) // Clears the surroundings of the ore vent before starting wave defense. + for(var/turf/closed/mineral/rock in oview(i)) + if(istype(rock, /turf/open/misc/asteroid) && prob(35)) // so it's too common + new /obj/effect/decal/cleanable/rubble(rock) + if(prob(100 - (i * 15))) + rock.gets_drilled(user, FALSE) + if(prob(50)) + new /obj/effect/decal/cleanable/rubble(rock) + sleep(0.6 SECONDS) + return TRUE + /** * Starts the wave defense event, which will spawn a number of lavaland mobs based on the size of the ore vent. * Called after the vent has been tapped by a scanning device. @@ -221,7 +249,6 @@ wave_timer = 150 SECONDS COOLDOWN_START(src, wave_cooldown, wave_timer) addtimer(CALLBACK(src, PROC_REF(handle_wave_conclusion)), wave_timer) - spawning_mobs = TRUE icon_state = icon_state_tapped update_appearance(UPDATE_ICON_STATE) @@ -272,7 +299,7 @@ if(tapped) balloon_alert_to_viewers("vent tapped!") return - if(!COOLDOWN_FINISHED(src, wave_cooldown)) + if(!COOLDOWN_FINISHED(src, wave_cooldown) || node) //We're already defending the vent, so don't scan it again. if(!scan_only) balloon_alert_to_viewers("protect the node drone!") return @@ -302,27 +329,9 @@ return if(scan_only) return - if(tgui_alert(user, excavation_warning, "Begin defending ore vent?", list("Yes", "No")) != "Yes") - return - if(!COOLDOWN_FINISHED(src, wave_cooldown)) - return - //This is where we start spitting out mobs. - Shake(duration = 3 SECONDS) - node = new /mob/living/basic/node_drone(loc) - node.arrive(src) - RegisterSignal(node, COMSIG_QDELETING, PROC_REF(handle_wave_conclusion)) - particles = new /particles/smoke/ash() - - for(var/i in 1 to 5) // Clears the surroundings of the ore vent before starting wave defense. - for(var/turf/closed/mineral/rock in oview(i)) - if(istype(rock, /turf/open/misc/asteroid) && prob(35)) // so it's too common - new /obj/effect/decal/cleanable/rubble(rock) - if(prob(100 - (i * 15))) - rock.gets_drilled(user, FALSE) - if(prob(50)) - new /obj/effect/decal/cleanable/rubble(rock) - sleep(0.6 SECONDS) + if(!pre_wave_defense(user, spawn_drone_on_tap)) + return start_wave_defense() /** @@ -416,15 +425,15 @@ if(LARGE_VENT_TYPE) boulder_size = BOULDER_SIZE_LARGE if(mapload) - SSore_generation.ore_vent_sizes["large"] += 1 + GLOB.ore_vent_sizes["large"] += 1 if(MEDIUM_VENT_TYPE) boulder_size = BOULDER_SIZE_MEDIUM if(mapload) - SSore_generation.ore_vent_sizes["medium"] += 1 + GLOB.ore_vent_sizes["medium"] += 1 if(SMALL_VENT_TYPE) boulder_size = BOULDER_SIZE_SMALL if(mapload) - SSore_generation.ore_vent_sizes["small"] += 1 + GLOB.ore_vent_sizes["small"] += 1 else boulder_size = BOULDER_SIZE_SMALL //Might as well set a default value name = initial(name) @@ -437,8 +446,8 @@ defending_mobs = list( /mob/living/basic/mining/lobstrosity, /mob/living/basic/mining/legion/snow/spawner_made, + /mob/living/basic/mining/wolf, /mob/living/simple_animal/hostile/asteroid/polarbear, - /mob/living/simple_animal/hostile/asteroid/wolf, ) ore_vent_options = list( SMALL_VENT_TYPE, @@ -450,8 +459,8 @@ /mob/living/basic/mining/lobstrosity, /mob/living/basic/mining/legion/snow/spawner_made, /mob/living/basic/mining/ice_demon, + /mob/living/basic/mining/wolf, /mob/living/simple_animal/hostile/asteroid/polarbear, - /mob/living/simple_animal/hostile/asteroid/wolf, ) ore_vent_options = list( SMALL_VENT_TYPE = 3, @@ -463,6 +472,7 @@ name = "menacing ore vent" desc = "An ore vent, brimming with underground ore. This one has an evil aura about it. Better be careful." unique_vent = TRUE + spawn_drone_on_tap = FALSE boulder_size = BOULDER_SIZE_LARGE mineral_breakdown = list( // All the riches of the world, eeny meeny boulder room. /datum/material/iron = 1, @@ -481,7 +491,7 @@ /mob/living/simple_animal/hostile/megafauna/dragon, /mob/living/simple_animal/hostile/megafauna/colossus, ) - excavation_warning = "Something big is nearby. Are you ABSOLUTELY ready to excavate this ore vent?" + excavation_warning = "Something big is nearby. Are you ABSOLUTELY ready to excavate this ore vent? A NODE drone will be deployed after threat is neutralized." ///What boss do we want to spawn? var/summoned_boss = null @@ -506,6 +516,8 @@ . += span_notice("[boss_string] is etched onto the side of the vent.") /obj/structure/ore_vent/boss/start_wave_defense() + if(!COOLDOWN_FINISHED(src, wave_cooldown)) + return // Completely override the normal wave defense, and just spawn the boss. var/mob/living/simple_animal/hostile/megafauna/boss = new summoned_boss(loc) RegisterSignal(boss, COMSIG_LIVING_DEATH, PROC_REF(handle_wave_conclusion)) diff --git a/code/game/objects/structures/morgue.dm b/code/game/objects/structures/morgue.dm index 1935d6ba4179021..500060850b7f961 100644 --- a/code/game/objects/structures/morgue.dm +++ b/code/game/objects/structures/morgue.dm @@ -450,14 +450,10 @@ GLOBAL_LIST_EMPTY(crematoriums) /obj/structure/bodycontainer/crematorium/creamatorium/cremate(mob/user) var/list/icecreams = list() for(var/mob/living/i_scream as anything in get_all_contents_type(/mob/living)) - var/obj/item/food/icecream/IC = new /obj/item/food/icecream( - loc = null, - prefill_flavours = list(ICE_CREAM_MOB = list(null, i_scream.name)) - ) - icecreams += IC + icecreams += new /obj/item/food/icecream(null, list(ICE_CREAM_MOB = list(null, i_scream.name))) . = ..() - for(var/obj/IC in icecreams) - IC.forceMove(src) + for(var/obj/ice_cream as anything in icecreams) + ice_cream.forceMove(src) /* * Generic Tray diff --git a/code/game/objects/structures/tank_holder.dm b/code/game/objects/structures/tank_holder.dm index 9b5b33d8417eb76..5b7c9d2ed553481 100644 --- a/code/game/objects/structures/tank_holder.dm +++ b/code/game/objects/structures/tank_holder.dm @@ -142,3 +142,7 @@ /obj/structure/tank_holder/extinguisher/advanced icon_state = "holder_foam_extinguisher" tank = /obj/item/extinguisher/advanced + +/obj/structure/tank_holder/extinguisher/anti + icon_state = "holder_extinguisher" + tank = /obj/item/extinguisher/anti diff --git a/code/game/objects/structures/watercloset.dm b/code/game/objects/structures/watercloset.dm index b343cd85f50b193..edf7f2fc803c192 100644 --- a/code/game/objects/structures/watercloset.dm +++ b/code/game/objects/structures/watercloset.dm @@ -760,11 +760,9 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/structure/sink/kitchen, (-16)) open = !open if(open) layer = SIGN_LAYER - set_density(FALSE) set_opacity(FALSE) else layer = WALL_OBJ_LAYER - set_density(TRUE) if(opaque_closed) set_opacity(TRUE) diff --git a/code/game/sound.dm b/code/game/sound.dm index 393cf79a3458efb..d98c1aface5c574 100644 --- a/code/game/sound.dm +++ b/code/game/sound.dm @@ -425,4 +425,10 @@ 'sound/items/reel4.ogg', 'sound/items/reel5.ogg', ) + if(SFX_RATTLE) + soundin = pick( + 'sound/items/rattle1.ogg', + 'sound/items/rattle2.ogg', + 'sound/items/rattle3.ogg', + ) return soundin diff --git a/code/game/turfs/closed/minerals.dm b/code/game/turfs/closed/minerals.dm index 0d8f505e62337e7..c7bc4a76d58475c 100644 --- a/code/game/turfs/closed/minerals.dm +++ b/code/game/turfs/closed/minerals.dm @@ -143,15 +143,15 @@ return rand(1,5) if(distance < VENT_PROX_VERY_HIGH) - return 5 + return ORE_WALL_VERY_HIGH if(distance < VENT_PROX_HIGH) - return 4 + return ORE_WALL_HIGH if(distance < VENT_PROX_MEDIUM) - return 3 + return ORE_WALL_MEDIUM if(distance < VENT_PROX_LOW) - return 2 + return ORE_WALL_LOW if(distance < VENT_PROX_FAR) - return 1 + return ORE_WALL_FAR return 0 /turf/closed/mineral/get_smooth_underlay_icon(mutable_appearance/underlay_appearance, turf/asking_turf, adjacency_dir) @@ -323,7 +323,7 @@ var/turf/closed/mineral/M = T M.turf_type = src.turf_type M.mineralAmt = scale_ore_to_vent() - SSore_generation.post_ore_random["[M.mineralAmt]"] += 1 + GLOB.post_ore_random["[M.mineralAmt]"] += 1 src = M M.levelupdate() else @@ -334,7 +334,7 @@ Change_Ore(path, FALSE) Spread_Vein(path) mineralAmt = scale_ore_to_vent() - SSore_generation.post_ore_manual["[mineralAmt]"] += 1 + GLOB.post_ore_manual["[mineralAmt]"] += 1 /turf/closed/mineral/random/high_chance icon_state = "rock_highchance" diff --git a/code/game/turfs/closed/walls.dm b/code/game/turfs/closed/walls.dm index 4e79d835271eb87..13bc0a43da69dbb 100644 --- a/code/game/turfs/closed/walls.dm +++ b/code/game/turfs/closed/walls.dm @@ -140,7 +140,7 @@ for(var/obj/O in src.contents) //Eject contents! if(istype(O, /obj/structure/sign/poster)) var/obj/structure/sign/poster/P = O - P.roll_and_drop(src) + INVOKE_ASYNC(P, TYPE_PROC_REF(/obj/structure/sign/poster, roll_and_drop), src) if(decon_type) ChangeTurf(decon_type, flags = CHANGETURF_INHERIT_AIR) else diff --git a/code/game/turfs/open/lava.dm b/code/game/turfs/open/lava.dm index 8f9e7b44aa600eb..8165b35a256b8b0 100644 --- a/code/game/turfs/open/lava.dm +++ b/code/game/turfs/open/lava.dm @@ -249,7 +249,7 @@ /turf/open/lava/proc/can_burn_stuff(atom/movable/burn_target) if(QDELETED(burn_target)) return LAVA_BE_IGNORING - if(burn_target.movement_type & MOVETYPES_NOT_TOUCHING_GROUND) //you're flying over it. + if(burn_target.movement_type & MOVETYPES_NOT_TOUCHING_GROUND || !burn_target.has_gravity()) //you're flying over it. return LAVA_BE_IGNORING if(isobj(burn_target)) @@ -268,7 +268,7 @@ var/mob/living/burn_living = burn_target var/atom/movable/burn_buckled = burn_living.buckled if(burn_buckled) - if(burn_buckled.movement_type & MOVETYPES_NOT_TOUCHING_GROUND) + if(burn_buckled.movement_type & MOVETYPES_NOT_TOUCHING_GROUND || !burn_buckled.has_gravity()) return LAVA_BE_PROCESSING if(isobj(burn_buckled)) var/obj/burn_buckled_obj = burn_buckled diff --git a/code/game/world.dm b/code/game/world.dm index 47e92316d942152..09ae2f810641fc1 100644 --- a/code/game/world.dm +++ b/code/game/world.dm @@ -119,7 +119,7 @@ GLOBAL_VAR(restart_counter) // From a really fucking old commit (91d7150) // I wanted to move it but I think this needs to be after /world/New is called but before any sleeps? // - Dominion/Cyberboss - GLOB.timezoneOffset = text2num(time2text(0,"hh")) * 36000 + GLOB.timezoneOffset = world.timezone * 36000 // First possible sleep() InitTgs() diff --git a/code/modules/admin/admin_verbs.dm b/code/modules/admin/admin_verbs.dm index f2b7fb1aa3cedbe..9ca2ea8ff7dfb60 100644 --- a/code/modules/admin/admin_verbs.dm +++ b/code/modules/admin/admin_verbs.dm @@ -309,6 +309,10 @@ GLOBAL_PROTECT(admin_verbs_poll) add_verb(src, /client/proc/play_web_sound) if(rights & R_SPAWN) add_verb(src, GLOB.admin_verbs_spawn) +#ifdef MAP_TEST + remove_verb(src, /client/proc/enable_mapping_verbs) + add_verb(src, list(/client/proc/disable_mapping_verbs, GLOB.admin_verbs_debug_mapping)) +#endif /client/proc/remove_admin_verbs() remove_verb(src, list( @@ -1226,4 +1230,3 @@ GLOBAL_PROTECT(admin_verbs_poll) QDEL_NULL(segment.ai_controller) segment.AddComponent(/datum/component/mob_chain, front = previous) previous = segment - diff --git a/code/modules/admin/antag_panel.dm b/code/modules/admin/antag_panel.dm index b8f6737b1552e55..a54aafde916d3f5 100644 --- a/code/modules/admin/antag_panel.dm +++ b/code/modules/admin/antag_panel.dm @@ -100,6 +100,7 @@ GLOBAL_VAR(antag_prototypes) out += "Mind currently owned by key: [key] [active?"(synced)":"(not synced)"]
" out += "Assigned role: [assigned_role.title]. Edit
" out += "Faction and special role: [special_role]
" + out += "Show Teams

" var/special_statuses = get_special_statuses() if(length(special_statuses)) diff --git a/code/modules/admin/holder2.dm b/code/modules/admin/holder2.dm index e98016df74f3dd3..9d2525ed8fa2d5f 100644 --- a/code/modules/admin/holder2.dm +++ b/code/modules/admin/holder2.dm @@ -232,7 +232,7 @@ GLOBAL_PROTECT(href_token) return VALID_2FA_CONNECTION if (!SSdbcore.Connect()) - if (verify_backup_data(client)) + if (verify_backup_data(client) || (client.ckey in GLOB.protected_admins)) return VALID_2FA_CONNECTION else return list(FALSE, null) diff --git a/code/modules/antagonists/abductor/equipment/gear/abductor_posters.dm b/code/modules/antagonists/abductor/equipment/gear/abductor_posters.dm index 2938e5f4fd2f06a..3ed57df1dcacdaa 100644 --- a/code/modules/antagonists/abductor/equipment/gear/abductor_posters.dm +++ b/code/modules/antagonists/abductor/equipment/gear/abductor_posters.dm @@ -17,6 +17,12 @@ return return ..() +/obj/structure/sign/poster/abductor/attackby(obj/item/tool, mob/user, params) + if(tool.toolspeed >= 0.2) + balloon_alert(user, "tool too weak!") + return FALSE + return ..() + /obj/structure/sign/poster/abductor/random name = "random abductor poster" icon_state = "random_abductor" diff --git a/code/modules/antagonists/brother/brother.dm b/code/modules/antagonists/brother/brother.dm index 38349dce2ac410d..214825f4c73a28b 100644 --- a/code/modules/antagonists/brother/brother.dm +++ b/code/modules/antagonists/brother/brother.dm @@ -77,22 +77,23 @@ flashed.balloon_alert(source, "[flashed.p_they()] resist!") return - flashed.mind.add_antag_datum(/datum/antagonist/brother, team) + if (!team.add_brother(flashed, key_name(source))) // Shouldn't happen given the former, more specific checks but just in case + flashed.balloon_alert(source, "failed!") + return + source.log_message("converted [key_name(flashed)] to blood brother", LOG_ATTACK) flashed.log_message("was converted by [key_name(source)] to blood brother", LOG_ATTACK) - log_game("[key_name(flashed)] converted [key_name(source)] to blood brother", list( - "flashed" = flashed, - "victim" = source, + log_game("[key_name(flashed)] was made into a blood brother by [key_name(source)]", list( + "converted" = flashed, + "converted by" = source, )) - - flashed.balloon_alert(source, "converted") - to_chat(source, span_notice("[span_bold("[flashed]")] has been converted to aide you as your Brother!")) flash.burn_out() flashed.mind.add_memory( \ /datum/memory/recruited_by_blood_brother, \ protagonist = flashed, \ antagonist = owner.current, \ ) + flashed.balloon_alert(source, "converted") UnregisterSignal(source, COMSIG_MOB_SUCCESSFUL_FLASHED_CARBON) source.RemoveComponentSource(REF(src), /datum/component/can_flash_from_behind) @@ -172,6 +173,34 @@ if (prob(10)) brothers_left += 1 +/datum/team/brother_team/add_member(datum/mind/new_member) + . = ..() + if (!new_member.has_antag_datum(/datum/antagonist/brother)) + add_brother(new_member.current) + +/datum/team/brother_team/remove_member(datum/mind/member) + if (!(member in members)) + return + . = ..() + member.remove_antag_datum(/datum/antagonist/brother) + if (isnull(member.current)) + return + for (var/datum/mind/brother_mind as anything in members) + to_chat(brother_mind, span_warning("[span_bold("[member.current.real_name]")] is no longer your brother!")) + update_name() + +/// Adds a new brother to the team +/datum/team/brother_team/proc/add_brother(mob/living/new_brother, source) + if (isnull(new_brother) || isnull(new_brother.mind) || !GET_CLIENT(new_brother) || new_brother.mind.has_antag_datum(/datum/antagonist/brother)) + return FALSE + + for (var/datum/mind/brother_mind as anything in members) + if (brother_mind == new_brother.mind) + continue + to_chat(brother_mind, span_notice("[span_bold("[new_brother.real_name]")] has been converted to aid you as your brother!")) + new_brother.mind.add_antag_datum(/datum/antagonist/brother, src) + return TRUE + /datum/team/brother_team/proc/update_name() var/list/last_names = list() for(var/datum/mind/team_minds as anything in members) diff --git a/code/modules/antagonists/cult/blood_magic.dm b/code/modules/antagonists/cult/blood_magic.dm index 5fd8b5d9ee4e998..16b3def11223e69 100644 --- a/code/modules/antagonists/cult/blood_magic.dm +++ b/code/modules/antagonists/cult/blood_magic.dm @@ -405,7 +405,7 @@ if(IS_CULTIST(user)) user.visible_message(span_warning("[user] holds up [user.p_their()] hand, which explodes in a flash of red light!"), \ span_cultitalic("You attempt to stun [target] with the spell!")) - user.mob_light(range = 3, color = LIGHT_COLOR_BLOOD_MAGIC, duration = 0.2 SECONDS) + user.mob_light(range = 1.1, power = 2, color = LIGHT_COLOR_BLOOD_MAGIC, duration = 0.2 SECONDS) if(IS_HERETIC(target)) to_chat(user, span_warning("Some force greater than you intervenes! [target] is protected by the Forgotten Gods!")) to_chat(target, span_warning("You are protected by your faith to the Forgotten Gods.")) diff --git a/code/modules/antagonists/heretic/items/eldritch_painting.dm b/code/modules/antagonists/heretic/items/eldritch_painting.dm index 5aa63407dc6ef6d..5302fc1c9c148d8 100644 --- a/code/modules/antagonists/heretic/items/eldritch_painting.dm +++ b/code/modules/antagonists/heretic/items/eldritch_painting.dm @@ -92,7 +92,7 @@ if(!IS_HERETIC(examiner)) to_chat(examiner, span_hypnophrase("Respite, for now....")) examiner.mob_mood.mood_events.Remove("eldritch_weeping") - examiner.add_mood_event("weeping_withdrawl", /datum/mood_event/eldritch_painting/weeping_withdrawl) + examiner.add_mood_event("weeping_withdrawal", /datum/mood_event/eldritch_painting/weeping_withdrawal) return to_chat(examiner, span_notice("Oh, what arts! Just gazing upon it clears your mind.")) diff --git a/code/modules/antagonists/heretic/knowledge/ash_lore.dm b/code/modules/antagonists/heretic/knowledge/ash_lore.dm index ff150f0ac0fb4e7..1124d9a44403e95 100644 --- a/code/modules/antagonists/heretic/knowledge/ash_lore.dm +++ b/code/modules/antagonists/heretic/knowledge/ash_lore.dm @@ -42,7 +42,7 @@ /datum/heretic_knowledge/ashen_grasp name = "Grasp of Ash" - desc = "Your Mansus Grasp will burn the eyes of the victim, causing damage and blindness." + desc = "Your Mansus Grasp will burn the eyes of the victim, damaging them and blurring their vision." gain_text = "The Nightwatcher was the first of them, his treason started it all. \ Their lantern, expired to ash - their watch, absent." next_knowledge = list(/datum/heretic_knowledge/spell/ash_passage) @@ -70,7 +70,7 @@ /datum/heretic_knowledge/spell/ash_passage name = "Ashen Passage" - desc = "Grants you Ashen Passage, a silent but short range jaunt." + desc = "Grants you Ashen Passage, a spell that lets you phase out of reality and traverse a short distance, passing though any walls." gain_text = "He knew how to walk between the planes." next_knowledge = list( /datum/heretic_knowledge/mark/ash_mark, @@ -181,6 +181,7 @@ When completed, you become a harbinger of flames, gaining two abilites. \ Cascade, which causes a massive, growing ring of fire around you, \ and Oath of Flame, causing you to passively create a ring of flames as you walk. \ + Some ashen spells you already knew will be empowered as well. \ You will also become immune to flames, space, and similar environmental hazards." gain_text = "The Watch is dead, the Nightwatcher burned with it. Yet his fire burns evermore, \ for the Nightwatcher brought forth the rite to mankind! His gaze continues, as now I am one with the flames, \ diff --git a/code/modules/antagonists/heretic/knowledge/cosmic_lore.dm b/code/modules/antagonists/heretic/knowledge/cosmic_lore.dm index 1a16f2e9f9321ce..09efb5c2eb8f44f 100644 --- a/code/modules/antagonists/heretic/knowledge/cosmic_lore.dm +++ b/code/modules/antagonists/heretic/knowledge/cosmic_lore.dm @@ -42,7 +42,8 @@ /datum/heretic_knowledge/cosmic_grasp name = "Grasp of Cosmos" - desc = "Your Mansus Grasp will give people a star mark (cosmic ring) and create a cosmic field where you stand." + desc = "Your Mansus Grasp will give people a star mark (cosmic ring) and create a cosmic field where you stand. \ + People with a star mark can not pass cosmic fields." gain_text = "Some stars dimmed, others' magnitude increased. \ With newfound strength I could channel the nebula's power into myself." next_knowledge = list(/datum/heretic_knowledge/spell/cosmic_runes) @@ -82,7 +83,8 @@ /datum/heretic_knowledge/mark/cosmic_mark name = "Mark of Cosmos" desc = "Your Mansus Grasp now applies the Mark of Cosmos. The mark is triggered from an attack with your Cosmic Blade. \ - When triggered, the victim is returned to the location where the mark was originally applied to them. \ + When triggered, the victim is returned to the location where the mark was originally applied to them, \ + leaving a cosmic field in their place. \ They will then be paralyzed for 2 seconds." gain_text = "The Beast now whispered to me occasionally, only small tidbits of their circumstances. \ I can help them, I have to help them." @@ -98,8 +100,7 @@ name = "Star Touch" desc = "Grants you Star Touch, a spell which places a star mark upon your target \ and creates a cosmic field at your feet and to the turfs next to you. Targets which already have a star mark \ - will be forced to sleep for 4 seconds. When the victim is hit it also creates a beam that \ - deals a bit of fire damage and damages the cells. \ + will be forced to sleep for 4 seconds. When the victim is hit it also creates a beam that burns them. \ The beam lasts a minute, until the beam is obstructed or until a new target has been found." gain_text = "After waking in a cold sweat I felt a palm on my scalp, a sigil burned onto me. \ My veins now emitted a strange purple glow, the Beast knows I will surpass its expectations." @@ -110,7 +111,7 @@ /datum/heretic_knowledge/spell/star_blast name = "Star Blast" - desc = "Fires a projectile that moves very slowly and creates cosmic fields on impact. \ + desc = "Fires a projectile that moves very slowly, raising a short-lived wall of cosmic fields where it goes. \ Anyone hit by the projectile will receive burn damage, a knockdown, and give people in a three tile range a star mark." gain_text = "The Beast was behind me now at all times, with each sacrifice words of affirmation coursed through me." next_knowledge = list( @@ -243,7 +244,8 @@ You can also give it commands through speech. \ The Star Gazer is a strong ally who can even break down reinforced walls. \ The Star Gazer has an aura that will heal you and damage opponents. \ - Star Touch can now teleport you to the Star Gazer when activated in your hand." + Star Touch can now teleport you to the Star Gazer when activated in your hand. \ + Your cosmic expansion spell and your blades also become greatly empowered." gain_text = "The Beast held out its hand, I grabbed hold and they pulled me to them. Their body was towering, but it seemed so small and feeble after all their tales compiled in my head. \ I clung on to them, they would protect me, and I would protect it. \ I closed my eyes with my head laid against their form. I was safe. \ diff --git a/code/modules/antagonists/heretic/knowledge/flesh_lore.dm b/code/modules/antagonists/heretic/knowledge/flesh_lore.dm index d6fcb2f43a25708..96d67f680adbb19 100644 --- a/code/modules/antagonists/heretic/knowledge/flesh_lore.dm +++ b/code/modules/antagonists/heretic/knowledge/flesh_lore.dm @@ -122,6 +122,7 @@ /datum/heretic_knowledge/limited_amount/flesh_ghoul name = "Imperfect Ritual" desc = "Allows you to transmute a corpse and a poppy to create a Voiceless Dead. \ + The corpse does not need to have a soul. \ Voiceless Dead are mute ghouls and only have 50 health, but can use Bloody Blades effectively. \ You can only create two at a time." gain_text = "I found notes of a dark ritual, unfinished... yet still, I pushed forward." diff --git a/code/modules/antagonists/heretic/knowledge/lock_lore.dm b/code/modules/antagonists/heretic/knowledge/lock_lore.dm index 9f80f47b0ae4878..0727b86bb668e4f 100644 --- a/code/modules/antagonists/heretic/knowledge/lock_lore.dm +++ b/code/modules/antagonists/heretic/knowledge/lock_lore.dm @@ -92,9 +92,12 @@ /datum/heretic_knowledge/key_ring name = "Key Keeper’s Burden" desc = "Allows you to transmute a wallet, an iron rod, and an ID card to create an Eldritch Card. \ - It functions the same as an ID Card, but attacking it with an ID card fuses it and gains its access. \ - You can use it in-hand to change its form to a card you fused. \ - Does not preserve the card used in the ritual." + Hit a pair of airlocks with it to create a pair of portals, which will teleport you between them, but teleport non-heretics randomly. \ + You can ctrl-click the card to invert this behavior for created portals. \ + Each card may only sustain a single pair of portals at the same time. \ + It also functions and appears the same as a regular ID Card. \ + Attacking it with a normal ID card consumes it and gains its access, and you can use it in-hand to change its appearance to a card you fused. \ + Does not preserve the card originally used in the ritual." gain_text = "The Keeper sneered. \"These plastic rectangles are a mockery of keys, and I curse every door that desires them.\"" required_atoms = list( /obj/item/storage/wallet = 1, @@ -186,7 +189,8 @@ desc = "The ascension ritual of the Path of Knock. \ Bring 3 corpses without organs in their torso to a transmutation rune to complete the ritual. \ When completed, you gain the ability to transform into empowered eldritch creatures \ - and in addition, create a tear to the Labyrinth's heart; \ + and your keyblades will become even deadlier. \ + In addition, you will create a tear to the Labyrinth's heart; \ a tear in reality located at the site of this ritual. \ Eldritch creatures will endlessly pour from this rift \ who are bound to obey your instructions." diff --git a/code/modules/antagonists/heretic/knowledge/moon_lore.dm b/code/modules/antagonists/heretic/knowledge/moon_lore.dm index d7d1bd3bf22a751..723599ad262f5ae 100644 --- a/code/modules/antagonists/heretic/knowledge/moon_lore.dm +++ b/code/modules/antagonists/heretic/knowledge/moon_lore.dm @@ -45,8 +45,8 @@ /datum/heretic_knowledge/moon_grasp name = "Grasp of Lunacy" - desc = "Your Mansus Grasp will cause them to hallucinate everyone as lunar mass, \ - and hides your identity for a short dur ation." + desc = "Your Mansus Grasp will cause your victims to hallucinate everyone as lunar mass, \ + and hides your identity for a short duration." gain_text = "The troupe on the side of the moon showed me truth, and I took it." next_knowledge = list(/datum/heretic_knowledge/spell/moon_smile) cost = 1 @@ -85,9 +85,8 @@ /datum/heretic_knowledge/mark/moon_mark name = "Mark of Moon" - desc = "Your Mansus Grasp now applies the Mark of Moon. The mark is triggered from an attack with your Moon Blade. \ - When triggered, the victim is confused, and when the mark is applied they are pacified \ - until attacked." + desc = "Your Mansus Grasp now applies the Mark of Moon, pacifying the victim until attacked. \ + The mark can also be triggered from an attack with your Moon Blade, leaving the victim confused." gain_text = "The troupe on the moon would dance all day long \ and in that dance the moon would smile upon us \ but when the night came its smile would dull forced to gaze on the earth." @@ -112,9 +111,9 @@ /datum/heretic_knowledge/moon_amulette name = "Moonlight Amulette" - desc = "Allows you to transmute 2 sheets of glass, a heart and a tie \ - if the item is used on someone with low sanity they go berserk attacking everyone \ - , if their sanity isnt low enough it decreases their mood." + desc = "Allows you to transmute 2 sheets of glass, a heart and a tie to create a Moonlight Amulette. \ + If the item is used on someone with low sanity they go berserk attacking everyone, \ + if their sanity isn't low enough it decreases their mood." gain_text = "At the head of the parade he stood, the moon condensed into one mass, a reflection of the soul." next_knowledge = list( /datum/heretic_knowledge/blade_upgrade/moon, @@ -153,9 +152,9 @@ /datum/heretic_knowledge/spell/moon_ringleader name = "Ringleaders Rise" - desc = "Grants you Ringleaders Rise, an aoe spell that deals more brain damage the lower the sanity of everyone in the AoE,\ - causes hallucinations with those who have less sanity getting more. \ - If their sanity is low enough turns them insane, the spell then halves their sanity." + desc = "Grants you Ringleaders Rise, an AoE spell that deals more brain damage the lower the sanity of everyone in the AoE \ + and causes hallucinations, with those who have less sanity getting more. \ + If their sanity is low enough this turns them insane, the spell then halves their sanity." gain_text = "I grabbed his hand and we rose, those who saw the truth rose with us. \ The ringleader pointed up and the dim light of truth illuminated us further." next_knowledge = list( @@ -170,8 +169,8 @@ name = "The Last Act" desc = "The ascension ritual of the Path of Moon. \ Bring 3 corpses with more than 50 brain damage to a transmutation rune to complete the ritual. \ - When completed, you become a harbinger of madness gaining and aura of passive sanity decrease \ - , confusion increase and if their sanity is low enough brain damage and blindness. \ + When completed, you become a harbinger of madness gaining and aura of passive sanity decrease, \ + confusion increase and, if their sanity is low enough, brain damage and blindness. \ 1/5th of the crew will turn into acolytes and follow your command, they will all recieve moonlight amulettes." gain_text = "We dived down towards the crowd, his soul splitting off in search of greater venture \ for where the Ringleader had started the parade, I shall continue it unto the suns demise \ diff --git a/code/modules/antagonists/heretic/knowledge/side_ash_moon.dm b/code/modules/antagonists/heretic/knowledge/side_ash_moon.dm index 4ce8f9de9c93601..a4810c706c1186f 100644 --- a/code/modules/antagonists/heretic/knowledge/side_ash_moon.dm +++ b/code/modules/antagonists/heretic/knowledge/side_ash_moon.dm @@ -21,7 +21,7 @@ name = "Curse of Paralysis" desc = "Allows you to transmute a hatchet and both a left and right leg to cast a curse of immobility on a crew member. \ While cursed, the victim will be unable to walk. You can additionally supply an item that a victim has touched \ - or is covered in the victim's blood to empower the curse." + or is covered in the victim's blood to make the curse last longer." gain_text = "The flesh of humanity is weak. Make them bleed. Show them their fragility." next_knowledge = list( /datum/heretic_knowledge/mad_mask, @@ -58,8 +58,8 @@ /datum/heretic_knowledge/summon/ashy name = "Ashen Ritual" - desc = "Allows you to transmute a head, a pile of ash, and a book to create an Ash Man. \ - Ash Men have a short range jaunt and the ability to cause bleeding in foes at range. \ + desc = "Allows you to transmute a head, a pile of ash, and a book to create an Ash Spirit. \ + Ash Spirits have a short range jaunt and the ability to cause bleeding in foes at range. \ They also have the ability to create a ring of fire around themselves for a length of time." gain_text = "I combined my principle of hunger with my desire for destruction. The Marshal knew my name, and the Nightwatcher gazed on." next_knowledge = list( diff --git a/code/modules/antagonists/heretic/knowledge/side_cosmos_ash.dm b/code/modules/antagonists/heretic/knowledge/side_cosmos_ash.dm index 470d98e178b7e8b..14a003ce11c0b70 100644 --- a/code/modules/antagonists/heretic/knowledge/side_cosmos_ash.dm +++ b/code/modules/antagonists/heretic/knowledge/side_cosmos_ash.dm @@ -36,8 +36,9 @@ /datum/heretic_knowledge/eldritch_coin name = "Eldritch Coin" desc = "Allows you to transmute a sheet of plasma and a diamond to create an Eldritch Coin. \ - The coin will open or close nearby doors when landing on heads and bolt or unbolt nearby doors \ - when landing on tails. If the coin gets inserted into an airlock it emags the door destroying the coin." + The coin will open or close nearby doors when landing on heads and toggle their bolts \ + when landing on tails. If you insert the coin into an airlock, it will be consumed \ + to fry its electronics, opening the airlock permanently unless bolted. " gain_text = "The Mansus is a place of all sorts of sins. But greed held a special role." next_knowledge = list( /datum/heretic_knowledge/spell/cosmic_expansion, diff --git a/code/modules/antagonists/heretic/knowledge/side_lock_flesh.dm b/code/modules/antagonists/heretic/knowledge/side_lock_flesh.dm index e2825c6db2869cc..74013f2b0bd1da6 100644 --- a/code/modules/antagonists/heretic/knowledge/side_lock_flesh.dm +++ b/code/modules/antagonists/heretic/knowledge/side_lock_flesh.dm @@ -2,7 +2,8 @@ /datum/heretic_knowledge/spell/opening_blast name = "Wave Of Desperation" desc = "Grants you Wave Of Desparation, a spell which can only be cast while restrained. \ - It removes your restraints, repels and knocks down adjacent people, and applies the Mansus Grasp to everything nearby." + It removes your restraints, repels and knocks down adjacent people, and applies the Mansus Grasp to everything nearby. \ + However, you will fall unconscious a short time after casting this spell." gain_text = "My shackles undone in dark fury, their feeble bindings crumble before my power." next_knowledge = list( /datum/heretic_knowledge/summon/raw_prophet, diff --git a/code/modules/antagonists/heretic/knowledge/side_lock_moon.dm b/code/modules/antagonists/heretic/knowledge/side_lock_moon.dm index 737e0f08f40a1cc..f1dd564310be502 100644 --- a/code/modules/antagonists/heretic/knowledge/side_lock_moon.dm +++ b/code/modules/antagonists/heretic/knowledge/side_lock_moon.dm @@ -16,10 +16,10 @@ /datum/heretic_knowledge/unfathomable_curio name = "Unfathomable Curio" - desc = "Allows you to transmute 3 rods, a brain and a belt into an Unfathomable Curio\ - , a belt that can hold blades and items for rituals. Whilst worn will also \ + desc = "Allows you to transmute 3 rods, lungs and any belt into an Unfathomable Curio\ + , a belt that can hold blades and items for rituals. Whilst worn it will also \ veil you, allowing you to take 5 hits without suffering damage, this veil will recharge very slowly \ - outside of combat. When examined the examiner will suffer brain damage and blindness." + outside of combat." gain_text = "The mansus holds many a curio, some are not meant for the mortal eye." next_knowledge = list( /datum/heretic_knowledge/spell/burglar_finesse, @@ -38,12 +38,12 @@ name = "Unsealed Arts" desc = "Allows you to transmute a canvas and an additional item to create a piece of art, these paintings \ have different effects depending on the additional item added. Possible paintings: \ - The sister and He Who Wept: Eyes. When a non-heretic looks at the painting they will begin to hallucinate everyone as heretics. \ - The First Desire: Any bodypart. Increases the hunger of non-heretics, when examined drops an organ or body part at your feet. \ - Great chaparral over rolling hills: Any grown food. Spreads kudzu when placed, when examined grants a flower. \ - Lady out of gates: Gloves. Causes non-heretics to scratch themselves, when examined removes all your mutations. \ - Climb over the rusted mountain: Trash. Causes non-heretics to rust the floor they walk on. \ - These effects are mitigated for a few minutes when a non-heretic suffering an effect examines the painting that caused the effect." + The sister and He Who Wept: Eyes. Clears your own mind, but curses non-heretics with hallucinations. \ + The First Desire: Any bodypart. Supplies you with random organs, but curses non-heretics with a hunger for flesh. \ + Great chaparral over rolling hills: Any grown food. Spreads kudzu when placed and examined by non-heretics. Also supplies you with poppies and harebells. \ + Lady out of gates: Gloves. Clears your mutations, but mutates non-heretics and curses them with scratching. \ + Climb over the rusted mountain: Trash. Curses non-heretics to rust the floor they walk on. \ + Non-heretics can counter most of these effects by examining one of these paintings." gain_text = "A wind of inspiration blows through me, past the walls and past the gate inspirations lie, yet to be depicted. \ They yearn for mortal eyes again, and I shall grant that wish." next_knowledge = list( diff --git a/code/modules/antagonists/heretic/knowledge/side_rust_cosmos.dm b/code/modules/antagonists/heretic/knowledge/side_rust_cosmos.dm index 2dbb44ea4eb7ed9..3d326b4a9af452d 100644 --- a/code/modules/antagonists/heretic/knowledge/side_rust_cosmos.dm +++ b/code/modules/antagonists/heretic/knowledge/side_rust_cosmos.dm @@ -44,7 +44,7 @@ name = "Curse of Corrosion" desc = "Allows you to transmute wirecutters, a pool of vomit, and a heart to cast a curse of sickness on a crew member. \ While cursed, the victim will repeatedly vomit while their organs will take constant damage. You can additionally supply an item \ - that a victim has touched or is covered in the victim's blood to empower the curse." + that a victim has touched or is covered in the victim's blood to make the curse last longer." gain_text = "The body of humanity is temporary. Their weaknesses cannot be stopped, like iron falling to rust. Show them all." next_knowledge = list( /datum/heretic_knowledge/spell/area_conversion, diff --git a/code/modules/antagonists/heretic/knowledge/side_void_blade.dm b/code/modules/antagonists/heretic/knowledge/side_void_blade.dm index 643fd434af7b5a0..e044eee8619ef8b 100644 --- a/code/modules/antagonists/heretic/knowledge/side_void_blade.dm +++ b/code/modules/antagonists/heretic/knowledge/side_void_blade.dm @@ -144,7 +144,8 @@ name = "Maid in the Mirror" desc = "Allows you to transmute five sheets of titanium, a flash, a suit of armor, and a pair of lungs \ to create a Maid in the Mirror. Maid in the Mirrors are decent combatants that can become incorporeal by \ - phasing in and out of the mirror realm, serving as powerful scouts and ambushers." + phasing in and out of the mirror realm, serving as powerful scouts and ambushers. \ + However, they are weak to mortal gaze and take damage by being examined." gain_text = "Within each reflection, lies a gateway into an unimaginable world of colors never seen and \ people never met. The ascent is glass, and the walls are knives. Each step is blood, if you do not have a guide." next_knowledge = list( diff --git a/code/modules/antagonists/heretic/magic/apetravulnera.dm b/code/modules/antagonists/heretic/magic/apetravulnera.dm index 801104dddf9fc29..e80d08911848cb5 100644 --- a/code/modules/antagonists/heretic/magic/apetravulnera.dm +++ b/code/modules/antagonists/heretic/magic/apetravulnera.dm @@ -5,7 +5,7 @@ background_icon_state = "bg_heretic" overlay_icon_state = "bg_heretic_border" button_icon = 'icons/mob/actions/actions_ecult.dmi' - button_icon_state = "cleave" + button_icon_state = "apetra_vulnera" school = SCHOOL_FORBIDDEN cooldown_time = 45 SECONDS @@ -23,7 +23,7 @@ /datum/action/cooldown/spell/pointed/apetra_vulnera/cast(mob/living/carbon/human/cast_on) . = ..() - + if(IS_HERETIC_OR_MONSTER(cast_on)) return FALSE @@ -44,7 +44,7 @@ a_limb_got_damaged = TRUE var/datum/wound/slash/crit_wound = new wound_type() crit_wound.apply_wound(bodypart) - + if(!a_limb_got_damaged) var/datum/wound/slash/crit_wound = new wound_type() crit_wound.apply_wound(pick(cast_on.bodyparts)) @@ -53,7 +53,7 @@ span_danger("[cast_on]'s scratches and bruises are torn open by an unholy force!"), span_danger("Your scratches and bruises are torn open by some horrible unholy force!") ) - + new /obj/effect/temp_visual/cleave(get_turf(cast_on)) return TRUE diff --git a/code/modules/antagonists/heretic/magic/ascended_shapeshift.dm b/code/modules/antagonists/heretic/magic/ascended_shapeshift.dm index 18e8d26fecc60fe..e792dc116da6fdc 100644 --- a/code/modules/antagonists/heretic/magic/ascended_shapeshift.dm +++ b/code/modules/antagonists/heretic/magic/ascended_shapeshift.dm @@ -6,6 +6,8 @@ cooldown_time = 20 SECONDS convert_damage = FALSE die_with_shapeshifted_form = FALSE + button_icon = 'icons/mob/actions/actions_ecult.dmi' + button_icon_state = "lock_ascension" possible_shapes = list( /mob/living/basic/heretic_summon/ash_spirit, /mob/living/basic/heretic_summon/raw_prophet/ascended, diff --git a/code/modules/antagonists/heretic/magic/caretaker.dm b/code/modules/antagonists/heretic/magic/caretaker.dm index 29fcecf076fb059..86ff285001917b9 100644 --- a/code/modules/antagonists/heretic/magic/caretaker.dm +++ b/code/modules/antagonists/heretic/magic/caretaker.dm @@ -6,8 +6,8 @@ and you can be removed from it upon contact with antimagical artifacts." background_icon_state = "bg_heretic" overlay_icon_state = "bg_heretic_border" - button_icon = 'icons/mob/actions/actions_minor_antag.dmi' - button_icon_state = "ninja_cloak" + button_icon = 'icons/mob/actions/actions_ecult.dmi' + button_icon_state = "caretaker" sound = 'sound/effects/curse2.ogg' school = SCHOOL_FORBIDDEN diff --git a/code/modules/antagonists/heretic/magic/cosmic_runes.dm b/code/modules/antagonists/heretic/magic/cosmic_runes.dm index 5115a2181fa9110..4af3b94b44f34d9 100644 --- a/code/modules/antagonists/heretic/magic/cosmic_runes.dm +++ b/code/modules/antagonists/heretic/magic/cosmic_runes.dm @@ -1,6 +1,7 @@ /datum/action/cooldown/spell/cosmic_rune name = "Cosmic Rune" - desc = "Creates a cosmic rune at your position, only two can exist at a time. Invoking one rune transports you to the other." + desc = "Creates a cosmic rune at your position, only two can exist at a time. Invoking one rune transports you to the other. \ + Anyone with a star mark gets transported along with you." background_icon_state = "bg_heretic" overlay_icon_state = "bg_heretic_border" button_icon = 'icons/mob/actions/actions_ecult.dmi' diff --git a/code/modules/antagonists/heretic/magic/moon_parade.dm b/code/modules/antagonists/heretic/magic/moon_parade.dm index 409e55bf9261acc..3b7f1d007cd6e18 100644 --- a/code/modules/antagonists/heretic/magic/moon_parade.dm +++ b/code/modules/antagonists/heretic/magic/moon_parade.dm @@ -1,6 +1,6 @@ /datum/action/cooldown/spell/pointed/projectile/moon_parade name = "Lunar parade" - desc = "This unleashes the parade towards a target." + desc = "This unleashes the parade, making everyone in its way join it and suffer hallucinations." background_icon_state = "bg_heretic" overlay_icon_state = "bg_heretic_border" button_icon = 'icons/mob/actions/actions_ecult.dmi' diff --git a/code/modules/antagonists/heretic/magic/moon_ringleader.dm b/code/modules/antagonists/heretic/magic/moon_ringleader.dm index 45d3285a876dade..3c0b1d2aedb52cd 100644 --- a/code/modules/antagonists/heretic/magic/moon_ringleader.dm +++ b/code/modules/antagonists/heretic/magic/moon_ringleader.dm @@ -1,7 +1,8 @@ /datum/action/cooldown/spell/aoe/moon_ringleader name = "Ringleaders Rise" - desc = "Big AoE spell that deals more brain damage the lower the sanity of everyone in the AoE and it also causes hallucinations with those who have less sanity getting more. \ - If their sanity is low enough they snap and go insane, the spell then halves their sanity." + desc = "Big AoE spell that deals brain damage and causes hallucinations to everyone in the AoE. \ + The worse their sanity, the stronger this spell becomes. \ + If their sanity is low enough, they even snap and go insane, and the spell then further halves their sanity." background_icon_state = "bg_heretic" overlay_icon_state = "bg_heretic_border" button_icon = 'icons/mob/actions/actions_ecult.dmi' diff --git a/code/modules/antagonists/heretic/magic/nightwatcher_rebirth.dm b/code/modules/antagonists/heretic/magic/nightwatcher_rebirth.dm index 64638d7103b17b7..4e37f5db17fed5e 100644 --- a/code/modules/antagonists/heretic/magic/nightwatcher_rebirth.dm +++ b/code/modules/antagonists/heretic/magic/nightwatcher_rebirth.dm @@ -1,6 +1,6 @@ /datum/action/cooldown/spell/aoe/fiery_rebirth name = "Nightwatcher's Rebirth" - desc = "A spell that extinguishes you drains nearby heathens engulfed in flames of their life force, \ + desc = "A spell that extinguishes you and drains nearby heathens engulfed in flames of their life force, \ healing you for each victim drained. Those in critical condition \ will have the last of their vitality drained, killing them." background_icon_state = "bg_heretic" diff --git a/code/modules/antagonists/heretic/magic/rust_charge.dm b/code/modules/antagonists/heretic/magic/rust_charge.dm index d5427cf3762622d..56054bd56fdd851 100644 --- a/code/modules/antagonists/heretic/magic/rust_charge.dm +++ b/code/modules/antagonists/heretic/magic/rust_charge.dm @@ -1,7 +1,9 @@ // Rust charge, a charge action that can only be started on rust (and only destroys rust tiles) /datum/action/cooldown/mob_cooldown/charge/rust name = "Rust Charge" - desc = "A charge that must be started on a rusted tile and will destroy any rusted objects you come into contact with, will deal high damage to others and rust around you during the charge. As it is the rust that empoweres you for this ability, no focus is needed" + desc = "A charge that must be started on a rusted tile and will destroy any rusted objects you come into contact with, \ + will deal high damage to others and rust around you during the charge. \ + As it is the rust that empowers you with this ability, no focus is needed." charge_distance = 10 charge_damage = 50 cooldown_time = 45 SECONDS diff --git a/code/modules/antagonists/heretic/magic/star_blast.dm b/code/modules/antagonists/heretic/magic/star_blast.dm index 212e90535d6c7ce..48fdf2f26934b06 100644 --- a/code/modules/antagonists/heretic/magic/star_blast.dm +++ b/code/modules/antagonists/heretic/magic/star_blast.dm @@ -1,6 +1,6 @@ /datum/action/cooldown/spell/pointed/projectile/star_blast name = "Star Blast" - desc = "This spell fires a disk with cosmic energies at a target." + desc = "This spell fires a disk with cosmic energies at a target, spreading the star mark." background_icon_state = "bg_heretic" overlay_icon_state = "bg_heretic_border" button_icon = 'icons/mob/actions/actions_ecult.dmi' diff --git a/code/modules/antagonists/heretic/magic/star_touch.dm b/code/modules/antagonists/heretic/magic/star_touch.dm index 9037d07295a9446..89c5d02e7d4981c 100644 --- a/code/modules/antagonists/heretic/magic/star_touch.dm +++ b/code/modules/antagonists/heretic/magic/star_touch.dm @@ -1,7 +1,8 @@ /datum/action/cooldown/spell/touch/star_touch name = "Star Touch" - desc = "Marks someone with a star mark or puts someone with a star mark to sleep for 4 seconds, removing the star mark. \ - You and your target are linked with a cosmic ray, burning them for up to a minute, or \ + desc = "Manifests cosmic fields on tiles next to you while marking the victim with a star mark \ + or consuming an already present star mark to put them to sleep for 4 seconds. \ + They will then be linked to you with a cosmic ray, burning them for up to a minute, or \ until they can escape your sight. Star Touch can also remove Cosmic Runes, or teleport you \ to your Star Gazer when used on yourself." background_icon_state = "bg_heretic" diff --git a/code/modules/antagonists/heretic/status_effects/debuffs.dm b/code/modules/antagonists/heretic/status_effects/debuffs.dm index 08839fa8f10583c..7037d1cc3778b6f 100644 --- a/code/modules/antagonists/heretic/status_effects/debuffs.dm +++ b/code/modules/antagonists/heretic/status_effects/debuffs.dm @@ -280,7 +280,7 @@ /datum/status_effect/moon_converted/on_remove() // Span warning and unconscious so they realize they aren't evil anymore - to_chat(owner, span_warning("Your mind is cleared from the effect of the manus, your alligiences are as they were before")) + to_chat(owner, span_warning("Your mind is cleared from the effect of the mansus, your alligiences are as they were before")) REMOVE_TRAIT(owner, TRAIT_MUTE, REF(src)) owner.AdjustUnconscious(5 SECONDS, ignore_canstun = FALSE) owner.log_message("[owner] is no longer insane.", LOG_GAME) diff --git a/code/modules/antagonists/nukeop/equipment/nuclear_authentication_disk.dm b/code/modules/antagonists/nukeop/equipment/nuclear_authentication_disk.dm index 72c51f14b2b9985..c318679b4f6febf 100644 --- a/code/modules/antagonists/nukeop/equipment/nuclear_authentication_disk.dm +++ b/code/modules/antagonists/nukeop/equipment/nuclear_authentication_disk.dm @@ -26,7 +26,7 @@ /obj/item/disk/nuclear/Initialize(mapload) . = ..() - AddElement(/datum/element/bed_tuckable, 6, -6, 0) + AddElement(/datum/element/bed_tuckable, mapload, 6, -6, 0) AddComponent(/datum/component/stationloving, !fake) if(!fake) diff --git a/code/modules/antagonists/nukeop/outfits.dm b/code/modules/antagonists/nukeop/outfits.dm index a3c97a764688bc5..e6a3fe6623d7f9d 100644 --- a/code/modules/antagonists/nukeop/outfits.dm +++ b/code/modules/antagonists/nukeop/outfits.dm @@ -77,6 +77,7 @@ backpack_contents = list( /obj/item/gun/ballistic/automatic/pistol/clandestine = 1, /obj/item/pen/edagger = 1, + /obj/item/ammo_box/magazine/m12g = 3, ) /datum/outfit/syndicate/full/plasmaman diff --git a/code/modules/antagonists/wizard/grand_ritual/finales/immortality.dm b/code/modules/antagonists/wizard/grand_ritual/finales/immortality.dm index 92489145fda9740..85267c0333c451a 100644 --- a/code/modules/antagonists/wizard/grand_ritual/finales/immortality.dm +++ b/code/modules/antagonists/wizard/grand_ritual/finales/immortality.dm @@ -148,6 +148,7 @@ color = COLOR_PALE_GREEN light_range = 2 light_color = COLOR_PALE_GREEN + resistance_flags = parent_type::resistance_flags | SHUTTLE_CRUSH_PROOF /// Who are we reviving? var/mob/living/corpse /// Who if anyone is playing as them? diff --git a/code/modules/assembly/flash.dm b/code/modules/assembly/flash.dm index 5319d4465e2ab9a..659bcec50cf9765 100644 --- a/code/modules/assembly/flash.dm +++ b/code/modules/assembly/flash.dm @@ -171,7 +171,7 @@ visible_message(span_danger("[user] blinds [flashed] with the flash!"), span_userdanger("[user] blinds you with the flash!")) //easy way to make sure that you can only long stun someone who is facing in your direction flashed.adjustStaminaLoss(rand(80, 120) * (1 - (deviation * 0.5))) - flashed.Paralyze(rand(25, 50) * (1 - (deviation * 0.5))) + flashed.Knockdown(rand(25, 50) * (1 - (deviation * 0.5))) SEND_SIGNAL(user, COMSIG_MOB_SUCCESSFUL_FLASHED_CARBON, flashed, src, deviation) else if(user) diff --git a/code/modules/atmospherics/gasmixtures/gas_mixture.dm b/code/modules/atmospherics/gasmixtures/gas_mixture.dm index 87523034f3ecc1c..cfb87ce7cb3fed0 100644 --- a/code/modules/atmospherics/gasmixtures/gas_mixture.dm +++ b/code/modules/atmospherics/gasmixtures/gas_mixture.dm @@ -184,7 +184,7 @@ GLOBAL_LIST_INIT(gaslist_cache, init_gaslist_cache()) if(amount <= 0) return null var/ratio = amount / sum - var/datum/gas_mixture/removed = new type + var/datum/gas_mixture/removed = new type(volume) var/list/removed_gases = removed.gases //accessing datum vars is slower than proc vars removed.temperature = temperature @@ -206,7 +206,7 @@ GLOBAL_LIST_INIT(gaslist_cache, init_gaslist_cache()) ratio = min(ratio, 1) var/list/cached_gases = gases - var/datum/gas_mixture/removed = new type + var/datum/gas_mixture/removed = new type(volume) var/list/removed_gases = removed.gases //accessing datum vars is slower than proc vars removed.temperature = temperature diff --git a/code/modules/atmospherics/machinery/atmosmachinery.dm b/code/modules/atmospherics/machinery/atmosmachinery.dm index be455ea6d47093d..d42618e9ee99dab 100644 --- a/code/modules/atmospherics/machinery/atmosmachinery.dm +++ b/code/modules/atmospherics/machinery/atmosmachinery.dm @@ -54,6 +54,10 @@ ///Whether it can be painted var/paintable = TRUE + ///Whether it will generate cap sprites when hidden + var/has_cap_visuals = FALSE + ///Cap overlay that is being added to turf's `vis_contents`, `null` if pipe was never hidden or has no valid connections + var/obj/effect/overlay/cap_visual/cap_overlay ///Is the thing being rebuilt by SSair or not. Prevents list bloat var/rebuilding = FALSE @@ -106,6 +110,10 @@ if(isturf(loc)) turf_loc = loc turf_loc.add_blueprints_preround(src) + + if(hide) + RegisterSignal(src, COMSIG_OBJ_HIDE, PROC_REF(on_hide)) + SSspatial_grid.add_grid_awareness(src, SPATIAL_GRID_CONTENTS_TYPE_ATMOS) SSspatial_grid.add_grid_membership(src, turf_loc, SPATIAL_GRID_CONTENTS_TYPE_ATMOS) if(init_processing) @@ -119,11 +127,22 @@ SSair.stop_processing_machine(src) SSair.rebuild_queue -= src - if(pipe_vision_img) - qdel(pipe_vision_img) + QDEL_NULL(pipe_vision_img) + QDEL_NULL(cap_overlay) return ..() - //return QDEL_HINT_FINDREFERENCE + +/** + * Handler for `COMSIG_OBJ_HIDE`, connects only if `hide` is set to `TRUE`. Calls `update_cap_visuals` on pipe and its connected nodes + */ +/obj/machinery/atmospherics/proc/on_hide(datum/source, underfloor_accessibility) + SHOULD_CALL_PARENT(TRUE) + SIGNAL_HANDLER + + for(var/obj/machinery/atmospherics/node in nodes) + node.update_cap_visuals() + + update_cap_visuals() /** * Run when you update the conditions in which an /atom might want to start reacting to its turf's air @@ -205,8 +224,9 @@ update_appearance() /obj/machinery/atmospherics/update_icon() - . = ..() update_layer() + update_cap_visuals() + return ..() /** * Find a connecting /obj/machinery/atmospherics in specified direction, called by relaymove() @@ -616,6 +636,52 @@ /obj/machinery/atmospherics/proc/update_layer() return +/** + * Handles cap overlay addition and removal, won't do anything if `has_cap_visuals` is set to `FALSE` + */ +/obj/machinery/atmospherics/proc/update_cap_visuals() + if(!has_cap_visuals) + return + + cap_overlay?.moveToNullspace() + + if(!HAS_TRAIT(src, TRAIT_UNDERFLOOR)) + return + + var/connections = NONE + for(var/obj/machinery/atmospherics/node in nodes) + if(HAS_TRAIT(node, TRAIT_UNDERFLOOR)) + continue + + if(isplatingturf(get_turf(node))) + continue + + var/connected_dir = get_dir(src, node) + connections |= connected_dir + + if(connections == NONE) + return + + var/bitfield = CARDINAL_TO_PIPECAPS(connections) | (~connections) & ALL_CARDINALS + var/turf/our_turf = get_turf(src) + + if(isnull(cap_overlay)) + cap_overlay = new + + SET_PLANE_EXPLICIT(cap_overlay, initial(plane), our_turf) + + cap_overlay.color = pipe_color + cap_overlay.layer = layer + cap_overlay.icon_state = "[bitfield]_[piping_layer]" + + cap_overlay.forceMove(our_turf) + +/obj/effect/overlay/cap_visual + mouse_opacity = MOUSE_OPACITY_TRANSPARENT + icon = 'icons/obj/pipes_n_cables/!pipes_bitmask.dmi' + vis_flags = NONE + anchored = TRUE + /** * Called by the RPD.dm pre_attack() * Arguments: diff --git a/code/modules/atmospherics/machinery/components/components_base.dm b/code/modules/atmospherics/machinery/components/components_base.dm index e72d72b3d595512..b4e5d88d62c7186 100644 --- a/code/modules/atmospherics/machinery/components/components_base.dm +++ b/code/modules/atmospherics/machinery/components/components_base.dm @@ -32,12 +32,6 @@ component_mixture.volume = 200 airs[i] = component_mixture -/obj/machinery/atmospherics/components/Initialize(mapload) - . = ..() - - if(hide) - RegisterSignal(src, COMSIG_OBJ_HIDE, PROC_REF(hide_pipe)) - // Iconnery /** @@ -46,11 +40,14 @@ /obj/machinery/atmospherics/components/proc/update_icon_nopipes() return +/obj/machinery/atmospherics/components/on_hide(datum/source, underfloor_accessibility) + hide_pipe(underfloor_accessibility) + return ..() + /** - * Called in Initialize(), set the showpipe var to true or false depending on the situation, calls update_icon() + * Called in on_hide(), set the showpipe var to true or false depending on the situation, calls update_icon() */ -/obj/machinery/atmospherics/components/proc/hide_pipe(datum/source, underfloor_accessibility) - SIGNAL_HANDLER +/obj/machinery/atmospherics/components/proc/hide_pipe(underfloor_accessibility) showpipe = !!underfloor_accessibility if(showpipe) REMOVE_TRAIT(src, TRAIT_UNDERFLOOR, REF(src)) diff --git a/code/modules/atmospherics/machinery/components/unary_devices/outlet_injector.dm b/code/modules/atmospherics/machinery/components/unary_devices/outlet_injector.dm index ea20f2eeb66a8a9..4161a30ed7d723c 100644 --- a/code/modules/atmospherics/machinery/components/unary_devices/outlet_injector.dm +++ b/code/modules/atmospherics/machinery/components/unary_devices/outlet_injector.dm @@ -10,6 +10,7 @@ hide = TRUE layer = GAS_SCRUBBER_LAYER pipe_state = "injector" + has_cap_visuals = TRUE resistance_flags = FIRE_PROOF | UNACIDABLE | ACID_PROOF //really helpful in building gas chambers for xenomorphs idle_power_usage = BASE_MACHINE_IDLE_CONSUMPTION * 0.25 @@ -74,6 +75,8 @@ if(showpipe) // everything is already shifted so don't shift the cap add_overlay(get_pipe_image(icon, "inje_cap", initialize_directions, pipe_color)) + else + PIPING_LAYER_SHIFT(src, PIPING_LAYER_DEFAULT) if(!nodes[1] || !on || !is_operational) icon_state = "inje_off" diff --git a/code/modules/atmospherics/machinery/components/unary_devices/passive_vent.dm b/code/modules/atmospherics/machinery/components/unary_devices/passive_vent.dm index f461cbe8988f8ec..17f6c761f129dc7 100644 --- a/code/modules/atmospherics/machinery/components/unary_devices/passive_vent.dm +++ b/code/modules/atmospherics/machinery/components/unary_devices/passive_vent.dm @@ -10,6 +10,7 @@ shift_underlay_only = FALSE pipe_state = "pvent" + has_cap_visuals = TRUE vent_movement = VENTCRAWL_ALLOWED | VENTCRAWL_CAN_SEE | VENTCRAWL_ENTRANCE_ALLOWED /obj/machinery/atmospherics/components/unary/passive_vent/update_icon_nopipes() @@ -17,6 +18,8 @@ if(showpipe) var/image/cap = get_pipe_image(icon, "vent_cap", initialize_directions, pipe_color) add_overlay(cap) + else + PIPING_LAYER_SHIFT(src, PIPING_LAYER_DEFAULT) icon_state = "passive_vent" /obj/machinery/atmospherics/components/unary/passive_vent/process_atmos() diff --git a/code/modules/atmospherics/machinery/components/unary_devices/portables_connector.dm b/code/modules/atmospherics/machinery/components/unary_devices/portables_connector.dm index d5eada4e73f8946..f47d6d5b069ca3a 100644 --- a/code/modules/atmospherics/machinery/components/unary_devices/portables_connector.dm +++ b/code/modules/atmospherics/machinery/components/unary_devices/portables_connector.dm @@ -13,6 +13,8 @@ pipe_flags = PIPING_ONE_PER_TURF pipe_state = "connector" + has_cap_visuals = TRUE + custom_reconcilation = TRUE ///Reference to the connected device @@ -29,11 +31,13 @@ return ..() /obj/machinery/atmospherics/components/unary/portables_connector/update_icon_nopipes() - icon_state = "connector" + cut_overlays() if(showpipe) - cut_overlays() var/image/cap = get_pipe_image(icon, "connector_cap", initialize_directions, pipe_color) add_overlay(cap) + else + PIPING_LAYER_SHIFT(src, PIPING_LAYER_DEFAULT) + icon_state = "connector" /obj/machinery/atmospherics/components/unary/portables_connector/process_atmos() if(!connected_device) diff --git a/code/modules/atmospherics/machinery/components/unary_devices/thermomachine.dm b/code/modules/atmospherics/machinery/components/unary_devices/thermomachine.dm index 46adfee054e6e65..aa890b0b574a0a1 100644 --- a/code/modules/atmospherics/machinery/components/unary_devices/thermomachine.dm +++ b/code/modules/atmospherics/machinery/components/unary_devices/thermomachine.dm @@ -16,8 +16,6 @@ layer = OBJ_LAYER circuit = /obj/item/circuitboard/machine/thermomachine - hide = TRUE - move_resist = MOVE_RESIST_DEFAULT vent_movement = NONE pipe_flags = PIPING_ONE_PER_TURF 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 f3c5563fd3afd30..bece67572b6f569 100644 --- a/code/modules/atmospherics/machinery/components/unary_devices/vent_pump.dm +++ b/code/modules/atmospherics/machinery/components/unary_devices/vent_pump.dm @@ -14,6 +14,7 @@ hide = TRUE shift_underlay_only = FALSE pipe_state = "uvent" + has_cap_visuals = TRUE 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 diff --git a/code/modules/atmospherics/machinery/components/unary_devices/vent_scrubber.dm b/code/modules/atmospherics/machinery/components/unary_devices/vent_scrubber.dm index 051299950bc68c9..0eadf783e5e9fb1 100644 --- a/code/modules/atmospherics/machinery/components/unary_devices/vent_scrubber.dm +++ b/code/modules/atmospherics/machinery/components/unary_devices/vent_scrubber.dm @@ -12,6 +12,7 @@ hide = TRUE shift_underlay_only = FALSE pipe_state = "scrubber" + has_cap_visuals = TRUE vent_movement = VENTCRAWL_ALLOWED | VENTCRAWL_CAN_SEE | VENTCRAWL_ENTRANCE_ALLOWED processing_flags = NONE diff --git a/code/modules/atmospherics/machinery/pipes/pipe_spritesheet_helper.dm b/code/modules/atmospherics/machinery/pipes/pipe_spritesheet_helper.dm index 9642442a9733f51..6b1997cc3c718b4 100644 --- a/code/modules/atmospherics/machinery/pipes/pipe_spritesheet_helper.dm +++ b/code/modules/atmospherics/machinery/pipes/pipe_spritesheet_helper.dm @@ -18,6 +18,13 @@ "[WEST]"=icon('icons/obj/pipes_n_cables/pipe_template_pieces.dmi', "damage_mask", WEST), ) + var/static/list/icon/cap_masks = list( + "[NORTH]" = icon('icons/obj/pipes_n_cables/pipe_template_pieces.dmi', "cap_mask", NORTH), + "[EAST]" = icon('icons/obj/pipes_n_cables/pipe_template_pieces.dmi', "cap_mask", EAST), + "[SOUTH]" = icon('icons/obj/pipes_n_cables/pipe_template_pieces.dmi', "cap_mask", SOUTH), + "[WEST]" = icon('icons/obj/pipes_n_cables/pipe_template_pieces.dmi', "cap_mask", WEST), + ) + var/icon/generated_icons /datum/pipe_icon_generator/proc/Start(icon_state_suffix="") @@ -85,6 +92,34 @@ outputs[damaged] = "[icon_state_dirs]_[layer]" return outputs +/datum/pipe_icon_generator/proc/generate_capped(icon/working, layer, dirs, x_offset=1, y_offset=1) + var/list/outputs = list() + var/list/completed = list() + for(var/combined_dirs in 1 to 15) + combined_dirs &= dirs + + var/completion_key = "[combined_dirs]" + if(completed[completion_key] || (combined_dirs == NONE)) + continue + + completed[completion_key] = TRUE + + var/icon/capped_mask = icon('icons/obj/pipes_n_cables/pipe_template_pieces.dmi', "blank_mask") + for(var/i in 0 to 3) + var/dir = 1 << i + if(!(combined_dirs & dir)) + continue + + var/icon/cap_mask = cap_masks["[dir]"] + capped_mask.Blend(cap_mask, ICON_OVERLAY, x_offset, y_offset) + + var/icon/capped = icon(working) + capped.Blend(capped_mask, ICON_MULTIPLY) + + var/icon_state_dirs = (dirs & ~combined_dirs) | CARDINAL_TO_PIPECAPS(combined_dirs) + outputs[capped] = "[icon_state_dirs]_[layer]" + + return outputs /datum/pipe_icon_generator/proc/GeneratePipeStraight(icon_state_suffix, layer, combined_dirs) var/list/output = list() @@ -97,8 +132,10 @@ switch(combined_dirs) if(NORTH | SOUTH) output += GenerateDamaged(working, layer, combined_dirs, y_offset=offset) + output += generate_capped(working, layer, combined_dirs, y_offset=offset) if(EAST | WEST) output += GenerateDamaged(working, layer, combined_dirs, x_offset=offset) + output += generate_capped(working, layer, combined_dirs, x_offset=offset) return output @@ -117,6 +154,7 @@ output[working] = "[combined_dirs]_[layer]" output += GenerateDamaged(working, layer, combined_dirs) + output += generate_capped(working, layer, combined_dirs) return output @@ -135,6 +173,7 @@ output[working] = "[combined_dirs]_[layer]" output += GenerateDamaged(working, layer, combined_dirs) + output += generate_capped(working, layer, combined_dirs) return output @@ -144,5 +183,6 @@ output[working] = "[combined_dirs]_[layer]" output += GenerateDamaged(working, layer, combined_dirs) + output += generate_capped(working, layer, combined_dirs) return output diff --git a/code/modules/atmospherics/machinery/pipes/smart.dm b/code/modules/atmospherics/machinery/pipes/smart.dm index 365d48e41213e49..ee2efd699cdb034 100644 --- a/code/modules/atmospherics/machinery/pipes/smart.dm +++ b/code/modules/atmospherics/machinery/pipes/smart.dm @@ -10,6 +10,8 @@ GLOBAL_LIST_INIT(atmos_components, typecacheof(list(/obj/machinery/atmospherics) device_type = QUATERNARY construction_type = /obj/item/pipe/quaternary pipe_state = "manifold4w" + has_cap_visuals = TRUE + ///Current active connections var/connections = NONE ///Was this pipe created during map load diff --git a/code/modules/cargo/coupon.dm b/code/modules/cargo/coupon.dm index f654db448872eac..8eefcc8676613e6 100644 --- a/code/modules/cargo/coupon.dm +++ b/code/modules/cargo/coupon.dm @@ -63,7 +63,7 @@ update_name() /// Choose what our prize is :D -/obj/item/coupon/proc/generate(discount, datum/supply_pack/discounted_pack) +/obj/item/coupon/proc/generate(discount, datum/supply_pack/discounted_pack, mob/user) src.discounted_pack = discounted_pack || pick(GLOB.discountable_packs[pick_weight(GLOB.pack_discount_odds)]) var/static/list/chances = list("0.10" = 4, "0.15" = 8, "0.20" = 10, "0.25" = 8, "0.50" = 4, COUPON_OMEN = 1) discount_pct_off = discount || pick_weight(chances) @@ -77,14 +77,14 @@ name = "coupon - fuck you" desc = "The small text reads, 'You will be slaughtered'... That doesn't sound right, does it?" - if(!ismob(loc)) + var/mob/cursed = user || loc + if(!ismob(cursed)) return FALSE - var/mob/cursed = loc to_chat(cursed, span_warning("The coupon reads 'fuck you' in large, bold text... is- is that a prize, or?")) if(!cursed.GetComponent(/datum/component/omen)) - cursed.AddComponent(/datum/component/omen) + cursed.AddComponent(/datum/component/omen, src, 1) return TRUE if(HAS_TRAIT(cursed, TRAIT_CURSED)) to_chat(cursed, span_warning("What a horrible night... To have a curse!")) @@ -98,6 +98,7 @@ /obj/item/coupon/proc/curse_heart(mob/living/cursed) if(!iscarbon(cursed)) cursed.gib(DROP_ALL_REMAINS) + burn_evilly() return TRUE var/mob/living/carbon/player = cursed @@ -105,6 +106,11 @@ to_chat(player, span_mind_control("What could that coupon mean?")) to_chat(player, span_userdanger("...The suspense is killing you!")) player.set_heartattack(status = TRUE) + burn_evilly() + +/obj/item/coupon/proc/burn_evilly() + visible_message(span_warning("[src] burns up in a sinister flash, taking an evil energy with it...")) + burn() /obj/item/coupon/attack_atom(obj/O, mob/living/user, params) if(!istype(O, /obj/machinery/computer/cargo)) diff --git a/code/modules/cargo/exports/parts.dm b/code/modules/cargo/exports/parts.dm index 840d40f18371291..fc8c9656fea78ba 100644 --- a/code/modules/cargo/exports/parts.dm +++ b/code/modules/cargo/exports/parts.dm @@ -33,3 +33,9 @@ unit_name = "data disk" export_types = list(/obj/item/computer_disk) include_subtypes = TRUE + +/datum/export/refill_canister + cost = CARGO_CRATE_VALUE * 0.5 //If someone want to make this worth more as it empties, go ahead + unit_name = "vending refill canister" + message = "Thank you for restocking the station!" + export_types = list(/obj/item/vending_refill) diff --git a/code/modules/cargo/goodies.dm b/code/modules/cargo/goodies.dm index fd30973d24107ad..c39fa59c200605c 100644 --- a/code/modules/cargo/goodies.dm +++ b/code/modules/cargo/goodies.dm @@ -308,3 +308,10 @@ desc = "A less cheap imported climbing hook. Absolutely no use outside of planetary stations." cost = PAYCHECK_CREW * 5 contains = list(/obj/item/climbing_hook) + +/datum/supply_pack/goody/double_barrel + name = "Double Barrel Shotgun" + desc = "Lost your beloved bunny to a demonic invasion? Clown broke in and stole your beloved gun? No worries! Get a new gun so long as you can pay the absurd fees." + cost = PAYCHECK_COMMAND * 18 + access_view = ACCESS_WEAPONS + contains = list(/obj/item/gun/ballistic/shotgun/doublebarrel) diff --git a/code/modules/cargo/markets/market_items/clothing.dm b/code/modules/cargo/markets/market_items/clothing.dm index 8af34e22916575d..bf705e8b5725100 100644 --- a/code/modules/cargo/markets/market_items/clothing.dm +++ b/code/modules/cargo/markets/market_items/clothing.dm @@ -93,5 +93,11 @@ stock_max = 3 availability_prob = 40 - - +/datum/market_item/clothing/collar_bomb + name = "Collar Bomb Kit" + desc = "An unpatented and questionably ethical kit consisting of a low-yield explosive collar and a remote to trigger it." + item = /obj/item/storage/box/collar_bomb + price_min = CARGO_CRATE_VALUE * 3.5 + price_max = CARGO_CRATE_VALUE * 4.5 + stock_max = 3 + availability_prob = 60 diff --git a/code/modules/cargo/markets/market_items/weapons.dm b/code/modules/cargo/markets/market_items/weapons.dm index 052074a30b38d26..11f242d57c87460 100644 --- a/code/modules/cargo/markets/market_items/weapons.dm +++ b/code/modules/cargo/markets/market_items/weapons.dm @@ -66,7 +66,7 @@ /datum/market_item/weapon/fisher name = "SC/FISHER Saboteur Handgun" - desc = "A self-recharging, compact pistol that disrupts flashlights and security cameras, if only temporarily. Also usable in melee." + desc = "A self-recharging, compact pistol that disrupts lights, cameras, APCs, turrets and more, if only temporarily. Also usable in melee." item = /obj/item/gun/energy/recharge/fisher price_min = CARGO_CRATE_VALUE * 2 diff --git a/code/modules/cargo/markets/market_uplink.dm b/code/modules/cargo/markets/market_uplink.dm index 19c1a049a1be061..a82218082e90dfa 100644 --- a/code/modules/cargo/markets/market_uplink.dm +++ b/code/modules/cargo/markets/market_uplink.dm @@ -150,6 +150,7 @@ icon_state = "uplink" //The original black market uplink accessible_markets = list(/datum/market/blackmarket) + custom_premium_price = PAYCHECK_CREW * 2.5 /datum/crafting_recipe/blackmarket_uplink diff --git a/code/modules/cargo/materials_market.dm b/code/modules/cargo/materials_market.dm index 92d83d5d0a14134..947197d16f298a0 100644 --- a/code/modules/cargo/materials_market.dm +++ b/code/modules/cargo/materials_market.dm @@ -166,12 +166,14 @@ var/min_value_override = initial(traded_mat.minimum_value_override) if(min_value_override) minimum_value_threshold = min_value_override - + else + minimum_value_threshold = round(initial(traded_mat.value_per_unit) * SHEET_MATERIAL_AMOUNT * 0.5) //send data material_data += list(list( "name" = initial(traded_mat.name), "price" = SSstock_market.materials_prices[traded_mat], + "rarity" = initial(traded_mat.value_per_unit), "threshold" = minimum_value_threshold, "quantity" = SSstock_market.materials_quantity[traded_mat], "trend" = trend_string, @@ -205,6 +207,7 @@ .["orderBalance"] = current_cost .["orderingPrive"] = ordering_private .["canOrderCargo"] = can_buy_via_budget + .["updateTime"] = SSstock_market.next_fire - world.time /obj/machinery/materials_market/ui_act(action, params, datum/tgui/ui, datum/ui_state/state) . = ..() @@ -348,8 +351,8 @@ /obj/item/stock_block/Initialize(mapload) . = ..() - addtimer(CALLBACK(src, PROC_REF(value_warning)), 2.5 MINUTES, TIMER_DELETE_ME) - addtimer(CALLBACK(src, PROC_REF(update_value)), 5 MINUTES, TIMER_DELETE_ME) + addtimer(CALLBACK(src, PROC_REF(value_warning)), 1.5 MINUTES, TIMER_DELETE_ME) + addtimer(CALLBACK(src, PROC_REF(update_value)), 3 MINUTES, TIMER_DELETE_ME) /obj/item/stock_block/examine(mob/user) . = ..() diff --git a/code/modules/cargo/packs/costumes_toys.dm b/code/modules/cargo/packs/costumes_toys.dm index 51fb4686038f561..e23e6112a4bfc6e 100644 --- a/code/modules/cargo/packs/costumes_toys.dm +++ b/code/modules/cargo/packs/costumes_toys.dm @@ -250,8 +250,9 @@ discountable = SUPPLY_PACK_STD_DISCOUNTABLE /datum/supply_pack/costumes_toys/stickers/fill(obj/structure/closet/crate/crate) - for(var/i in 1 to rand(1,2)) + for(var/i in 1 to rand(1, 2)) new /obj/item/storage/box/stickers(crate) + if(prob(30)) // a pair of googly eyes because funny new /obj/item/storage/box/stickers/googly(crate) diff --git a/code/modules/cargo/packs/organic.dm b/code/modules/cargo/packs/organic.dm index d806ce51d45a9d7..f405fc7de3a8a9a 100644 --- a/code/modules/cargo/packs/organic.dm +++ b/code/modules/cargo/packs/organic.dm @@ -298,7 +298,7 @@ name = "Grilling Starter Kit" desc = "Hey dad I'm Hungry. Hi Hungry I'm THE NEW GRILLING STARTER KIT \ ONLY 5000 BUX GET NOW! Contains a grill and fuel." - cost = CARGO_CRATE_VALUE * 8 + cost = CARGO_CRATE_VALUE * 4 crate_type = /obj/structure/closet/crate contains = list( /obj/item/stack/sheet/mineral/coal/five, diff --git a/code/modules/cargo/packs/science.dm b/code/modules/cargo/packs/science.dm index f0de463c4490f87..7fa9013c686cf69 100644 --- a/code/modules/cargo/packs/science.dm +++ b/code/modules/cargo/packs/science.dm @@ -104,14 +104,16 @@ name = "Robotics Assembly Crate" desc = "The tools you need to replace those finicky humans with a loyal robot army! \ Contains four proximity sensors, two empty first aid kits, two health analyzers, \ - two red hardhats, two mechanical toolboxes, and two cleanbot assemblies!" + two red hardhats, two toolboxes, and two cleanbot assemblies!" cost = CARGO_CRATE_VALUE * 3 access = ACCESS_ROBOTICS access_view = ACCESS_ROBOTICS - contains = list(/obj/item/assembly/prox_sensor = 5, + contains = list(/obj/item/assembly/prox_sensor = 4, /obj/item/healthanalyzer = 2, /obj/item/clothing/head/utility/hardhat/red = 2, - /obj/item/storage/medkit = 2) + /obj/item/storage/medkit = 2, + /obj/item/storage/toolbox = 2, + /obj/item/bot_assembly/cleanbot = 2) crate_name = "robotics assembly crate" crate_type = /obj/structure/closet/crate/secure/science/robo diff --git a/code/modules/cargo/packs/security.dm b/code/modules/cargo/packs/security.dm index 0b0073258298b1c..b8e93f2815c0d85 100644 --- a/code/modules/cargo/packs/security.dm +++ b/code/modules/cargo/packs/security.dm @@ -330,8 +330,8 @@ /datum/supply_pack/security/armory/thermal name = "Thermal Pistol Crate" desc = "Contains a pair of holsters each with two experimental thermal pistols, \ - using nanites as the basis for their ammo." - cost = CARGO_CRATE_VALUE * 7 + using nanites as the basis for their ammo. Can be shaken to reload." + cost = CARGO_CRATE_VALUE * 10 contains = list(/obj/item/storage/belt/holster/energy/thermal = 2) crate_name = "thermal pistol crate" diff --git a/code/modules/cargo/packs/vending_restock.dm b/code/modules/cargo/packs/vending_restock.dm index cfe9961cc3a4362..10ae874d5d6c927 100644 --- a/code/modules/cargo/packs/vending_restock.dm +++ b/code/modules/cargo/packs/vending_restock.dm @@ -4,7 +4,7 @@ /datum/supply_pack/vending/bartending name = "Booze-o-mat and Coffee Supply Crate" desc = "Bring on the booze and coffee vending machine refills." - cost = CARGO_CRATE_VALUE * 4 + cost = CARGO_CRATE_VALUE * 2 contains = list(/obj/item/vending_refill/boozeomat, /obj/item/vending_refill/coffee, ) @@ -14,7 +14,7 @@ name = "Cigarette Supply Crate" desc = "Don't believe the reports - smoke today! Contains a \ cigarette vending machine refill." - cost = CARGO_CRATE_VALUE * 3 + cost = CARGO_CRATE_VALUE * 2 contains = list(/obj/item/vending_refill/cigarette) crate_name = "cigarette supply crate" crate_type = /obj/structure/closet/crate @@ -62,7 +62,7 @@ /datum/supply_pack/vending/imported name = "Imported Vending Machines" desc = "Vending machines famous in other parts of the galaxy." - cost = CARGO_CRATE_VALUE * 8 + cost = CARGO_CRATE_VALUE * 5 contains = list(/obj/item/vending_refill/sustenance, /obj/item/vending_refill/robotics, /obj/item/vending_refill/sovietsoda, @@ -74,7 +74,7 @@ name = "Medical Vending Crate" desc = "Contains one NanoMed Plus refill, one NanoDrug Plus refill, \ and one wall-mounted NanoMed refill." - cost = CARGO_CRATE_VALUE * 5 + cost = CARGO_CRATE_VALUE * 3.5 contains = list(/obj/item/vending_refill/medical, /obj/item/vending_refill/drugs, /obj/item/vending_refill/wallmed, @@ -85,7 +85,7 @@ name = "PTech Supply Crate" desc = "Not enough cartridges after half the crew lost their PDA \ to explosions? This may fix it." - cost = CARGO_CRATE_VALUE * 3 + cost = CARGO_CRATE_VALUE * 2.5 contains = list(/obj/item/vending_refill/cart) crate_name = "\improper PTech supply crate" @@ -103,7 +103,7 @@ name = "Snack Supply Crate" desc = "One vending machine refill of cavity-bringin' goodness! \ The number one dentist recommended order!" - cost = CARGO_CRATE_VALUE * 3 + cost = CARGO_CRATE_VALUE * 2 contains = list(/obj/item/vending_refill/snack) crate_name = "snacks supply crate" @@ -111,14 +111,14 @@ name = "Softdrinks Supply Crate" desc = "Got whacked by a toolbox, but you still have those pesky teeth? \ Get rid of those pearly whites with this soda machine refill, today!" - cost = CARGO_CRATE_VALUE * 3 + cost = CARGO_CRATE_VALUE * 2 contains = list(/obj/item/vending_refill/cola) crate_name = "soft drinks supply crate" /datum/supply_pack/vending/vendomat name = "Part-Mart & YouTool Supply Crate" desc = "More tools for your IED testing facility." - cost = CARGO_CRATE_VALUE * 2 + cost = CARGO_CRATE_VALUE * 3 contains = list(/obj/item/vending_refill/assist, /obj/item/vending_refill/youtool, ) @@ -138,7 +138,7 @@ name = "Autodrobe Supply Crate" desc = "Autodrobe missing your favorite dress? Solve that issue today \ with this autodrobe refill." - cost = CARGO_CRATE_VALUE * 3 + cost = CARGO_CRATE_VALUE * 2 contains = list(/obj/item/vending_refill/autodrobe) crate_name = "autodrobe supply crate" @@ -200,7 +200,7 @@ name = "Science Wardrobe Supply Crate" desc = "This crate contains refills for the SciDrobe, \ GeneDrobe, and RoboDrobe." - cost = CARGO_CRATE_VALUE * 3 + cost = CARGO_CRATE_VALUE * 4.5 contains = list(/obj/item/vending_refill/wardrobe/robo_wardrobe, /obj/item/vending_refill/wardrobe/gene_wardrobe, /obj/item/vending_refill/wardrobe/science_wardrobe, diff --git a/code/modules/cargo/supplypod.dm b/code/modules/cargo/supplypod.dm index 20ea6fec8ba5088..15850f13e590d84 100644 --- a/code/modules/cargo/supplypod.dm +++ b/code/modules/cargo/supplypod.dm @@ -70,6 +70,16 @@ bluespace = TRUE explosionSize = list(0,0,0,0) +/obj/structure/closet/supplypod/podspawn/deathmatch + desc = "A blood-red styled drop pod." + specialised = TRUE + +/obj/structure/closet/supplypod/podspawn/deathmatch/Entered(atom/movable/arrived) + . = ..() + if(isliving(arrived)) + var/mob/living/critter = arrived + critter.faction = list(FACTION_HOSTILE) //No infighting, but also KILL!! + /obj/structure/closet/supplypod/extractionpod name = "Syndicate Extraction Pod" desc = "A specalised, blood-red styled pod for extracting high-value targets out of active mission areas. Targets must be manually stuffed inside the pod for proper delivery." @@ -90,6 +100,28 @@ delays = list(POD_TRANSIT = 20, POD_FALLING = 4, POD_OPENING = 30, POD_LEAVING = 30) resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF +/obj/structure/closet/supplypod/back_to_station + name = "blood-red supply pod" + desc = "An intimidating supply pod, covered in the blood-red markings" + bluespace = TRUE + explosionSize = list(0,0,0,0) + style = STYLE_SYNDICATE + specialised = TRUE + +/obj/structure/closet/supplypod/deadmatch_missile + name = "cruise missile" + desc = "A big ass missile, likely launched from some far-off deep space missile silo." + decal = null + door = null + fin_mask = null + explosionSize = list(0,1,2,2) + effectShrapnel = TRUE + rubble_type = RUBBLE_THIN + specialised = TRUE + delays = list(POD_TRANSIT = 2.6 SECONDS, POD_FALLING = 0.4 SECONDS) + effectMissile = TRUE + shrapnel_type = /obj/projectile/bullet/shrapnel/short_range + /datum/armor/closet_supplypod melee = 30 bullet = 50 diff --git a/code/modules/client/client_procs.dm b/code/modules/client/client_procs.dm index a197c5d3cdf9e39..29eec0802a80dbd 100644 --- a/code/modules/client/client_procs.dm +++ b/code/modules/client/client_procs.dm @@ -1196,8 +1196,8 @@ GLOBAL_LIST_INIT(blacklisted_builds, list( if(!CONFIG_GET(flag/use_age_restriction_for_jobs)) return 0 - if(!isnum(player_age)) - return 0 //This is only a number if the db connection is established, otherwise it is text: "Requires database", meaning these restrictions cannot be enforced + if(!isnum(player_age) || player_age < 0) + return 0 if(!isnum(days_needed)) return 0 diff --git a/code/modules/client/verbs/ooc.dm b/code/modules/client/verbs/ooc.dm index 5df802b9f608936..dc55b72b09d39de 100644 --- a/code/modules/client/verbs/ooc.dm +++ b/code/modules/client/verbs/ooc.dm @@ -10,12 +10,15 @@ GLOBAL_VAR_INIT(normal_ooc_colour, "#002eb8") to_chat(usr, span_danger("Speech is currently admin-disabled.")) return - if(!mob) - return + var/client_initalized = VALIDATE_CLIENT_INITIALIZATION(src) + if(isnull(mob) || !client_initalized) + if(!client_initalized) + unvalidated_client_error() // we only want to throw this warning message when it's directly related to client failure. - VALIDATE_CLIENT(src) + to_chat(usr, span_warning("Failed to send your OOC message. You attempted to send the following message:\n[span_big(msg)]")) + return - if(!holder) + if(isnull(holder)) if(!GLOB.ooc_allowed) to_chat(src, span_danger("OOC is globally muted.")) return diff --git a/code/modules/clothing/belts/polymorph_belt.dm b/code/modules/clothing/belts/polymorph_belt.dm index 73959d6d415195e..fb09b2e68c8f119 100644 --- a/code/modules/clothing/belts/polymorph_belt.dm +++ b/code/modules/clothing/belts/polymorph_belt.dm @@ -63,10 +63,9 @@ if (target_mob.mob_biotypes & (MOB_HUMANOID|MOB_ROBOTIC|MOB_SPECIAL|MOB_SPIRIT|MOB_UNDEAD)) balloon_alert(user, "incompatible!") return TRUE - if (isanimal_or_basicmob(target_mob)) - if (!target_mob.compare_sentience_type(SENTIENCE_ORGANIC)) - balloon_alert(user, "target too intelligent!") - return TRUE + if (!target_mob.compare_sentience_type(SENTIENCE_ORGANIC)) + balloon_alert(user, "target too intelligent!") + return TRUE if (stored_mob_type == target_mob.type) balloon_alert(user, "already scanned!") return TRUE diff --git a/code/modules/clothing/head/cakehat.dm b/code/modules/clothing/head/cakehat.dm index 57369ac24f89ccc..1fc0fa0b05b5009 100644 --- a/code/modules/clothing/head/cakehat.dm +++ b/code/modules/clothing/head/cakehat.dm @@ -9,8 +9,10 @@ lefthand_file = 'icons/mob/inhands/clothing/hats_lefthand.dmi' righthand_file = 'icons/mob/inhands/clothing/hats_righthand.dmi' armor_type = /datum/armor/none - light_range = 2 //luminosity when on light_system = OVERLAY_LIGHT + light_range = 2 //luminosity when on + light_power = 1.3 + light_color = "#FF964E" flags_cover = HEADCOVERSEYES heat = 999 wound_bonus = 10 diff --git a/code/modules/clothing/head/hardhat.dm b/code/modules/clothing/head/hardhat.dm index 3550690b42626ca..c5b25166c09e0b6 100644 --- a/code/modules/clothing/head/hardhat.dm +++ b/code/modules/clothing/head/hardhat.dm @@ -16,6 +16,7 @@ light_system = OVERLAY_LIGHT_DIRECTIONAL light_range = 4 light_power = 0.8 + light_color = "#ffcc99" light_on = FALSE dog_fashion = /datum/dog_fashion/head @@ -39,9 +40,7 @@ /obj/item/clothing/head/utility/hardhat/Initialize(mapload) . = ..() AddElement(/datum/element/update_icon_updates_onmob) - -/obj/item/clothing/head/utility/hardhat/attack_self(mob/living/user) - toggle_helmet_light(user) + RegisterSignal(src, COMSIG_HIT_BY_SABOTEUR, PROC_REF(on_saboteur)) /obj/item/clothing/head/utility/hardhat/proc/toggle_helmet_light(mob/living/user) on = !on @@ -61,6 +60,15 @@ /obj/item/clothing/head/utility/hardhat/proc/turn_off(mob/user) set_light_on(FALSE) +/obj/item/clothing/head/utility/hardhat/proc/on_saboteur(datum/source, disrupt_duration) + SIGNAL_HANDLER + if(on) + toggle_helmet_light() + return COMSIG_SABOTEUR_SUCCESS + +/obj/item/clothing/head/utility/hardhat/attack_self(mob/living/user) + toggle_helmet_light(user) + /obj/item/clothing/head/utility/hardhat/orange icon_state = "hardhat0_orange" inhand_icon_state = null diff --git a/code/modules/clothing/head/soft_caps.dm b/code/modules/clothing/head/soft_caps.dm index e8338f4c95b19fc..0b0a6fb4d50cb31 100644 --- a/code/modules/clothing/head/soft_caps.dm +++ b/code/modules/clothing/head/soft_caps.dm @@ -135,6 +135,15 @@ strip_delay = 60 dog_fashion = null +/obj/item/clothing/head/soft/veteran + name = "veteran cap" + desc = "It's a robust baseball hat in tasteful black colour with a golden connotation to \"REMEMBER\"." + icon_state = "veteransoft" + soft_type = "veteran" + armor_type = /datum/armor/cosmetic_sec + strip_delay = 60 + dog_fashion = null + /obj/item/clothing/head/soft/paramedic name = "paramedic cap" desc = "It's a baseball hat with a dark turquoise color and a reflective cross on the top." diff --git a/code/modules/clothing/neck/collar_bomb.dm b/code/modules/clothing/neck/collar_bomb.dm new file mode 100644 index 000000000000000..72f5b20320db361 --- /dev/null +++ b/code/modules/clothing/neck/collar_bomb.dm @@ -0,0 +1,118 @@ +///Special neckwear that kills its wearer if triggered, by either its specific remote or assemblies. +/obj/item/clothing/neck/collar_bomb + name = "collar bomb" + desc = "A cumbersome collar of some sort, filled with just enough explosive to rip one's head off... at least that's what it reads on the front tag." + icon_state = "collar_bomb" + icon = 'icons/obj/clothing/neck.dmi' + inhand_icon_state = "reverse_bear_trap" + lefthand_file = 'icons/mob/inhands/items_lefthand.dmi' + righthand_file = 'icons/mob/inhands/items_righthand.dmi' + clothing_flags = INEDIBLE_CLOTHING + armor_type = /datum/armor/collar_bomb + equip_delay_self = 6 SECONDS + equip_delay_other = 8 SECONDS + ///The button it's associated with + var/obj/item/collar_bomb_button/button + ///Whether the collar countdown has been triggered. + var/active = FALSE + +/datum/armor/collar_bomb + fire = 97 + bomb = 97 + acid = 97 + +/obj/item/clothing/neck/collar_bomb/Initialize(mapload, obj/item/collar_bomb_button/button) + . = ..() + src.button = button + button?.collar = src + set_wires(new /datum/wires/collar_bomb(src)) + +/obj/item/clothing/neck/collar_bomb/Destroy() + button?.collar = null + button = null + return ..() + +/obj/item/clothing/neck/collar_bomb/examine(mob/user) + . = ..() + if(user.get_item_by_slot(ITEM_SLOT_NECK) == src) + return + . += span_tinynotice("It has a [EXAMINE_HINT("wire")] panel that could be interacted with...") + +/obj/item/clothing/neck/collar_bomb/attackby(obj/item/item, mob/user, params) + if(is_wire_tool(item)) + wires.interact(user) + else + return ..() + +/obj/item/clothing/neck/collar_bomb/equipped(mob/user, slot, initial = FALSE) + . = ..() + if(slot == ITEM_SLOT_NECK) + ADD_TRAIT(src, TRAIT_NODROP, INNATE_TRAIT) + +/obj/item/clothing/neck/collar_bomb/dropped(mob/user, silent = FALSE) + . = ..() + REMOVE_TRAIT(src, TRAIT_NODROP, INNATE_TRAIT) + +/obj/item/clothing/neck/collar_bomb/proc/explosive_countdown(ticks_left) + active = TRUE + if(ticks_left > 0) + playsound(src, 'sound/items/timer.ogg', 30, FALSE) + balloon_alert_to_viewers("[ticks_left]") + ticks_left-- + addtimer(CALLBACK(src, PROC_REF(explosive_countdown), ticks_left), 1 SECONDS) + return + + playsound(src, 'sound/effects/snap.ogg', 75, TRUE) + if(!ishuman(loc)) + balloon_alert_to_viewers("dud...") + active = FALSE + return + var/mob/living/carbon/human/brian = loc + if(brian.get_item_by_slot(ITEM_SLOT_NECK) != src) + balloon_alert_to_viewers("dud...") + active = FALSE + return + visible_message(span_warning("[src] goes off, outright decapitating [brian]!"), span_hear("You hear a fleshy boom!")) + playsound(src, SFX_EXPLOSION, 30, TRUE) + brian.apply_damage(200, BRUTE, BODY_ZONE_HEAD) + var/obj/item/bodypart/head/myhead = brian.get_bodypart(BODY_ZONE_HEAD) + myhead?.dismember() + brian.investigate_log("has been decapitated by [src].", INVESTIGATE_DEATHS) + flash_color(brian, flash_color = "#FF0000", flash_time = 1 SECONDS) + qdel(src) + +///The button that detonates the collar. +/obj/item/collar_bomb_button + name = "big yellow button" + desc = "It looks like a big red button, except it's yellow. It comes with a heavy trigger, to avoid accidents." + icon = 'icons/obj/devices/assemblies.dmi' + icon_state = "bigyellow" + inhand_icon_state = "electronic" + lefthand_file = 'icons/mob/inhands/items/devices_lefthand.dmi' + righthand_file = 'icons/mob/inhands/items/devices_righthand.dmi' + w_class = WEIGHT_CLASS_TINY + ///The collar bomb it's associated with. + var/obj/item/clothing/neck/collar_bomb/collar + +/obj/item/collar_bomb_button/attack_self(mob/user) + . = ..() + if(DOING_INTERACTION_WITH_TARGET(user, src)) + return + balloon_alert_to_viewers("pushing the button...") + if(!do_after(user, 1.2 SECONDS, target = src)) + return + playsound(user, 'sound/machines/click.ogg', 25, TRUE) + if(!collar|| collar.active) + return + collar.explosive_countdown(ticks_left = 5) + if(!ishuman(collar.loc)) + return + var/mob/living/carbon/human/brian = collar.loc + if(brian.get_item_by_slot(ITEM_SLOT_NECK) == collar) + brian.investigate_log("has has their [collar] triggered by [user] via yellow button.", INVESTIGATE_DEATHS) + + +/obj/item/collar_bomb_button/Destroy() + collar?.button = null + collar = null + return ..() diff --git a/code/modules/clothing/shoes/clown.dm b/code/modules/clothing/shoes/clown.dm index 549d2a40f152e82..2f4b973f9a9f9e9 100644 --- a/code/modules/clothing/shoes/clown.dm +++ b/code/modules/clothing/shoes/clown.dm @@ -58,4 +58,4 @@ name = "moffers" desc = "No moths were harmed in the making of these slippers." icon_state = "moffers" - squeak_sound = list('sound/voice/moth/scream_moth.ogg'=1) //like sweet music to my ears + squeak_sound = list('sound/effects/footstep/moffstep01.ogg'=1) //like sweet music to my ears diff --git a/code/modules/clothing/spacesuits/plasmamen.dm b/code/modules/clothing/spacesuits/plasmamen.dm index 90141d281dd3162..860ac12d2020996 100644 --- a/code/modules/clothing/spacesuits/plasmamen.dm +++ b/code/modules/clothing/spacesuits/plasmamen.dm @@ -54,6 +54,8 @@ resistance_flags = FIRE_PROOF light_system = OVERLAY_LIGHT_DIRECTIONAL light_range = 4 + light_power = 0.8 + light_color = "#ffcc99" light_on = FALSE var/helmet_on = FALSE var/smile = FALSE @@ -76,6 +78,7 @@ . = ..() visor_toggling() update_appearance() + RegisterSignal(src, COMSIG_HIT_BY_SABOTEUR, PROC_REF(on_saboteur)) /obj/item/clothing/head/helmet/space/plasmaman/examine() . = ..() @@ -106,6 +109,11 @@ playsound(src, 'sound/mecha/mechmove03.ogg', 50, TRUE) //Visors don't just come from nothing update_appearance() +/obj/item/clothing/head/helmet/space/plasmaman/update_icon_state() + . = ..() + icon_state = "[initial(icon_state)][helmet_on ? "-light":""]" + inhand_icon_state = icon_state + /obj/item/clothing/head/helmet/space/plasmaman/update_overlays() . = ..() . += visor_icon @@ -137,6 +145,7 @@ hitting_clothing.forceMove(src) update_appearance() +///By the by, helmets have the update_icon_updates_onmob element, so we don't have to call mob.update_worn_head() /obj/item/clothing/head/helmet/space/plasmaman/worn_overlays(mutable_appearance/standing, isinhands) . = ..() if(!isinhands && smile) @@ -159,9 +168,7 @@ /obj/item/clothing/head/helmet/space/plasmaman/attack_self(mob/user) helmet_on = !helmet_on - icon_state = "[initial(icon_state)][helmet_on ? "-light":""]" - inhand_icon_state = icon_state - user.update_worn_head() //So the mob overlay updates + update_appearance() if(helmet_on) if(!up) @@ -174,6 +181,14 @@ update_item_action_buttons() +/obj/item/clothing/head/helmet/space/plasmaman/proc/on_saboteur(datum/source, disrupt_duration) + SIGNAL_HANDLER + if(!helmet_on) + return + helmet_on = FALSE + update_appearance() + return COMSIG_SABOTEUR_SUCCESS + /obj/item/clothing/head/helmet/space/plasmaman/attack_hand_secondary(mob/user) ..() . = SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN diff --git a/code/modules/clothing/suits/costume.dm b/code/modules/clothing/suits/costume.dm index 8c1815f3a01a338..e4fb756e2980a15 100644 --- a/code/modules/clothing/suits/costume.dm +++ b/code/modules/clothing/suits/costume.dm @@ -360,6 +360,48 @@ clothing_flags = THICKMATERIAL flags_inv = HIDEHAIR|HIDEEARS +/obj/item/clothing/suit/hooded/shark_costume // Blahaj + name = "Shark costume" + desc = "Finally, a costume to match your favorite plush." + icon_state = "shark" + icon = 'icons/obj/clothing/suits/costume.dmi' + worn_icon = 'icons/mob/clothing/suits/costume.dmi' + inhand_icon_state = "shark" + body_parts_covered = CHEST|GROIN|ARMS + clothing_flags = THICKMATERIAL + hoodtype = /obj/item/clothing/head/hooded/shark_hood + +/obj/item/clothing/head/hooded/shark_hood + name = "shark hood" + desc = "A hood attached to a shark costume." + icon = 'icons/obj/clothing/head/costume.dmi' + worn_icon = 'icons/mob/clothing/head/costume.dmi' + icon_state = "shark" + body_parts_covered = HEAD + clothing_flags = THICKMATERIAL + flags_inv = HIDEHAIR|HIDEEARS + +/obj/item/clothing/suit/hooded/shork_costume // Oh God Why + name = "shork costume" + desc = "Why would you ever do this?" + icon_state = "sharkcursed" + icon = 'icons/obj/clothing/suits/costume.dmi' + worn_icon = 'icons/mob/clothing/suits/costume.dmi' + inhand_icon_state = "sharkcursed" + body_parts_covered = CHEST|GROIN|ARMS + clothing_flags = THICKMATERIAL + hoodtype = /obj/item/clothing/head/hooded/shork_hood + +/obj/item/clothing/head/hooded/shork_hood + name = "shork hood" + desc = "A hood attached to a shork costume." + icon = 'icons/obj/clothing/head/costume.dmi' + worn_icon = 'icons/mob/clothing/head/costume.dmi' + icon_state = "sharkcursed" + body_parts_covered = HEAD + clothing_flags = THICKMATERIAL + flags_inv = HIDEHAIR|HIDEEARS + /obj/item/clothing/suit/hooded/bloated_human //OH MY GOD WHAT HAVE YOU DONE!?!?!? name = "bloated human suit" desc = "A horribly bloated suit made from human skins." diff --git a/code/modules/clothing/suits/wintercoats.dm b/code/modules/clothing/suits/wintercoats.dm index 283878339fe3232..aaa233f0d35ff89 100644 --- a/code/modules/clothing/suits/wintercoats.dm +++ b/code/modules/clothing/suits/wintercoats.dm @@ -521,6 +521,9 @@ /obj/item/pipe_dispenser, /obj/item/storage/bag/construction, /obj/item/t_scanner, + /obj/item/construction/rld, + /obj/item/construction/rtd, + /obj/item/gun/ballistic/rifle/rebarxbow ) armor_type = /datum/armor/wintercoat_engineering hoodtype = /obj/item/clothing/head/hooded/winterhood/engineering diff --git a/code/modules/deathmatch/deathmatch_controller.dm b/code/modules/deathmatch/deathmatch_controller.dm index c288daefd4e1ce2..45b5f087c5bb5a2 100644 --- a/code/modules/deathmatch/deathmatch_controller.dm +++ b/code/modules/deathmatch/deathmatch_controller.dm @@ -5,6 +5,8 @@ var/list/datum/lazy_template/deathmatch/maps = list() /// All loadouts var/list/datum/outfit/loadouts + /// All modifiers + var/list/datum/deathmatch_modifier/modifiers /datum/deathmatch_controller/New() . = ..() @@ -17,6 +19,7 @@ var/map_name = initial(template.name) maps[map_name] = new template loadouts = subtypesof(/datum/outfit/deathmatch_loadout) + modifiers = sortTim(init_subtypes_w_path_keys(/datum/deathmatch_modifier), GLOBAL_PROC_REF(cmp_deathmatch_mods), associative = TRUE) /datum/deathmatch_controller/proc/create_new_lobby(mob/host) lobbies[host.ckey] = new /datum/deathmatch_lobby(host) @@ -87,7 +90,7 @@ var/datum/deathmatch_lobby/chosen_lobby = lobbies[params["id"]] if (!isnull(playing_lobby) && playing_lobby != chosen_lobby) playing_lobby.leave(usr.ckey) - + if(isnull(playing_lobby)) log_game("[usr.ckey] joined deathmatch lobby [params["id"]] as a player.") chosen_lobby.join(usr) diff --git a/code/modules/deathmatch/deathmatch_loadouts.dm b/code/modules/deathmatch/deathmatch_loadouts.dm index f994987427e86dd..341b85fb926806e 100644 --- a/code/modules/deathmatch/deathmatch_loadouts.dm +++ b/code/modules/deathmatch/deathmatch_loadouts.dm @@ -17,7 +17,7 @@ if(!isnull(species_override)) user.set_species(species_override) - else if (istype(user.dna.species.outfit_important_for_life)) //plasmamen get lit on fire and die + else if (!isnull(user.dna.species.outfit_important_for_life)) //plasmamen get lit on fire and die user.set_species(/datum/species/human) for(var/datum/action/act as anything in granted_spells) var/datum/action/new_ability = new act(user) diff --git a/code/modules/deathmatch/deathmatch_lobby.dm b/code/modules/deathmatch/deathmatch_lobby.dm index e498f662b5e397e..fb8077b491698d6 100644 --- a/code/modules/deathmatch/deathmatch_lobby.dm +++ b/code/modules/deathmatch/deathmatch_lobby.dm @@ -12,13 +12,15 @@ /// Whether players hear deadchat and people through walls var/global_chat = FALSE /// Whether the lobby is currently playing - var/playing = FALSE + var/playing = DEATHMATCH_NOT_PLAYING /// Number of total ready players var/ready_count /// List of loadouts, either gotten from the deathmatch controller or the map var/list/loadouts /// Current map player spawn locations, cleared after spawning var/list/player_spawns = list() + /// A list of paths of modifiers enabled for the match. + var/list/modifiers = list() /datum/deathmatch_lobby/New(mob/player) . = ..() @@ -48,11 +50,12 @@ map = null location = null loadouts = null + modifiers = null /datum/deathmatch_lobby/proc/start_game() if (playing) return - playing = TRUE + playing = DEATHMATCH_PRE_PLAYING RegisterSignal(map, COMSIG_LAZY_TEMPLATE_LOADED, PROC_REF(find_spawns_and_start_delay)) location = map.lazy_load() @@ -78,6 +81,9 @@ playing = FALSE return FALSE + for(var/modpath in modifiers) + GLOB.deathmatch_game.modifiers[modpath].on_start_game(src) + for (var/key in players) var/mob/dead/observer/observer = players[key]["mob"] if (isnull(observer) || !observer.client) @@ -97,19 +103,26 @@ var/mob/observer = observers[observer_key]["mob"] observer.forceMove(pick(location.reserved_turfs)) + playing = DEATHMATCH_PLAYING addtimer(CALLBACK(src, PROC_REF(game_took_too_long)), initial(map.automatic_gameend_time)) log_game("Deathmatch game [host] started.") announce(span_reallybig("GO!")) + if(length(modifiers)) + var/list/modifier_names = list() + for(var/datum/deathmatch_modifier/modifier in modifiers) + modifier_names += uppertext(initial(modifier.name)) + announce(span_boldnicegreen("THIS MATCH MODIFIERS: [english_list(modifier_names, and_text = " ,")].")) return TRUE /datum/deathmatch_lobby/proc/spawn_observer_as_player(ckey, loc) - var/mob/dead/observer/observer = players[ckey]["mob"] + var/list/players_info = players[ckey] + var/mob/dead/observer/observer = players_info["mob"] if (isnull(observer) || !observer.client) remove_ckey_from_play(ckey) return // equip player - var/datum/outfit/deathmatch_loadout/loadout = players[ckey]["loadout"] + var/datum/outfit/deathmatch_loadout/loadout = players_info["loadout"] if (!(loadout in loadouts)) loadout = loadouts[1] @@ -126,7 +139,10 @@ ) new_player.equipOutfit(loadout) // Loadout new_player.key = ckey - players[ckey]["mob"] = new_player + players_info["mob"] = new_player + + for(var/datum/deathmatch_modifier/modifier as anything in modifiers) + GLOB.deathmatch_game.modifiers[modifier].apply(new_player, src) // register death handling. RegisterSignals(new_player, list(COMSIG_LIVING_DEATH, COMSIG_MOB_GHOSTIZED, COMSIG_QDELETING), PROC_REF(player_died)) @@ -158,6 +174,9 @@ loser.ghostize() qdel(loser) + for(var/datum/deathmatch_modifier/modifier in modifiers) + GLOB.deathmatch_game.modifiers[modifier].on_end_game(src) + clear_reservation() GLOB.deathmatch_game.remove_lobby(host) log_game("Deathmatch game [host] ended.") @@ -187,7 +206,8 @@ announce(span_reallybig("[player.real_name] HAS DIED.
[players.len] REMAIN.")) if(!gibbed && !QDELING(player)) // for some reason dusting or deleting in chasm storage messes up tgui bad - player.dust(TRUE, TRUE, TRUE) + if(!HAS_TRAIT(src, TRAIT_DEATHMATCH_EXPLOSIVE_IMPLANTS)) + player.dust(TRUE, TRUE, TRUE) if (players.len <= 1) end_game() @@ -277,6 +297,9 @@ continue players[player_key]["loadout"] = loadouts[1] + for(var/deathmatch_mod in modifiers) + GLOB.deathmatch_game.modifiers[deathmatch_mod].on_map_changed(src) + /datum/deathmatch_lobby/proc/clear_reservation() if(isnull(location) || isnull(map)) return @@ -312,11 +335,15 @@ for (var/map_key in GLOB.deathmatch_game.maps) .["maps"] += map_key + /datum/deathmatch_lobby/ui_data(mob/user) . = list() + var/is_player = !isnull(players[user.ckey]) + var/is_host = (user.ckey == host) + var/is_admin = check_rights_for(user.client, R_ADMIN) .["self"] = user.ckey - .["host"] = (user.ckey == host) - .["admin"] = check_rights_for(user.client, R_ADMIN) + .["host"] = is_host + .["admin"] = is_admin .["global_chat"] = global_chat .["playing"] = playing .["loadouts"] = list("Randomize") @@ -328,7 +355,27 @@ .["map"]["time"] = map.automatic_gameend_time .["map"]["min_players"] = map.min_players .["map"]["max_players"] = map.max_players - if(!isnull(players[user.ckey]) && !isnull(players[user.ckey]["loadout"])) + + .["mod_menu_open"] = FALSE + if((is_host || is_admin) && players[user.ckey]["mod_menu_open"]) + .["mod_menu_open"] = TRUE + for(var/modpath in GLOB.deathmatch_game.modifiers) + var/datum/deathmatch_modifier/mod = GLOB.deathmatch_game.modifiers[modpath] + .["modifiers"] += list(list( + "name" = mod.name, + "desc" = mod.description, + "modpath" = "[modpath]", + "selected" = (modpath in modifiers), + "selectable" = is_host && mod.selectable(src), + )) + .["active_mods"] = "No modifiers selected" + if(length(modifiers)) + var/list/mod_names = list() + for(var/datum/deathmatch_modifier/modpath as anything in modifiers) + mod_names += initial(modpath.name) + .["active_mods"] = "Selected modifiers: [english_list(mod_names)]" + + if(is_player && !isnull(players[user.ckey]["loadout"])) var/datum/outfit/deathmatch_loadout/loadout = players[user.ckey]["loadout"] .["loadoutdesc"] = initial(loadout.desc) else @@ -437,6 +484,31 @@ if ("global_chat") global_chat = !global_chat return TRUE + if("open_mod_menu") + players[usr.ckey]["mod_menu_open"] = TRUE + return TRUE + if("exit_mod_menu") + players[usr.ckey] -= "mod_menu_open" + return TRUE + if("toggle_modifier") + var/datum/deathmatch_modifier/modpath = text2path(params["modpath"]) + if(!ispath(modpath)) + return TRUE + var/global_mod = params["global_mod"] + if(global_mod) + if(usr.ckey != host && !check_rights(R_ADMIN)) + return TRUE + else if(!(usr.ckey in players)) + return TRUE + var/datum/deathmatch_modifier/chosen_modifier = GLOB.deathmatch_game.modifiers[modpath] + if(modpath in modifiers) + chosen_modifier.unselect(src) + modifiers -= modpath + return TRUE + else if(chosen_modifier.selectable(src)) + chosen_modifier.on_select(src) + modifiers += modpath + return TRUE if ("admin") // Admin functions if (!check_rights(R_ADMIN)) message_admins("[usr.key] has attempted to use admin functions in a deathmatch lobby!") @@ -447,4 +519,7 @@ log_admin("[key_name(usr)] force started deathmatch lobby [host].") start_game() - +/datum/deathmatch_lobby/ui_close(mob/user) + . = ..() + if(players[user.ckey]) + players[user.ckey] -= "mod_menu_open" diff --git a/code/modules/deathmatch/deathmatch_modifier.dm b/code/modules/deathmatch/deathmatch_modifier.dm new file mode 100644 index 000000000000000..e654db3d392c9f5 --- /dev/null +++ b/code/modules/deathmatch/deathmatch_modifier.dm @@ -0,0 +1,478 @@ +///Deathmatch modifiers are little options the host can choose to spice the match a bit. +/datum/deathmatch_modifier + ///The name of the modifier + var/name = "Unnamed Modifier" + ///A small description/tooltip shown in the UI + var/description = "What the heck does this do?" + ///The color of the button shown in the UI + var/color = "blue" + ///A list of modifiers this is incompatible with. + var/list/blacklisted_modifiers + ///Is this trait exempted from the "Random Modifiers" modifier. + var/random_exempted = FALSE + +///Whether or not this modifier can be selected, for both host and player-selected modifiers. +/datum/deathmatch_modifier/proc/selectable(datum/deathmatch_lobby/lobby) + SHOULD_CALL_PARENT(TRUE) + if(!random_exempted && (/datum/deathmatch_modifier/random in lobby.modifiers)) + return FALSE + if(length(lobby.modifiers & blacklisted_modifiers)) + return FALSE + for(var/modpath in lobby.modifiers) + if(src in GLOB.deathmatch_game.modifiers[modpath].blacklisted_modifiers) + return FALSE + return TRUE + +///Called when selecting the deathmatch modifier. +/datum/deathmatch_modifier/proc/on_select(datum/deathmatch_lobby/lobby) + return + +///When the host changes his mind and unselects it. +/datum/deathmatch_modifier/proc/unselect(datum/deathmatch_lobby/lobby) + return + +///Called when the host chooses to change map. +/datum/deathmatch_modifier/proc/on_map_changed(datum/deathmatch_lobby/lobby) + return + +///Called as the game is about to start. +/datum/deathmatch_modifier/proc/on_start_game(datum/deathmatch_lobby/lobby) + return + +///Called as the game has ended, right before the reservation is deleted. +/datum/deathmatch_modifier/proc/on_end_game(datum/deathmatch_lobby/lobby) + return + +///Apply the modifier to the newly spawned player as the game is about to start +/datum/deathmatch_modifier/proc/apply(mob/living/carbon/player, datum/deathmatch_lobby/lobby) + return + +/datum/deathmatch_modifier/health + name = "Double-Health" + description = "Doubles your starting health" + blacklisted_modifiers = list(/datum/deathmatch_modifier/health/triple) + var/multiplier = 2 + +/datum/deathmatch_modifier/health/apply(mob/living/carbon/player, datum/deathmatch_lobby/lobby) + player.maxHealth *= multiplier + player.health *= multiplier + +/datum/deathmatch_modifier/health/triple + name = "Triple-Health" + description = "When \"Double-Health\" isn't enough..." + multiplier = 3 + blacklisted_modifiers = list(/datum/deathmatch_modifier/health) + +/datum/deathmatch_modifier/tenacity + name = "Tenacity" + description = "Unaffected by critical condition and pain" + +/datum/deathmatch_modifier/tenacity/apply(mob/living/carbon/player, datum/deathmatch_lobby/lobby) + player.add_traits(list(TRAIT_NOSOFTCRIT, TRAIT_NOHARDCRIT, TRAIT_ANALGESIA), DEATHMATCH_TRAIT) + +/datum/deathmatch_modifier/no_wounds + name = "No Wounds" + description = "Ah, the good ol' days when people did't have literal dents in their skulls..." + +/datum/deathmatch_modifier/no_wounds/apply(mob/living/carbon/player, datum/deathmatch_lobby/lobby) + ADD_TRAIT(player, TRAIT_NEVER_WOUNDED, DEATHMATCH_TRAIT) + +/datum/deathmatch_modifier/no_knockdown + name = "No Knockdowns" + description = "I'M FUCKING INVINCIBLE!" + +/datum/deathmatch_modifier/no_knockdown/apply(mob/living/carbon/player, datum/deathmatch_lobby/lobby) + player.add_traits(list(TRAIT_STUNIMMUNE, TRAIT_SLEEPIMMUNE), DEATHMATCH_TRAIT) + +/datum/deathmatch_modifier/xray + name = "X-Ray Vision" + description = "See through the cordons of the deathmatch arena!" + blacklisted_modifiers = list(/datum/deathmatch_modifier/thermal, /datum/deathmatch_modifier/echolocation) + +/datum/deathmatch_modifier/xray/apply(mob/living/carbon/player, datum/deathmatch_lobby/lobby) + ADD_TRAIT(player, TRAIT_XRAY_VISION, DEATHMATCH_TRAIT) + player.update_sight() + +/datum/deathmatch_modifier/thermal + name = "Thermal Vision" + description = "See mobs through walls" + blacklisted_modifiers = list(/datum/deathmatch_modifier/xray, /datum/deathmatch_modifier/echolocation) + +/datum/deathmatch_modifier/thermal/apply(mob/living/carbon/player, datum/deathmatch_lobby/lobby) + ADD_TRAIT(player, TRAIT_THERMAL_VISION, DEATHMATCH_TRAIT) + player.update_sight() + +/datum/deathmatch_modifier/regen + name = "Health Regen" + description = "The closest thing to free health insurance you can get" + +/datum/deathmatch_modifier/regen/apply(mob/living/carbon/player, datum/deathmatch_lobby/lobby) + player.AddComponent(/datum/component/regenerator, regeneration_delay = 4 SECONDS, brute_per_second = 2.5, burn_per_second = 2.5, tox_per_second = 2.5) + +/datum/deathmatch_modifier/nearsightness + name = "Nearsightness" + description = "Oops, I forgot my glasses at home" + blacklisted_modifiers = list(/datum/deathmatch_modifier/echolocation) + +/datum/deathmatch_modifier/nearsightness/apply(mob/living/carbon/player, datum/deathmatch_lobby/lobby) + player.become_nearsighted(DEATHMATCH_TRAIT) + +/datum/deathmatch_modifier/echolocation + name = "Echolocation" + description = "On one hand, you're blind, but on the other..." + blacklisted_modifiers = list(/datum/deathmatch_modifier/nearsightness, /datum/deathmatch_modifier/xray, /datum/deathmatch_modifier/thermal) + +/datum/deathmatch_modifier/echolocation/apply(mob/living/carbon/player, datum/deathmatch_lobby/lobby) + player.AddComponent(/datum/component/echolocation) + +/datum/deathmatch_modifier/ocelot + name = "Ocelot" + description = "Shoot faster, with extra ricochet and less spread. You're pretty good!" + blacklisted_modifiers = list(/datum/deathmatch_modifier/stormtrooper) + +/datum/deathmatch_modifier/ocelot/apply(mob/living/carbon/player, datum/deathmatch_lobby/lobby) + player.add_traits(list(TRAIT_NICE_SHOT, TRAIT_DOUBLE_TAP), DEATHMATCH_TRAIT) + RegisterSignal(player, COMSIG_MOB_FIRED_GUN, PROC_REF(reduce_spread)) + RegisterSignal(player, COMSIG_PROJECTILE_FIRER_BEFORE_FIRE, PROC_REF(apply_ricochet)) + +/datum/deathmatch_modifier/ocelot/proc/reduce_spread(mob/user, obj/item/gun/gun_fired, target, params, zone_override, list/bonus_spread_values) + SIGNAL_HANDLER + bonus_spread_values[MIN_BONUS_SPREAD_INDEX] -= 50 + bonus_spread_values[MAX_BONUS_SPREAD_INDEX] -= 50 + +/datum/deathmatch_modifier/ocelot/proc/apply_ricochet(mob/user, obj/projectile/projectile, datum/fired_from, atom/clicked_atom) + SIGNAL_HANDLER + projectile.ricochets_max += 2 + projectile.min_ricochets += 2 + projectile.ricochet_incidence_leeway = 0 + ADD_TRAIT(projectile, TRAIT_ALWAYS_HIT_ZONE, DEATHMATCH_TRAIT) + +/datum/deathmatch_modifier/stormtrooper + name = "Stormtrooper Aim" + description = "Fresh out of the 'I Can't Aim For Shit' School" + blacklisted_modifiers = list(/datum/deathmatch_modifier/ocelot) + +/datum/deathmatch_modifier/stormtrooper/apply(mob/living/carbon/player, datum/deathmatch_lobby/lobby) + RegisterSignal(player, COMSIG_MOB_FIRED_GUN, PROC_REF(increase_spread)) + +/datum/deathmatch_modifier/stormtrooper/proc/increase_spread(mob/user, obj/item/gun/gun_fired, target, params, zone_override, list/bonus_spread_values) + SIGNAL_HANDLER + bonus_spread_values[MIN_BONUS_SPREAD_INDEX] += 10 + bonus_spread_values[MAX_BONUS_SPREAD_INDEX] += 35 + +/datum/deathmatch_modifier/four_hands + name = "Four Hands" + description = "When one pair isn't enough..." + +/datum/deathmatch_modifier/four_hands/apply(mob/living/carbon/player, datum/deathmatch_lobby/lobby) + player.change_number_of_hands(4) + +/datum/deathmatch_modifier/paraplegic + name = "Paraplegic" + description = "Wheelchairs. For. Everyone." + blacklisted_modifiers = list(/datum/deathmatch_modifier/mounts) + +/datum/deathmatch_modifier/paraplegic/apply(mob/living/carbon/player, datum/deathmatch_lobby/lobby) + player.gain_trauma(/datum/brain_trauma/severe/paralysis/paraplegic, TRAUMA_RESILIENCE_ABSOLUTE) + var/obj/vehicle/ridden/wheelchair/motorized/improved/wheels = new (player.loc) + wheels.setDir(player.dir) + wheels.buckle_mob(player) + +/datum/deathmatch_modifier/mounts + name = "Mounts" + description = "A horse! A horse! My kingdom for a horse!" + blacklisted_modifiers = list(/datum/deathmatch_modifier/paraplegic) + +/datum/deathmatch_modifier/mounts/apply(mob/living/carbon/player, datum/deathmatch_lobby/lobby) + ///We do a bit of fun over balance here, some mounts may be better than others. + var/mount_path = pick(list( + /mob/living/basic/carp, + /mob/living/basic/pony, + /mob/living/basic/pony/syndicate, + /mob/living/basic/pig, + /mob/living/basic/cow, + /mob/living/basic/cow/moonicorn, + /mob/living/basic/mining/wolf, + /mob/living/basic/mining/goldgrub, + /mob/living/basic/mining/goliath/saddled, + )) + var/mob/living/basic/mount = new mount_path (player.loc) + mount.tamed(player, null) + mount.befriend(player) + mount.buckle_mob(player) + if(HAS_TRAIT(lobby, TRAIT_DEATHMATCH_EXPLOSIVE_IMPLANTS)) + var/obj/item/implant/explosive/deathmatch/implant = new() + implant.implant(mount, silent = TRUE, force = TRUE) + +/datum/deathmatch_modifier/no_gravity + name = "No Gravity" + description = "Hone your robusting skills in zero g" + blacklisted_modifiers = list(/datum/deathmatch_modifier/mounts, /datum/deathmatch_modifier/paraplegic, /datum/deathmatch_modifier/minefield) + +/datum/deathmatch_modifier/no_gravity/on_start_game(datum/deathmatch_lobby/lobby) + ASYNC + for(var/turf/turf as anything in lobby.location.reserved_turfs) + turf.AddElement(/datum/element/forced_gravity, 0) + CHECK_TICK + +/datum/deathmatch_modifier/no_gravity/on_end_game(datum/deathmatch_lobby/lobby) + for(var/turf/turf as anything in lobby.location.reserved_turfs) + turf.RemoveElement(/datum/element/forced_gravity, 0) + +/datum/deathmatch_modifier/drop_pod + name = "Drop Pod: Syndies" + description = "Steel Rain: Syndicate Edition" + ///A lazylist of lobbies that have this modifier enabled + var/list/signed_lobbies + ///The type of drop pod that'll periodically fall from the sky + var/drop_pod_type = /obj/structure/closet/supplypod/podspawn/deathmatch + ///A (weighted) list of possible contents of the drop pod. Only one is picked at a time + var/list/contents + ///An interval representing the min and max cooldown between each time it's fired. + var/interval = list(7 SECONDS, 12 SECONDS) + ///How many (a number or a two keyed list) drop pods can be dropped at a time. + var/amount = list(1, 2) + ///The cooldown for dropping pods into every affected deathmatch arena. + COOLDOWN_DECLARE(drop_pod_cd) + +/datum/deathmatch_modifier/drop_pod/New() + . = ..() + populate_contents() + +/datum/deathmatch_modifier/drop_pod/on_select(datum/deathmatch_lobby/lobby) + if(isnull(signed_lobbies)) + START_PROCESSING(SSprocessing, src) + LAZYADD(signed_lobbies, lobby) + RegisterSignal(lobby, COMSIG_QDELETING, PROC_REF(remove_lobby)) + +/datum/deathmatch_modifier/drop_pod/unselect(datum/deathmatch_lobby/lobby) + remove_lobby(lobby) + +/datum/deathmatch_modifier/drop_pod/proc/remove_lobby(datum/deathmatch_lobby/lobby) + SIGNAL_HANDLER + LAZYREMOVE(signed_lobbies, lobby) + UnregisterSignal(lobby, COMSIG_QDELETING) + if(isnull(signed_lobbies)) + STOP_PROCESSING(SSprocessing, src) + +/datum/deathmatch_modifier/drop_pod/process(seconds_per_tick) + if(!COOLDOWN_FINISHED(src, drop_pod_cd)) + return + var/pod_spawned = FALSE + for(var/datum/deathmatch_lobby/lobby as anything in signed_lobbies) + if(lobby.playing != DEATHMATCH_PLAYING || isnull(lobby.location)) + continue + var/yet_to_spawn = islist(amount) ? rand(amount[1], amount[2]) : amount + for(var/attempt in 1 to 10) + var/turf/to_strike = pick(lobby.location.reserved_turfs) + if(!isopenturf(to_strike) || isgroundlessturf(to_strike)) + continue + var/atom/movable/to_spawn + if(length(contents)) + var/spawn_path = pick_weight(contents) + to_spawn = new spawn_path (to_strike) + if(isliving(to_spawn) && HAS_TRAIT(lobby, TRAIT_DEATHMATCH_EXPLOSIVE_IMPLANTS)) + var/obj/item/implant/explosive/deathmatch/implant = new() + implant.implant(to_spawn, silent = TRUE, force = TRUE) + podspawn(list( + "path" = drop_pod_type, + "target" = to_strike, + "spawn" = to_spawn, + )) + pod_spawned = TRUE + yet_to_spawn-- + if(yet_to_spawn == 0) + break + + if(pod_spawned) + COOLDOWN_START(src, drop_pod_cd, rand(interval[1], interval[2])) + +/datum/deathmatch_modifier/drop_pod/proc/populate_contents() + contents = typesof(/mob/living/basic/trooper/syndicate) + +/datum/deathmatch_modifier/drop_pod/monsters + name = "Drop Pod: Monsters" + description = "Monsters are raining from the sky!" + +/datum/deathmatch_modifier/drop_pod/monsters/populate_contents() + contents = list( + /mob/living/basic/ant = 2, + /mob/living/basic/construct/proteon = 2, + /mob/living/basic/flesh_spider = 2, + /mob/living/basic/garden_gnome = 2, + /mob/living/basic/killer_tomato = 2, + /mob/living/basic/leaper = 1, + /mob/living/basic/mega_arachnid = 1, + /mob/living/basic/mining/goliath = 1, + /mob/living/basic/mining/ice_demon = 1, + /mob/living/basic/mining/ice_whelp = 1, + /mob/living/basic/mining/lobstrosity = 1, + /mob/living/basic/mining/mook = 2, + /mob/living/basic/mouse/rat = 2, + /mob/living/basic/spider/giant/nurse/scrawny = 2, + /mob/living/basic/spider/giant/tarantula/scrawny = 2, + /mob/living/basic/spider/giant/hunter/scrawny = 2, + /mob/living/simple_animal/hostile/dark_wizard = 2, + /mob/living/simple_animal/hostile/retaliate/goose = 2, + /mob/living/simple_animal/hostile/ooze = 1, + /mob/living/simple_animal/hostile/vatbeast = 1, + ) + +/datum/deathmatch_modifier/drop_pod/missiles + name = "Drop Pod: Cruise Missiles" + description = "You're going to get shelled hard" + drop_pod_type = /obj/structure/closet/supplypod/deadmatch_missile + interval = list(3 SECONDS, 5 SECONDS) + amount = list(1, 3) + +/datum/deathmatch_modifier/drop_pod/missiles/populate_contents() + return + +/datum/deathmatch_modifier/explode_on_death + name = "Explosive Death" + description = "Everyone gets a microbomb that cannot be manually activated." + +/datum/deathmatch_modifier/explode_on_death/on_start_game(datum/deathmatch_lobby/lobby) + ADD_TRAIT(lobby, TRAIT_DEATHMATCH_EXPLOSIVE_IMPLANTS, DEATHMATCH_TRAIT) + +/datum/deathmatch_modifier/explode_on_death/apply(mob/living/carbon/player, datum/deathmatch_lobby/lobby) + var/obj/item/implant/explosive/deathmatch/implant = new() + implant.implant(player, silent = TRUE, force = TRUE) + +/datum/deathmatch_modifier/helgrasp + name = "Helgrasped" + description = "Cursed hands are being thrown at you!" + +/datum/deathmatch_modifier/helgrasp/apply(mob/living/carbon/player, datum/deathmatch_lobby/lobby) + var/metabolism_rate = /datum/reagent/inverse/helgrasp/heretic::metabolization_rate + player.reagents.add_reagent(/datum/reagent/inverse/helgrasp/heretic, initial(lobby.map.automatic_gameend_time) / metabolism_rate) + +/datum/deathmatch_modifier/wasted + name = "Wasted" + description = "You've had one drink too many" + +/datum/deathmatch_modifier/wasted/apply(mob/living/carbon/player, datum/deathmatch_lobby/lobby) + player.adjust_drunk_effect(rand(30, 35)) + var/metabolism_rate = /datum/reagent/consumable/ethanol/kahlua::metabolization_rate + player.reagents.add_reagent(/datum/reagent/consumable/ethanol/kahlua, initial(lobby.map.automatic_gameend_time) * 0.35 / metabolism_rate) + +/datum/deathmatch_modifier/monkeys + name = "Monkeyfication" + description = "Go back, I want to be monkey!" + +/datum/deathmatch_modifier/monkeys/apply(mob/living/carbon/player, datum/deathmatch_lobby/lobby) + //we don't call monkeyize(), because it'd set the player name to a generic "monkey(number)". + player.set_species(/datum/species/monkey) + +/datum/deathmatch_modifier/inverted_movement + name = "Inverted Movement" + description = "Up is down, left is right" + +/datum/deathmatch_modifier/inverted_movement/apply(mob/living/carbon/player, datum/deathmatch_lobby/lobby) + player.AddElement(/datum/element/inverted_movement) + +/datum/deathmatch_modifier/minefield + name = "Minefield" + description = "Oh, it seems you've trotted on a mine!" + +/datum/deathmatch_modifier/minefield/on_start_game(datum/deathmatch_lobby/lobby) + var/list/mines = subtypesof(/obj/effect/mine) + mines -= list( + /obj/effect/mine/explosive, //too lethal. + /obj/effect/mine/kickmine, //will kick the client, lol + /obj/effect/mine/gas, //Just spawns oxygen. + ) + + ///1 every 10 turfs, but it will actually spawn fewer mines since groundless and closed turfs are skipped. + var/mines_to_spawn = length(lobby.location.reserved_turfs) * 0.1 + for(var/iteration in 1 to mines_to_spawn) + var/turf/target_turf = pick(lobby.location.reserved_turfs) + if(!isopenturf(target_turf) || isgroundlessturf(target_turf)) + continue + ///don't spawn mine next to player spawns. + if(locate(/obj/effect/landmark/deathmatch_player_spawn) in range(1, target_turf)) + continue + var/mine_path = pick(mines) + new mine_path (target_turf) + +/datum/deathmatch_modifier/flipping + name = "Perma-Flipping" + description = "You're constantly flipping, however it's purely cosmetic" + +/datum/deathmatch_modifier/flipping/apply(mob/living/carbon/player, datum/deathmatch_lobby/lobby) + player.SpinAnimation(speed = 0.9 SECONDS, loops = -1) + +/datum/deathmatch_modifier/screen_flipping + name = "Rotating Screen" + description = "♪ You spin me right round, baby right round ♪" + +/datum/deathmatch_modifier/screen_flipping/apply(mob/living/carbon/player, datum/deathmatch_lobby/lobby) + var/atom/movable/plane_master_controller/pm_controller = player.hud_used.plane_master_controllers[PLANE_MASTERS_GAME] + var/clockwise = prob(50) + for(var/atom/movable/screen/plane_master/plane as anything in pm_controller.get_planes()) + plane.SpinAnimation(4.5 SECONDS, clockwise = clockwise) + +/datum/deathmatch_modifier/random + name = "Random Modifiers" + description = "Picks 3 to 5 random modifiers as the game is about to start" + +/datum/deathmatch_modifier/random/on_select(datum/deathmatch_lobby/lobby) + ///remove any other global modifier if chosen. It'll pick random ones when the time comes. + for(var/modpath in lobby.modifiers) + var/datum/deathmatch_modifier/modifier = GLOB.deathmatch_game.modifiers[modpath] + if(modifier.random_exempted) + continue + modifier.unselect(lobby) + lobby -= modpath + +/datum/deathmatch_modifier/random/on_start_game(datum/deathmatch_lobby/lobby) + lobby.modifiers -= type //remove it before attempting to select other modifiers, or they'll fail. + + var/static/list/static_pool + if(!static_pool) + static_pool = subtypesof(/datum/deathmatch_modifier) + for(var/datum/deathmatch_modifier/modpath as anything in static_pool) + if(initial(modpath.random_exempted)) + static_pool -= modpath + var/list/modifiers_pool = static_pool.Copy() + + ///Pick global modifiers at random. + for(var/iteration in rand(3, 5)) + var/mod_len = length(modifiers_pool) + if(!mod_len) + break + var/datum/deathmatch_modifier/modifier + if(mod_len > 1) + modifier = GLOB.deathmatch_game.modifiers[pick_n_take(modifiers_pool)] + else //pick() throws errors if the list has only one element iirc. + modifier = GLOB.deathmatch_game.modifiers[modifiers_pool[1]] + modifiers_pool = null + if(!modifier.selectable(lobby)) + continue + modifier.on_select(lobby) + modifier.on_start_game(lobby) + lobby += modifier + modifiers_pool -= modifier.blacklisted_modifiers + +/datum/deathmatch_modifier/any_loadout + name = "Any Loadout Allowed" + description = "Watch players pick Instagib everytime" + random_exempted = TRUE + +/datum/deathmatch_modifier/any_loadout/selectable(datum/deathmatch_lobby/lobby) + . = ..() + if(!.) + return + return lobby.map.allowed_loadouts + +/datum/deathmatch_modifier/any_loadout/on_select(datum/deathmatch_lobby/lobby) + lobby.loadouts = GLOB.deathmatch_game.loadouts + +/datum/deathmatch_modifier/any_loadout/unselect(datum/deathmatch_lobby/lobby) + lobby.loadouts = lobby.map.allowed_loadouts + +/datum/deathmatch_modifier/any_loadout/on_map_changed(datum/deathmatch_lobby/lobby) + if(lobby.loadouts == GLOB.deathmatch_game.loadouts) //This arena already allows any loadout for some reason. + lobby.modifiers -= type + else + lobby.loadouts = GLOB.deathmatch_game.loadouts diff --git a/code/modules/events/ghost_role/fugitive_event.dm b/code/modules/events/ghost_role/fugitive_event.dm index 4b86e751c0b981d..687dde2dcee0f34 100644 --- a/code/modules/events/ghost_role/fugitive_event.dm +++ b/code/modules/events/ghost_role/fugitive_event.dm @@ -105,7 +105,7 @@ /datum/round_event/ghost_role/fugitives/proc/check_spawn_hunters(backstory, remaining_time) //if the emergency shuttle has been called, spawn hunters now to give them a chance - if(remaining_time == 0 || SSshuttle.emergency.mode != EMERGENCY_IDLE_OR_RECALLED) + if(remaining_time == 0 || !EMERGENCY_IDLE_OR_RECALLED) spawn_hunters(backstory) return addtimer(CALLBACK(src, PROC_REF(check_spawn_hunters), backstory, remaining_time - 1 MINUTES), 1 MINUTES) diff --git a/code/modules/fishing/aquarium/aquarium_kit.dm b/code/modules/fishing/aquarium/aquarium_kit.dm index 3aafa178f263677..e22ccb3755879a2 100644 --- a/code/modules/fishing/aquarium/aquarium_kit.dm +++ b/code/modules/fishing/aquarium/aquarium_kit.dm @@ -85,7 +85,7 @@ ) return pick_weight(weighted_list) -/obj/item/storage/fish_cas/blackmarket/Initialize(mapload) +/obj/item/storage/fish_case/blackmarket/Initialize(mapload) . = ..() for(var/obj/item/fish/fish as anything in contents) fish.set_status(FISH_DEAD) diff --git a/code/modules/fishing/fish/fish_traits.dm b/code/modules/fishing/fish/fish_traits.dm index f247d11ef8484d8..8dee817f3e57fb5 100644 --- a/code/modules/fishing/fish/fish_traits.dm +++ b/code/modules/fishing/fish/fish_traits.dm @@ -213,9 +213,10 @@ GLOBAL_LIST_INIT(fish_traits, init_subtypes_w_path_keys(/datum/fish_trait, list( /datum/fish_trait/revival/proc/check_status(obj/item/fish/source) SIGNAL_HANDLER if(source.status == FISH_DEAD) - addtimer(CALLBACK(src, PROC_REF(revive), source), rand(1 MINUTES, 2 MINUTES)) + addtimer(CALLBACK(src, PROC_REF(revive), WEAKREF(source)), rand(1 MINUTES, 2 MINUTES)) -/datum/fish_trait/revival/proc/revive(obj/item/fish/source) +/datum/fish_trait/revival/proc/revive(datum/weakref/fish_ref) + var/obj/item/fish/source = fish_ref.resolve() if(QDELETED(source) || source.status != FISH_DEAD) return source.set_status(FISH_ALIVE) diff --git a/code/modules/food_and_drinks/machinery/grill.dm b/code/modules/food_and_drinks/machinery/grill.dm index bfa740a6fb23ba3..3d9acdde0baf170 100644 --- a/code/modules/food_and_drinks/machinery/grill.dm +++ b/code/modules/food_and_drinks/machinery/grill.dm @@ -1,33 +1,88 @@ -//I JUST WANNA GRILL FOR GOD'S SAKE - +///The fuel amount wasted as heat #define GRILL_FUELUSAGE_IDLE 0.5 +///The fuel amount used to actually grill the item #define GRILL_FUELUSAGE_ACTIVE 5 -/obj/machinery/grill//SKYRAT EDIT - ICON OVERRIDEN BY AESTHETICS - SEE MODULE - name = "grill" - desc = "Just like the old days." +/obj/machinery/grill //SKYRAT EDIT - ICON OVERRIDEN BY AESTHETICS - SEE MODULE + name = "Barbeque grill" + desc = "Just like the old days. Smokes items over a light heat" icon = 'icons/obj/machines/kitchen.dmi' icon_state = "grill_open" density = TRUE pass_flags_self = PASSMACHINE | LETPASSTHROW - layer = BELOW_OBJ_LAYER + processing_flags = START_PROCESSING_MANUALLY use_power = NO_POWER_USE + + ///The amount of fuel gained from stacks or reagents var/grill_fuel = 0 + ///The item we are trying to grill var/obj/item/food/grilled_item + ///The amount of time the food item has spent on the grill var/grill_time = 0 + ///Sound loop for the sizzling sound var/datum/looping_sound/grill/grill_loop /obj/machinery/grill/Initialize(mapload) . = ..() + create_reagents(30, NO_REACT) grill_loop = new(src, FALSE) + register_context() /obj/machinery/grill/Destroy() - grilled_item = null + QDEL_NULL(grilled_item) QDEL_NULL(grill_loop) return ..() +/obj/machinery/grill/on_deconstruction(disassembled) + if(!QDELETED(grilled_item)) + grilled_item.forceMove(drop_location()) + + new /obj/item/assembly/igniter(loc) + new /obj/item/stack/sheet/iron(loc, 5) + new /obj/item/stack/rods(loc, 5) + + if(grill_fuel > 0) + var/datum/effect_system/fluid_spread/smoke/bad/smoke = new + smoke.set_up(1, holder = src, location = loc) + smoke.start() + +/obj/machinery/grill/add_context(atom/source, list/context, obj/item/held_item, mob/user) + . = NONE + if(isnull(held_item) || (held_item.item_flags & ABSTRACT) || (held_item.flags_1 & HOLOGRAM_1) || (held_item.resistance_flags & INDESTRUCTIBLE)) + return + + if(istype(held_item, /obj/item/stack/sheet/mineral/coal) || istype(held_item, /obj/item/stack/sheet/mineral/wood)) + context[SCREENTIP_CONTEXT_LMB] = "Add fuel" + return CONTEXTUAL_SCREENTIP_SET + else if(is_reagent_container(held_item) && held_item.is_open_container() && held_item.reagents.total_volume) + context[SCREENTIP_CONTEXT_LMB] = "Add fuel" + return CONTEXTUAL_SCREENTIP_SET + else if(IS_EDIBLE(held_item) && !HAS_TRAIT(held_item, TRAIT_NODROP)) + context[SCREENTIP_CONTEXT_LMB] = "Add item" + return CONTEXTUAL_SCREENTIP_SET + else if(held_item.tool_behaviour == TOOL_WRENCH) + context[SCREENTIP_CONTEXT_LMB] = "[anchored ? "Un" : ""]anchor" + return CONTEXTUAL_SCREENTIP_SET + else if(!anchored && held_item.tool_behaviour == TOOL_CROWBAR) + context[SCREENTIP_CONTEXT_LMB] = "Deconstruct" + return CONTEXTUAL_SCREENTIP_SET + +/obj/machinery/grill/examine(mob/user) + . = ..() + + . += span_notice("Add fuel via wood/coal stacks or any open container having a good fuel source") + . += span_notice("Monkey energy > Oil > Welding fuel > Ethanol. Others cause bad effects") + . += span_notice("Place any food item on top via hand to start grilling") + + if(!anchored) + . += span_notice("It can be [EXAMINE_HINT("pried")] apart.") + if(anchored) + . += span_notice("Its [EXAMINE_HINT("anchored")] in place.") + else + . += span_warning("It needs to be [EXAMINE_HINT("anchored")] to work.") + /obj/machinery/grill/update_icon_state() - if(grilled_item) + if(!QDELETED(grilled_item)) icon_state = "grill" return ..() if(grill_fuel > 0) @@ -36,115 +91,216 @@ icon_state = "grill_open" return ..() -/obj/machinery/grill/attackby(obj/item/I, mob/user) - if(istype(I, /obj/item/stack/sheet/mineral/coal) || istype(I, /obj/item/stack/sheet/mineral/wood)) - var/obj/item/stack/S = I - var/stackamount = S.get_amount() - to_chat(user, span_notice("You put [stackamount] [I]s in [src].")) - if(istype(I, /obj/item/stack/sheet/mineral/coal)) - grill_fuel += (500 * stackamount) - else - grill_fuel += (50 * stackamount) - S.use(stackamount) - update_appearance() - return - if(I.resistance_flags & INDESTRUCTIBLE) - to_chat(user, span_warning("You don't feel it would be wise to grill [I]...")) - return ..() - if(istype(I, /obj/item/reagent_containers/cup/glass)) - if(I.reagents.has_reagent(/datum/reagent/consumable/monkey_energy)) - grill_fuel += (20 * (I.reagents.get_reagent_amount(/datum/reagent/consumable/monkey_energy))) - to_chat(user, span_notice("You pour the Monkey Energy in [src].")) - I.reagents.remove_reagent(/datum/reagent/consumable/monkey_energy, I.reagents.get_reagent_amount(/datum/reagent/consumable/monkey_energy)) - update_appearance() - return - else if(IS_EDIBLE(I)) - if(HAS_TRAIT(I, TRAIT_NODROP) || (I.item_flags & (ABSTRACT | DROPDEL))) - return ..() - else if(HAS_TRAIT(I, TRAIT_FOOD_GRILLED)) - to_chat(user, span_notice("[I] has already been grilled!")) - return - else if(grill_fuel <= 0) - to_chat(user, span_warning("There is not enough fuel!")) - return - else if(!grilled_item && user.transferItemToLoc(I, src)) - grilled_item = I - RegisterSignal(grilled_item, COMSIG_ITEM_GRILLED, PROC_REF(GrillCompleted)) - to_chat(user, span_notice("You put the [grilled_item] on [src].")) - update_appearance() - grill_loop.start() - return - - ..() - -/obj/machinery/grill/process(seconds_per_tick) - update_appearance() - if(grill_fuel <= 0) - return - else - grill_fuel -= GRILL_FUELUSAGE_IDLE * seconds_per_tick - if(SPT_PROB(0.5, seconds_per_tick)) - var/datum/effect_system/fluid_spread/smoke/bad/smoke = new - smoke.set_up(1, holder = src, location = loc) - smoke.start() - if(grilled_item) - SEND_SIGNAL(grilled_item, COMSIG_ITEM_GRILL_PROCESS, src, seconds_per_tick) - if(QDELETED(grilled_item)) - grilled_item = null - finish_grill() - return - grill_time += seconds_per_tick * 10 //convert to deciseconds - grilled_item.reagents.add_reagent(/datum/reagent/consumable/char, 0.5 * seconds_per_tick) - grill_fuel -= GRILL_FUELUSAGE_ACTIVE * seconds_per_tick - grilled_item.AddComponent(/datum/component/sizzle) - /obj/machinery/grill/Exited(atom/movable/gone, direction) . = ..() if(gone == grilled_item) - finish_grill() + grill_time = 0 + grill_loop.stop() grilled_item = null -/obj/machinery/grill/wrench_act(mob/living/user, obj/item/I) - . = ..() - if(default_unfasten_wrench(user, I) != CANT_UNFASTEN) +/obj/machinery/grill/attack_hand(mob/living/user, list/modifiers) + if(!QDELETED(grilled_item)) + balloon_alert(user, "item removed") + grilled_item.forceMove(drop_location()) + update_appearance(UPDATE_ICON_STATE) return TRUE -/obj/machinery/grill/on_deconstruction(disassembled) - if(grilled_item) - finish_grill() - new /obj/item/stack/sheet/iron(loc, 5) - new /obj/item/stack/rods(loc, 5) + return ..() /obj/machinery/grill/attack_ai(mob/user) - return + return //the ai can't physically flip the lid for the grill + + +/// Makes grill fuel from a unit of stack +/obj/machinery/grill/proc/burn_stack() + PRIVATE_PROC(TRUE) + + //compute boost from wood or coal + var/boost + for(var/obj/item/stack in contents) + boost = 5 * (GRILL_FUELUSAGE_IDLE + GRILL_FUELUSAGE_ACTIVE) + if(istype(stack, /obj/item/stack/sheet/mineral/coal)) + boost *= 2 + if(stack.use(1)) + grill_fuel += boost + update_appearance(UPDATE_ICON_STATE) + +/obj/machinery/grill/item_interaction(mob/living/user, obj/item/weapon, list/modifiers, is_right_clicking) + if(user.combat_mode || (weapon.item_flags & ABSTRACT) || (weapon.flags_1 & HOLOGRAM_1) || (weapon.resistance_flags & INDESTRUCTIBLE)) + return ..() + + if(istype(weapon, /obj/item/stack/sheet/mineral/coal) || istype(weapon, /obj/item/stack/sheet/mineral/wood)) + if(!QDELETED(grilled_item)) + return ..() + if(!anchored) + balloon_alert(user, "anchor first!") + return ITEM_INTERACT_BLOCKING + + //required for amount subtypes + var/target_type + if(istype(weapon, /obj/item/stack/sheet/mineral/coal)) + target_type = /obj/item/stack/sheet/mineral/coal + else + target_type = /obj/item/stack/sheet/mineral/wood + + //transfer or merge stacks if we have enough space + var/merged = FALSE + var/obj/item/stack/target = weapon + for(var/obj/item/stack/stored in contents) + if(!istype(stored, target_type)) + continue + if(stored.amount == MAX_STACK_SIZE) + to_chat(user, span_warning("No space for [weapon]")) + return ITEM_INTERACT_BLOCKING + target.merge(stored) + merged = TRUE + break + if(!merged) + weapon.forceMove(src) + + to_chat(user, span_notice("You add [src] to the fuel stack")) + if(!grill_fuel) + burn_stack() + begin_processing() + return ITEM_INTERACT_SUCCESS + + if(is_reagent_container(weapon) && weapon.is_open_container()) + var/obj/item/reagent_containers/container = weapon + if(!QDELETED(grilled_item)) + return ..() + if(!anchored) + balloon_alert(user, "anchor first!") + return ITEM_INTERACT_BLOCKING + + var/transfered_amount = weapon.reagents.trans_to(src, container.amount_per_transfer_from_this) + if(transfered_amount) + //reagents & their effects on fuel + var/static/list/fuel_map = list( + /datum/reagent/consumable/monkey_energy = 4, + /datum/reagent/fuel/oil = 3, + /datum/reagent/fuel = 2, + /datum/reagent/consumable/ethanol = 1 + ) + + //compute extra fuel to be obtained from everything transfered + var/boost + var/additional_fuel = 0 + for(var/datum/reagent/stored as anything in reagents.reagent_list) + boost = fuel_map[stored.type] + if(!boost) //anything we don't recognize as fuel has inverse effects + boost = -1 + boost = boost * stored.volume * (GRILL_FUELUSAGE_IDLE + GRILL_FUELUSAGE_ACTIVE) + additional_fuel += boost + + //add to fuel source + reagents.clear_reagents() + grill_fuel += additional_fuel + if(grill_fuel <= 0) //can happen if you put water or something + grill_fuel = 0 + else + begin_processing() + update_appearance(UPDATE_ICON_STATE) + + //feedback + to_chat(user, span_notice("You transfer [transfered_amount]u to the fuel source")) + return ITEM_INTERACT_SUCCESS + else + to_chat(user, span_warning("No fuel was transfered")) + return ITEM_INTERACT_BLOCKING + + if(IS_EDIBLE(weapon)) + //sanity checks + if(!anchored) + balloon_alert(user, "anchor first!") + return ITEM_INTERACT_BLOCKING + if(HAS_TRAIT(weapon, TRAIT_NODROP)) + return ..() + if(!QDELETED(grilled_item)) + balloon_alert(user, "remove item first!") + return ITEM_INTERACT_BLOCKING + else if(grill_fuel <= 0) + balloon_alert(user, "no fuel!") + return ITEM_INTERACT_BLOCKING + else if(!user.transferItemToLoc(weapon, src)) + balloon_alert(user, "[weapon] is stuck in your hand!") + return ITEM_INTERACT_BLOCKING + + //add the item on the grill + grill_time = 0 + grilled_item = weapon + var/datum/component/sizzle/sizzle = grilled_item.GetComponent(/datum/component/sizzle) + if(!isnull(sizzle)) + grill_time = sizzle.time_elapsed() + to_chat(user, span_notice("You put the [grilled_item] on [src].")) + update_appearance(UPDATE_ICON_STATE) + grill_loop.start() + return ITEM_INTERACT_SUCCESS -/obj/machinery/grill/attack_hand(mob/user, list/modifiers) - if(grilled_item) - to_chat(user, span_notice("You take out [grilled_item] from [src].")) - grilled_item.forceMove(drop_location()) - update_appearance() - return return ..() -/obj/machinery/grill/proc/finish_grill() +/obj/machinery/grill/wrench_act(mob/living/user, obj/item/tool) + if(user.combat_mode) + return NONE + + . = ITEM_INTERACT_BLOCKING + if(default_unfasten_wrench(user, tool) == SUCCESSFUL_UNFASTEN) + return ITEM_INTERACT_SUCCESS + +/obj/machinery/grill/crowbar_act(mob/living/user, obj/item/tool) + if(user.combat_mode) + return NONE + + . = ITEM_INTERACT_BLOCKING + if(anchored) + balloon_alert(user, "unanchor first!") + return + + if(default_deconstruction_crowbar(tool, ignore_panel = TRUE)) + return ITEM_INTERACT_SUCCESS + +/obj/machinery/grill/process(seconds_per_tick) + if(!anchored) + return PROCESS_KILL + + var/fuel_usage = GRILL_FUELUSAGE_IDLE * seconds_per_tick + if(grill_fuel < fuel_usage) + grill_fuel = 0 + burn_stack() + if(grill_fuel < fuel_usage) //could not make any fuel + return PROCESS_KILL + + //use fuel, create smoke puffs for immersion + grill_fuel -= fuel_usage + if(SPT_PROB(0.5, seconds_per_tick)) + var/datum/effect_system/fluid_spread/smoke/bad/smoke = new + smoke.set_up(1, holder = src, location = loc) + smoke.start() + + fuel_usage = GRILL_FUELUSAGE_ACTIVE * seconds_per_tick if(!QDELETED(grilled_item)) + //check to see if we need to burn more fuel + if(grill_fuel < fuel_usage) + burn_stack() + if(grill_fuel < fuel_usage) //could not make any fuel + return + + //grill the item + var/last_grill_time = grill_time + grill_time += seconds_per_tick * 10 //convert to deciseconds + grilled_item.reagents.add_reagent(/datum/reagent/consumable/char, 0.5 * seconds_per_tick) + grilled_item.AddComponent(/datum/component/sizzle, grill_time) + + //check to see if we have grilled our item to perfection var/time_limit = 20 SECONDS - //when items grill themselves in their own unique ways we want to follow their constraints var/datum/component/grillable/custom_grilling = grilled_item.GetComponent(/datum/component/grillable) if(!isnull(custom_grilling)) time_limit = custom_grilling.required_cook_time - if(grill_time >= time_limit) + grilled_item.RemoveElement(/datum/element/grilled_item, last_grill_time) grilled_item.AddElement(/datum/element/grilled_item, grill_time) - UnregisterSignal(grilled_item, COMSIG_ITEM_GRILLED) - - grill_time = 0 - grill_loop.stop() -///Called when a food is transformed by the grillable component -/obj/machinery/grill/proc/GrillCompleted(obj/item/source, atom/grilled_result) - SIGNAL_HANDLER - grilled_item = grilled_result //use the new item!! + //use fuel + grill_fuel -= fuel_usage /obj/machinery/grill/unwrenched anchored = FALSE diff --git a/code/modules/food_and_drinks/machinery/icecream_vat.dm b/code/modules/food_and_drinks/machinery/icecream_vat.dm index e5742418c140f09..d4de59919954482 100644 --- a/code/modules/food_and_drinks/machinery/icecream_vat.dm +++ b/code/modules/food_and_drinks/machinery/icecream_vat.dm @@ -249,6 +249,12 @@ reagents.remove_reagent(reagents_used, CONE_REAGENET_NEEDED) balloon_alert_to_viewers("scoops [selected_flavour]", "scoops [selected_flavour]") + if(istype(cone)) + if(isnull(cone.crafted_food_buff)) + cone.crafted_food_buff = /datum/status_effect/food/chilling + if(user.mind) + ADD_TRAIT(cone, TRAIT_FOOD_CHEF_MADE, REF(user.mind)) + ///Swaps the mode to the next one meant to be selected, then tells the user who changed it. /obj/machinery/icecream_vat/proc/swap_modes(mob/user) if(!user.can_perform_action(src)) diff --git a/code/modules/food_and_drinks/plate.dm b/code/modules/food_and_drinks/plate.dm index a0d24dec8dacbaa..1df1d7c24bb9175 100644 --- a/code/modules/food_and_drinks/plate.dm +++ b/code/modules/food_and_drinks/plate.dm @@ -22,7 +22,7 @@ . = ..() if(fragile) - AddElement(/datum/element/shatters_when_thrown) + AddElement(/datum/element/can_shatter) /obj/item/plate/attackby(obj/item/I, mob/user, params) if(!IS_EDIBLE(I)) diff --git a/code/modules/forensics/_forensics.dm b/code/modules/forensics/_forensics.dm index 40b480182537e17..5c43b9da0995c6a 100644 --- a/code/modules/forensics/_forensics.dm +++ b/code/modules/forensics/_forensics.dm @@ -8,8 +8,8 @@ * * List of clothing fibers on the atom */ /datum/forensics - /// Weakref to the parent owning this datum - var/datum/weakref/parent + /// Ref to the parent owning this datum + var/atom/parent /** * List of fingerprints on this atom * @@ -39,7 +39,7 @@ */ var/list/fibers -/datum/forensics/New(atom/parent, fingerprints, hiddenprints, blood_DNA, fibers) +/datum/forensics/New(atom/parent, list/fingerprints, list/hiddenprints, list/blood_DNA, list/fibers) if(!isatom(parent)) stack_trace("We tried adding a forensics datum to something that isnt an atom. What the hell are you doing?") qdel(src) @@ -47,7 +47,7 @@ RegisterSignal(parent, COMSIG_COMPONENT_CLEAN_ACT, PROC_REF(clean_act)) - src.parent = WEAKREF(parent) + src.parent = parent src.fingerprints = fingerprints src.hiddenprints = hiddenprints src.blood_DNA = blood_DNA @@ -67,9 +67,7 @@ check_blood() /datum/forensics/Destroy(force) - var/atom/parent_atom = parent.resolve() - if (!isnull(parent_atom)) - UnregisterSignal(parent_atom, list(COMSIG_COMPONENT_CLEAN_ACT)) + UnregisterSignal(parent, COMSIG_COMPONENT_CLEAN_ACT) parent = null return ..() @@ -148,10 +146,7 @@ /// Adds a single fiber /datum/forensics/proc/add_fibers(mob/living/carbon/human/suspect) var/fibertext - var/atom/actual_parent = parent?.resolve() - if(isnull(actual_parent)) - parent = null - var/item_multiplier = isitem(actual_parent) ? ITEM_FIBER_MULTIPLIER : NON_ITEM_FIBER_MULTIPLIER + var/item_multiplier = isitem(parent) ? ITEM_FIBER_MULTIPLIER : NON_ITEM_FIBER_MULTIPLIER if(suspect.wear_suit) fibertext = "Material from \a [suspect.wear_suit]." if(prob(10 * item_multiplier) && !LAZYACCESS(fibers, fibertext)) @@ -217,11 +212,7 @@ if(last_stamp_pos) LAZYSET(hiddenprints, suspect.key, copytext(hiddenprints[suspect.key], 1, last_stamp_pos)) hiddenprints[suspect.key] += "\nLast: \[[current_time]\] \"[suspect.real_name]\"[has_gloves]. Ckey: [suspect.ckey]" //made sure to be existing by if(!LAZYACCESS);else - var/atom/parent_atom = parent?.resolve() - if(!isnull(parent_atom)) - parent_atom.fingerprintslast = suspect.ckey - else - parent = null + parent.fingerprintslast = suspect.ckey return TRUE /// Adds the given list into blood_DNA @@ -236,12 +227,8 @@ /// Updates the blood displayed on parent /datum/forensics/proc/check_blood() - var/obj/item/the_thing = parent?.resolve() - if(isnull(the_thing)) - parent = null - return - if(!istype(the_thing) || isorgan(the_thing)) // organs don't spawn with blood decals by default + if(!isitem(parent) || isorgan(parent)) // organs don't spawn with blood decals by default return if(!length(blood_DNA)) return - the_thing.AddElement(/datum/element/decal/blood) + parent.AddElement(/datum/element/decal/blood) diff --git a/code/modules/forensics/forensics_helpers.dm b/code/modules/forensics/forensics_helpers.dm index d71d1ebe1539c74..8cb7f721842101d 100644 --- a/code/modules/forensics/forensics_helpers.dm +++ b/code/modules/forensics/forensics_helpers.dm @@ -1,5 +1,7 @@ /// Adds a list of fingerprints to the atom /atom/proc/add_fingerprint_list(list/fingerprints_to_add) //ASSOC LIST FINGERPRINT = FINGERPRINT + if (QDELETED(src)) + return if (isnull(fingerprints_to_add)) return if (forensics) @@ -10,7 +12,7 @@ /// Adds a single fingerprint to the atom /atom/proc/add_fingerprint(mob/suspect, ignoregloves = FALSE) //Set ignoregloves to add prints irrespective of the mob having gloves on. - if (QDELING(src)) + if (QDELETED(src)) return if (isnull(forensics)) forensics = new(src) @@ -19,6 +21,8 @@ /// Add a list of fibers to the atom /atom/proc/add_fiber_list(list/fibers_to_add) //ASSOC LIST FIBERTEXT = FIBERTEXT + if (QDELETED(src)) + return if (isnull(fibers_to_add)) return if (forensics) @@ -29,6 +33,8 @@ /// Adds a single fiber to the atom /atom/proc/add_fibers(mob/living/carbon/human/suspect) + if (QDELETED(src)) + return var/old = 0 if(suspect.gloves && istype(suspect.gloves, /obj/item/clothing)) var/obj/item/clothing/gloves/suspect_gloves = suspect.gloves @@ -47,6 +53,8 @@ /// Adds a list of hiddenprints to the atom /atom/proc/add_hiddenprint_list(list/hiddenprints_to_add) //NOTE: THIS IS FOR ADMINISTRATION FINGERPRINTS, YOU MUST CUSTOM SET THIS TO INCLUDE CKEY/REAL NAMES! CHECK FORENSICS.DM + if (QDELETED(src)) + return if (isnull(hiddenprints_to_add)) return if (forensics) @@ -57,6 +65,8 @@ /// Adds a single hiddenprint to the atom /atom/proc/add_hiddenprint(mob/suspect) + if (QDELETED(src)) + return if (isnull(forensics)) forensics = new(src) forensics.add_hiddenprint(suspect) @@ -67,6 +77,8 @@ return FALSE /obj/add_blood_DNA(list/blood_DNA_to_add) + if (QDELETED(src)) + return . = ..() if (isnull(blood_DNA_to_add)) return . @@ -98,6 +110,8 @@ return FALSE /mob/living/carbon/human/add_blood_DNA(list/blood_DNA_to_add, list/datum/disease/diseases) + if (QDELETED(src)) + return if(wear_suit) wear_suit.add_blood_DNA(blood_DNA_to_add) update_worn_oversuit() diff --git a/code/modules/hallucination/stray_bullet.dm b/code/modules/hallucination/stray_bullet.dm index 97f75f95061064e..9281bc6534361ea 100644 --- a/code/modules/hallucination/stray_bullet.dm +++ b/code/modules/hallucination/stray_bullet.dm @@ -34,6 +34,7 @@ damage = 0 projectile_type = /obj/projectile/hallucination log_override = TRUE + do_not_log = TRUE /// Our parent hallucination that's created us var/datum/hallucination/parent /// The image that represents our projectile itself diff --git a/code/modules/holiday/holidays.dm b/code/modules/holiday/holidays.dm index f41f607dabe120f..24e5274f7fbfeb1 100644 --- a/code/modules/holiday/holidays.dm +++ b/code/modules/holiday/holidays.dm @@ -456,8 +456,8 @@ /datum/holiday/france/greet() return "Do you hear the people sing?" -/datum/holiday/hotdogday //I have plans for this. - name = "National Hot Dog Day" +/datum/holiday/hotdogday + name = HOTDOG_DAY begin_day = 17 begin_month = JULY diff --git a/code/modules/hydroponics/grown/ambrosia.dm b/code/modules/hydroponics/grown/ambrosia.dm index aa02ba7efa1bca8..2becc390f39802a 100644 --- a/code/modules/hydroponics/grown/ambrosia.dm +++ b/code/modules/hydroponics/grown/ambrosia.dm @@ -74,6 +74,8 @@ icon_state = "ambrosia_gaia" light_system = OVERLAY_LIGHT light_range = 3 + light_power = 1.2 + light_color = "#ffff00" seed = /obj/item/seeds/ambrosia/gaia wine_power = 70 wine_flavor = "the earthmother's blessing" diff --git a/code/modules/hydroponics/grown/cereals.dm b/code/modules/hydroponics/grown/cereals.dm index 2bcc2860458bbc0..744c0dc5b023cf4 100644 --- a/code/modules/hydroponics/grown/cereals.dm +++ b/code/modules/hydroponics/grown/cereals.dm @@ -25,6 +25,8 @@ grind_results = list(/datum/reagent/consumable/flour = 0) tastes = list("wheat" = 1) distill_reagent = /datum/reagent/consumable/ethanol/beer + slot_flags = ITEM_SLOT_MASK + worn_icon = 'icons/mob/clothing/head/hydroponics.dmi' // Oat /obj/item/seeds/wheat/oat @@ -93,6 +95,8 @@ grind_results = list(/datum/reagent/consumable/flour = 0, /datum/reagent/blood = 0) tastes = list("meatwheat" = 1) can_distill = FALSE + slot_flags = ITEM_SLOT_MASK + worn_icon = 'icons/mob/clothing/head/hydroponics.dmi' /obj/item/food/grown/meatwheat/attack_self(mob/living/user) user.visible_message(span_notice("[user] crushes [src] into meat."), span_notice("You crush [src] into something that resembles meat.")) diff --git a/code/modules/instruments/items.dm b/code/modules/instruments/items.dm index d9a7e2f3e8b18ea..dcc4ef8daba3d8b 100644 --- a/code/modules/instruments/items.dm +++ b/code/modules/instruments/items.dm @@ -34,20 +34,7 @@ user.visible_message(span_suicide("[user] begins to play 'Gloomy Sunday'! It looks like [user.p_theyre()] trying to commit suicide!")) return BRUTELOSS -/obj/item/instrument/attack_self(mob/user) - if(!ISADVANCEDTOOLUSER(user)) - to_chat(user, span_warning("You don't have the dexterity to do this!")) - return TRUE - interact(user) - -/obj/item/instrument/interact(mob/user) - ui_interact(user) - -/obj/item/instrument/ui_interact(mob/living/user) - if(!isliving(user) || user.stat != CONSCIOUS || (HAS_TRAIT(user, TRAIT_HANDS_BLOCKED) && !ispAI(user))) - return - - user.set_machine(src) +/obj/item/instrument/ui_interact(mob/user, datum/tgui/ui) song.ui_interact(user) /obj/item/instrument/violin @@ -130,9 +117,9 @@ . = ..() AddElement(/datum/element/spooky) -/obj/item/instrument/trumpet/spectral/attack(mob/living/carbon/C, mob/user) - playsound (src, 'sound/runtime/instruments/trombone/En4.mid', 100,1,-1) - ..() +/obj/item/instrument/trumpet/spectral/attack(mob/living/target_mob, mob/living/user, params) + playsound(src, 'sound/runtime/instruments/trombone/En4.mid', 1000, 1, -1) + return ..() /obj/item/instrument/saxophone name = "saxophone" @@ -154,9 +141,9 @@ . = ..() AddElement(/datum/element/spooky) -/obj/item/instrument/saxophone/spectral/attack(mob/living/carbon/C, mob/user) - playsound (src, 'sound/runtime/instruments/saxophone/En4.mid', 100,1,-1) - ..() +/obj/item/instrument/saxophone/spectral/attack(mob/living/target_mob, mob/living/user, params) + playsound(src, 'sound/runtime/instruments/trombone/En4.mid', 1000, 1, -1) + return ..() /obj/item/instrument/trombone name = "trombone" @@ -178,9 +165,9 @@ . = ..() AddElement(/datum/element/spooky) -/obj/item/instrument/trombone/spectral/attack(mob/living/carbon/C, mob/user) - playsound (src, 'sound/runtime/instruments/trombone/Cn4.mid', 100,1,-1) - ..() +/obj/item/instrument/trombone/spectral/attack(mob/living/target_mob, mob/living/user, params) + playsound(src, 'sound/runtime/instruments/trombone/Cn4.mid', 1000, 1, -1) + return ..() /obj/item/instrument/recorder name = "recorder" @@ -201,19 +188,24 @@ w_class = WEIGHT_CLASS_SMALL actions_types = list(/datum/action/item_action/instrument) -/obj/item/instrument/harmonica/proc/handle_speech(datum/source, list/speech_args) - SIGNAL_HANDLER - if(song.playing && ismob(loc)) - to_chat(loc, span_warning("You stop playing the harmonica to talk...")) - song.playing = FALSE - -/obj/item/instrument/harmonica/equipped(mob/M, slot) +/obj/item/instrument/harmonica/equipped(mob/user, slot, initial = FALSE) . = ..() - RegisterSignal(M, COMSIG_MOB_SAY, PROC_REF(handle_speech)) + if(!(slot & slot_flags)) + return + RegisterSignal(user, COMSIG_MOB_SAY, PROC_REF(handle_speech)) -/obj/item/instrument/harmonica/dropped(mob/M) +/obj/item/instrument/harmonica/dropped(mob/user, silent = FALSE) . = ..() - UnregisterSignal(M, COMSIG_MOB_SAY) + UnregisterSignal(user, COMSIG_MOB_SAY) + +/obj/item/instrument/harmonica/proc/handle_speech(datum/source, list/speech_args) + SIGNAL_HANDLER + if(!song.playing) + return + if(!ismob(loc)) + CRASH("[src] was still registered to listen in on [source] but was not found to be on their mob.") + to_chat(loc, span_warning("You stop playing the harmonica to talk...")) + song.playing = FALSE /datum/action/item_action/instrument name = "Use Instrument" diff --git a/code/modules/instruments/piano_synth.dm b/code/modules/instruments/piano_synth.dm index 71d0d96ef560dfc..8e107d494c779f8 100644 --- a/code/modules/instruments/piano_synth.dm +++ b/code/modules/instruments/piano_synth.dm @@ -148,7 +148,7 @@ stopped_playing.set_output(COMPONENT_SIGNAL) /obj/item/circuit_component/synth/proc/import_song() - synth.song.ParseSong(song.value) + synth.song.ParseSong(new_song = song.value) /obj/item/circuit_component/synth/proc/set_repetitions() synth.song.set_repeats(repetitions.value) @@ -169,7 +169,9 @@ synth.song.note_shift = clamp(note_shift.value, synth.song.note_shift_min, synth.song.note_shift_max) /obj/item/circuit_component/synth/proc/set_sustain_mode() - synth.song.sustain_mode = SSinstruments.note_sustain_modes[sustain_mode.value] + if(!(sustain_mode.value in SSinstruments.note_sustain_modes)) + return + synth.song.sustain_mode = sustain_mode.value /obj/item/circuit_component/synth/proc/set_sustain_value() switch(synth.song.sustain_mode) diff --git a/code/modules/instruments/songs/_song.dm b/code/modules/instruments/songs/_song.dm index 68039df21468ee3..fb0e4f087449a35 100644 --- a/code/modules/instruments/songs/_song.dm +++ b/code/modules/instruments/songs/_song.dm @@ -23,11 +23,6 @@ /// Are we currently playing? var/playing = FALSE - /// Are we currently editing? - var/editing = TRUE - /// Is the help screen open? - var/help = FALSE - /// Repeats left var/repeat = 0 /// Maximum times we can repeat @@ -107,7 +102,6 @@ var/note_shift = 0 var/note_shift_min = -100 var/note_shift_max = 100 - var/can_noteshift = TRUE /// The kind of sustain we're using var/sustain_mode = SUSTAIN_LINEAR /// When a note is considered dead if it is below this in volume @@ -129,7 +123,7 @@ tempo = sanitize_tempo(tempo, TRUE) src.parent = parent if(instrument_ids) - allowed_instrument_ids = islist(instrument_ids)? instrument_ids : list(instrument_ids) + allowed_instrument_ids = islist(instrument_ids) ? instrument_ids : list(instrument_ids) if(length(allowed_instrument_ids)) set_instrument(allowed_instrument_ids[1]) hearing_mobs = list() @@ -217,8 +211,6 @@ delay_by = 0 current_chord = 1 music_player = user - if(ismob(music_player)) - updateDialog(music_player) START_PROCESSING(SSinstruments, src) /** @@ -328,12 +320,6 @@ /datum/song/proc/set_bpm(bpm) tempo = sanitize_tempo(600 / bpm) -/** - * Updates the window for our users. Override down the line. - */ -/datum/song/proc/updateDialog(mob/user) - ui_interact(user) - /datum/song/process(wait) if(!playing) return PROCESS_KILL @@ -359,7 +345,6 @@ /datum/song/proc/set_volume(volume) src.volume = clamp(round(volume, 1), max(0, min_volume), min(100, max_volume)) update_sustain() - updateDialog() /** * Setter for setting how low the volume has to get before a note is considered "dead" and dropped @@ -367,7 +352,6 @@ /datum/song/proc/set_dropoff_volume(volume) sustain_dropoff_volume = clamp(round(volume, 0.01), INSTRUMENT_MIN_SUSTAIN_DROPOFF, 100) update_sustain() - updateDialog() /** * Setter for setting exponential falloff factor. @@ -375,7 +359,6 @@ /datum/song/proc/set_exponential_drop_rate(drop) sustain_exponential_dropoff = clamp(round(drop, 0.00001), INSTRUMENT_EXP_FALLOFF_MIN, INSTRUMENT_EXP_FALLOFF_MAX) update_sustain() - updateDialog() /** * Setter for setting linear falloff duration. @@ -383,7 +366,6 @@ /datum/song/proc/set_linear_falloff_duration(duration) sustain_linear_duration = clamp(round(duration * 10, world.tick_lag), world.tick_lag, INSTRUMENT_MAX_TOTAL_SUSTAIN) update_sustain() - updateDialog() /datum/song/vv_edit_var(var_name, var_value) . = ..() @@ -401,9 +383,6 @@ // subtype for handheld instruments, like violin /datum/song/handheld -/datum/song/handheld/updateDialog(mob/user) - parent.ui_interact(user || usr) - /datum/song/handheld/should_stop_playing(atom/player) . = ..() if(. == STOP_PLAYING || . == IGNORE_INSTRUMENT_CHECKS) @@ -414,9 +393,6 @@ // subtype for stationary structures, like pianos /datum/song/stationary -/datum/song/stationary/updateDialog(mob/user) - parent.ui_interact(user || usr) - /datum/song/stationary/should_stop_playing(atom/player) . = ..() if(. == STOP_PLAYING || . == IGNORE_INSTRUMENT_CHECKS) diff --git a/code/modules/instruments/songs/editor.dm b/code/modules/instruments/songs/editor.dm index 58c0562c9b04d1a..927e03d055dcf27 100644 --- a/code/modules/instruments/songs/editor.dm +++ b/code/modules/instruments/songs/editor.dm @@ -1,96 +1,189 @@ -/** - * Returns the HTML for the status UI for this song datum. - */ -/datum/song/proc/instrument_status_ui() - . = list() - . += "
" - . += "Current instrument: " - if(!using_instrument) - . += "[span_danger("No instrument loaded!")]
" - else - . += "[using_instrument.name]
" - . += "Playback Settings:
" - if(can_noteshift) - . += "Note Shift/Note Transpose: [note_shift] keys / [round(note_shift / 12, 0.01)] octaves
" - var/smt - var/modetext = "" +/datum/song/ui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) + if (!ui) + ui = new(user, src, "InstrumentEditor", parent.name) + ui.open() + +/datum/song/ui_host(mob/user) + return parent + +/datum/song/ui_data(mob/user) + var/list/data = ..() + data["using_instrument"] = using_instrument?.name || "No instrument loaded!" + data["note_shift"] = note_shift + data["octaves"] = round(note_shift / 12, 0.01) + data["sustain_mode"] = sustain_mode switch(sustain_mode) if(SUSTAIN_LINEAR) - smt = "Linear" - modetext = "Linear Sustain Duration: [sustain_linear_duration / 10] seconds
" + data["sustain_mode_button"] = "Linear Sustain Duration (in seconds)" + data["sustain_mode_duration"] = sustain_linear_duration / 10 + data["sustain_mode_min"] = INSTRUMENT_MIN_TOTAL_SUSTAIN + data["sustain_mode_max"] = INSTRUMENT_MAX_TOTAL_SUSTAIN if(SUSTAIN_EXPONENTIAL) - smt = "Exponential" - modetext = "Exponential Falloff Factor: [sustain_exponential_dropoff]% per decisecond
" - . += "Sustain Mode: [smt]
" - . += modetext - . += using_instrument?.ready()? "Status: Ready
" : "Status: !Instrument Definition Error!
" - . += "Instrument Type: [legacy? "Legacy" : "Synthesized"]
" - . += "Volume: [volume]
" - . += "Volume Dropoff Threshold: [sustain_dropoff_volume]
" - . += "Sustain indefinitely last held note: [full_sustain_held_note? "Enabled" : "Disabled"].
" - . += "
" - -/datum/song/ui_interact(mob/user) - var/list/dat = list() - - dat += instrument_status_ui() - - if(lines.len > 0) - dat += "

Playback

" - if(!playing) - dat += "Play Stop

" - dat += "Repeat Song: " - dat += repeat > 0 ? "--" : "--" - dat += " [repeat] times " - dat += repeat < max_repeats ? "++" : "++" - dat += "
" - else - dat += "Play Stop
" - dat += "Repeats left: [repeat]
" - if(!editing) - dat += "
Show Editor
" - else - dat += "

Editing

" - dat += "Hide Editor" - dat += " Start a New Song" - dat += " Import a Song

" - var/bpm = round(600 / tempo) - dat += "Tempo: - [bpm] BPM +

" - var/linecount = 0 - for(var/line in lines) - linecount += 1 - dat += "Line [linecount]: Edit X [line]
" - dat += "Add Line

" - if(help) - dat += "Hide Help
" - dat += {" - Lines are a series of chords, separated by commas (,), each with notes separated by hyphens (-).
- Every note in a chord will play together, with chord timed by the tempo.
-
- Notes are played by the names of the note, and optionally, the accidental, and/or the octave number.
- By default, every note is natural and in octave 3. Defining otherwise is remembered for each note.
- Example: C,D,E,F,G,A,B will play a C major scale.
- After a note has an accidental placed, it will be remembered: C,C4,C,C3 is C3,C4,C4,C3
- Chords can be played simply by seperating each note with a hyphon: A-C#,Cn-E,E-G#,Gn-B
- A pause may be denoted by an empty chord: C,E,,C,G
- To make a chord be a different time, end it with /x, where the chord length will be length
- defined by tempo / x: C,G/2,E/4
- Combined, an example is: E-E4/4,F#/2,G#/8,B/8,E3-E4/4 -
- Lines may be up to [MUSIC_MAXLINECHARS] characters.
- A song may only contain up to [MUSIC_MAXLINES] lines.
- "} - else - dat += "Show Help
" - - var/datum/browser/popup = new(user, "instrument", parent?.name || "instrument", 700, 500) - popup.set_content(dat.Join("")) - popup.open() + data["sustain_mode_button"] = "Exponential Falloff Factor (% per decisecond)" + data["sustain_mode_duration"] = sustain_exponential_dropoff + data["sustain_mode_min"] = INSTRUMENT_EXP_FALLOFF_MIN + data["sustain_mode_max"] = INSTRUMENT_EXP_FALLOFF_MAX + data["instrument_ready"] = using_instrument?.ready() + data["volume"] = volume + data["volume_dropoff_threshold"] = sustain_dropoff_volume + data["sustain_indefinitely"] = full_sustain_held_note + data["playing"] = playing + data["repeat"] = repeat + data["bpm"] = round(60 SECONDS / tempo) + data["lines"] = list() + var/linecount + for(var/line in lines) + linecount++ + data["lines"] += list(list( + "line_count" = linecount, + "line_text" = line, + )) + return data + +/datum/song/ui_static_data(mob/user) + var/list/data = ..() + data["can_switch_instrument"] = (length(allowed_instrument_ids) > 1) + data["possible_instruments"] = list() + for(var/instrument in allowed_instrument_ids) + UNTYPED_LIST_ADD(data["possible_instruments"], list("name" = SSinstruments.instrument_data[instrument], "id" = instrument)) + data["sustain_modes"] = SSinstruments.note_sustain_modes + data["max_repeats"] = max_repeats + data["min_volume"] = min_volume + data["max_volume"] = max_volume + data["note_shift_min"] = note_shift_min + data["note_shift_max"] = note_shift_max + data["max_line_chars"] = MUSIC_MAXLINECHARS + data["max_lines"] = MUSIC_MAXLINES + return data + +/datum/song/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state) + . = ..() + var/mob/user = ui.user + if(!istype(user)) + return FALSE + + switch(action) + //SETTINGS + if("play_music") + if(!playing) + INVOKE_ASYNC(src, PROC_REF(start_playing), user) + else + stop_playing() + return TRUE + if("change_instrument") + var/new_instrument = params["new_instrument"] + //only one instrument, so no need to bother changing it. + if(!length(allowed_instrument_ids)) + return FALSE + if(!(new_instrument in allowed_instrument_ids)) + return FALSE + set_instrument(new_instrument) + return TRUE + if("tempo") + var/move_direction = params["tempo_change"] + var/tempo_diff + if(move_direction == "increase_speed") + tempo_diff = world.tick_lag + else + tempo_diff = -world.tick_lag + tempo = sanitize_tempo(tempo + tempo_diff) + return TRUE + + //SONG MAKING + if("import_song") + var/song_text = "" + do + song_text = tgui_input_text(user, "Please paste the entire song, formatted:", name, max_length = (MUSIC_MAXLINES * MUSIC_MAXLINECHARS)) + if(!in_range(parent, user)) + return + if(length_char(song_text) >= MUSIC_MAXLINES * MUSIC_MAXLINECHARS) + var/should_continue = tgui_alert(user, "Your message is too long! Would you like to continue editing it?", "Warning", list("Yes", "No")) + if(should_continue != "Yes") + break + while(length_char(song_text) > MUSIC_MAXLINES * MUSIC_MAXLINECHARS) + ParseSong(user, song_text) + return TRUE + if("start_new_song") + name = "" + lines = new() + tempo = sanitize_tempo(5) // default 120 BPM + return TRUE + if("add_new_line") + var/newline = tgui_input_text(user, "Enter your line", parent.name) + if(!newline || !in_range(parent, user)) + return + if(lines.len > MUSIC_MAXLINES) + return + if(length(newline) > MUSIC_MAXLINECHARS) + newline = copytext(newline, 1, MUSIC_MAXLINECHARS) + lines.Add(newline) + if("delete_line") + var/line_to_delete = params["line_deleted"] + if(line_to_delete > lines.len || line_to_delete < 1) + return FALSE + lines.Cut(line_to_delete, line_to_delete + 1) + return TRUE + if("modify_line") + var/line_to_edit = params["line_editing"] + if(line_to_edit > lines.len || line_to_edit < 1) + return FALSE + var/new_line_text = tgui_input_text(user, "Enter your line ", parent.name, lines[line_to_edit], MUSIC_MAXLINECHARS) + if(isnull(new_line_text) || !in_range(parent, user)) + return FALSE + lines[line_to_edit] = new_line_text + return TRUE + + //MODE STUFF + if("set_sustain_mode") + var/new_mode = params["new_mode"] + if(isnull(new_mode) || !(new_mode in SSinstruments.note_sustain_modes)) + return FALSE + sustain_mode = new_mode + return TRUE + if("set_note_shift") + var/amount = params["amount"] + if(!isnum(amount)) + return FALSE + note_shift = clamp(amount, note_shift_min, note_shift_max) + return TRUE + if("set_volume") + var/new_volume = params["amount"] + if(!isnum(new_volume)) + return FALSE + set_volume(new_volume) + return TRUE + if("set_dropoff_volume") + var/dropoff_threshold = params["amount"] + if(!isnum(dropoff_threshold)) + return FALSE + set_dropoff_volume(dropoff_threshold) + return TRUE + if("toggle_sustain_hold_indefinitely") + full_sustain_held_note = !full_sustain_held_note + return TRUE + if("set_repeat_amount") + if(playing) + return + var/repeat_amount = params["amount"] + if(!isnum(repeat_amount)) + return FALSE + set_repeats(repeat_amount) + return TRUE + if("edit_sustain_mode") + var/sustain_amount = params["amount"] + if(isnull(sustain_amount) || !isnum(sustain_amount)) + return + switch(sustain_mode) + if(SUSTAIN_LINEAR) + set_linear_falloff_duration(sustain_amount) + if(SUSTAIN_EXPONENTIAL) + set_exponential_drop_rate(sustain_amount) /** * Parses a song the user has input into lines and stores them. */ -/datum/song/proc/ParseSong(new_song) +/datum/song/proc/ParseSong(mob/user, new_song) set waitfor = FALSE //split into lines lines = islist(new_song) ? new_song : splittext(new_song, "\n") @@ -103,142 +196,14 @@ else tempo = sanitize_tempo(5) // default 120 BPM if(lines.len > MUSIC_MAXLINES) - to_chat(usr, "Too many lines!") + if(user) + to_chat(user, "Too many lines!") lines.Cut(MUSIC_MAXLINES + 1) var/linenum = 1 for(var/l in lines) if(length_char(l) > MUSIC_MAXLINECHARS) - to_chat(usr, "Line [linenum] too long!") + if(user) + to_chat(user, "Line [linenum] too long!") lines.Remove(l) else linenum++ - updateDialog(usr) // make sure updates when complete - -/datum/song/Topic(href, href_list) - if(!usr.can_perform_action(parent, ALLOW_RESTING)) - usr << browse(null, "window=instrument") - usr.unset_machine() - return - - parent.add_fingerprint(usr) - - if(href_list["newsong"]) - lines = new() - tempo = sanitize_tempo(5) // default 120 BPM - name = "" - - else if(href_list["import"]) - var/t = "" - do - t = html_encode(input(usr, "Please paste the entire song, formatted:", name, t) as message) - if(!in_range(parent, usr)) - return - - if(length_char(t) >= MUSIC_MAXLINES * MUSIC_MAXLINECHARS) - var/cont = tgui_alert(usr, "Your message is too long! Would you like to continue editing it?", "Warning", list("Yes", "No")) - if(cont != "Yes") - break - while(length_char(t) > MUSIC_MAXLINES * MUSIC_MAXLINECHARS) - ParseSong(t) - - else if(href_list["help"]) - help = text2num(href_list["help"]) - 1 - - else if(href_list["edit"]) - editing = text2num(href_list["edit"]) - 1 - - if(href_list["repeat"]) //Changing this from a toggle to a number of repeats to avoid infinite loops. - set_repeats(repeat + text2num(href_list["repeat"])) - - else if(href_list["tempo"]) - tempo = sanitize_tempo(tempo + text2num(href_list["tempo"])) - - else if(href_list["play"]) - INVOKE_ASYNC(src, PROC_REF(start_playing), usr) - - else if(href_list["newline"]) - var/newline = tgui_input_text(usr, "Enter your line ", parent.name) - if(!newline || !in_range(parent, usr)) - return - if(lines.len > MUSIC_MAXLINES) - return - if(length(newline) > MUSIC_MAXLINECHARS) - newline = copytext(newline, 1, MUSIC_MAXLINECHARS) - lines.Add(newline) - - else if(href_list["deleteline"]) - var/num = round(text2num(href_list["deleteline"])) - if(num > lines.len || num < 1) - return - lines.Cut(num, num+1) - - else if(href_list["modifyline"]) - var/num = round(text2num(href_list["modifyline"]),1) - var/content = tgui_input_text(usr, "Enter your line ", parent.name, lines[num], MUSIC_MAXLINECHARS) - if(!content || !in_range(parent, usr)) - return - if(num > lines.len || num < 1) - return - lines[num] = content - - else if(href_list["stop"]) - stop_playing() - - else if(href_list["setlinearfalloff"]) - var/amount = tgui_input_number(usr, "Set linear sustain duration in seconds", "Linear Sustain Duration", 0.1, INSTRUMENT_MAX_TOTAL_SUSTAIN, 0.1, round_value = FALSE) - if(!isnull(amount)) - set_linear_falloff_duration(amount) - - else if(href_list["setexpfalloff"]) - var/amount = tgui_input_number(usr, "Set exponential sustain factor", "Exponential sustain factor", INSTRUMENT_EXP_FALLOFF_MIN, INSTRUMENT_EXP_FALLOFF_MAX, INSTRUMENT_EXP_FALLOFF_MIN, round_value = FALSE) - if(!isnull(amount)) - set_exponential_drop_rate(amount) - - else if(href_list["setvolume"]) - var/amount = tgui_input_number(usr, "Set volume", "Volume", 1, 75, 1) - if(!isnull(amount)) - set_volume(amount) - - else if(href_list["setdropoffvolume"]) - var/amount = tgui_input_number(usr, "Set dropoff threshold", "Dropoff Volume", max_value = 100) - if(!isnull(amount)) - set_dropoff_volume(amount) - - else if(href_list["switchinstrument"]) - if(!length(allowed_instrument_ids)) - return - else if(length(allowed_instrument_ids) == 1) - set_instrument(allowed_instrument_ids[1]) - return - var/list/categories = list() - for(var/i in allowed_instrument_ids) - var/datum/instrument/I = SSinstruments.get_instrument(i) - if(I) - LAZYSET(categories[I.category || "ERROR CATEGORY"], I.name, I.id) - var/cat = tgui_input_list(usr, "Select Category", "Instrument Category", categories) - if(isnull(cat)) - return - var/list/instruments = categories[cat] - var/choice = tgui_input_list(usr, "Select Instrument", "Instrument Selection", instruments) - if(isnull(choice)) - return - if(isnull(instruments[choice])) - return - choice = instruments[choice] //get id - if(choice) - set_instrument(choice) - - else if(href_list["setnoteshift"]) - var/amount = input(usr, "Set note shift", "Note Shift") as null|num - if(!isnull(amount)) - note_shift = clamp(amount, note_shift_min, note_shift_max) - - else if(href_list["setsustainmode"]) - var/choice = tgui_input_list(usr, "Choose a sustain mode", "Sustain Mode", SSinstruments.note_sustain_modes) - if(choice) - sustain_mode = SSinstruments.note_sustain_modes[choice] - - else if(href_list["togglesustainhold"]) - full_sustain_held_note = !full_sustain_held_note - - updateDialog(usr) diff --git a/code/modules/instruments/songs/play_synthesized.dm b/code/modules/instruments/songs/play_synthesized.dm index 3b5f3d5b9f42caa..836c2fdd86bceed 100644 --- a/code/modules/instruments/songs/play_synthesized.dm +++ b/code/modules/instruments/songs/play_synthesized.dm @@ -43,8 +43,7 @@ * Does a hearing check if enough time has passed. */ /datum/song/proc/playkey_synth(key, atom/player) - if(can_noteshift) - key = clamp(key + note_shift, key_min, key_max) + key = clamp(key + note_shift, key_min, key_max) if((world.time - MUSICIAN_HEARCHECK_MINDELAY) > last_hearcheck) do_hearcheck() var/datum/instrument_key/K = using_instrument.samples[num2text(key)] //See how fucking easy it is to make a number text? You don't need a complicated 9 line proc! diff --git a/code/modules/jobs/departments/departments.dm b/code/modules/jobs/departments/departments.dm index db45899b5c4a25e..9f2776bad0e0a98 100644 --- a/code/modules/jobs/departments/departments.dm +++ b/code/modules/jobs/departments/departments.dm @@ -25,6 +25,16 @@ department_jobs += job job.departments_bitflags |= department_bitflags +/// Handles removing jobs from the department and removing job bitflags. +/datum/job_department/proc/remove_job(datum/job/job_type) + for(var/datum/job/job_datum as anything in department_jobs) + if(job_datum.type == job_type) + department_jobs -= job_datum + job_datum.departments_bitflags -= department_bitflags + job_datum.job_flags &= ~JOB_NEW_PLAYER_JOINABLE + job_datum.spawn_positions = 0 + job_datum.total_positions = 0 + /// Returns a nation name for this department. /datum/job_department/proc/generate_nation_name() var/static/list/nation_suffixes = list("stan", "topia", "land", "nia", "ca", "tova", "dor", "ador", "tia", "sia", "ano", "tica", "tide", "cis", "marea", "co", "taoide", "slavia", "stotzka") diff --git a/code/modules/jobs/job_types/station_trait/veteran_advisor.dm b/code/modules/jobs/job_types/station_trait/veteran_advisor.dm new file mode 100644 index 000000000000000..87ad65c2c7a713f --- /dev/null +++ b/code/modules/jobs/job_types/station_trait/veteran_advisor.dm @@ -0,0 +1,76 @@ +/datum/job/veteran_advisor + title = JOB_VETERAN_ADVISOR + description = "Advise HoS, and Captain on matters of Security. Train green Officers. \ + Lay back in your wheelchair and say \"I told you\" to the HoS when all of the station collapses." + auto_deadmin_role_flags = DEADMIN_POSITION_SECURITY + department_head = list(JOB_HEAD_OF_SECURITY) + faction = FACTION_STATION + total_positions = 0 + spawn_positions = 0 + supervisors = SUPERVISOR_HOS + minimal_player_age = 7 + exp_requirements = 6000 //100 HOURS! We want really hard boiled people + exp_required_type = EXP_TYPE_CREW + exp_required_type_department = EXP_TYPE_SECURITY + exp_granted_type = EXP_TYPE_CREW + config_tag = "VETERAN_ADVISOR" + + outfit = /datum/outfit/job/veteran_advisor + plasmaman_outfit = /datum/outfit/plasmaman/security + + paycheck = PAYCHECK_CREW + paycheck_department = ACCOUNT_SEC + + liver_traits = list(TRAIT_LAW_ENFORCEMENT_METABOLISM) + + display_order = JOB_DISPLAY_ORDER_VETERAN_ADVISOR + departments_list = list(/datum/job_department/security) + + family_heirlooms = list(/obj/item/plaque) + + mail_goodies = list( + /obj/item/clothing/accessory/medal/conduct = 1, + /obj/item/instrument/trumpet = 5, + /obj/item/storage/fancy/cigarettes/cigars = 10, + ) + rpg_title = "Royal Advisor" + allow_bureaucratic_error = FALSE + job_flags = STATION_JOB_FLAGS | STATION_TRAIT_JOB_FLAGS + +/datum/job/veteran_advisor/get_roundstart_spawn_point() //Spawning at Brig where Officers spawn + if (length(GLOB.start_landmarks_list["Security Officer"])) + return pick(GLOB.start_landmarks_list["Security Officer"]) + return ..() + +/datum/job/veteran_advisor/after_spawn(mob/living/spawned, client/player_client) + . = ..() + var/mob/living/carbon/veteran = spawned + spawned.add_quirk(/datum/quirk/paraplegic) //Even in 2300s veterans are getting it bad + if(veteran) + veteran.gain_trauma(/datum/brain_trauma/special/ptsd) //War, war never changes... + +/datum/outfit/job/veteran_advisor + name = "Veteran Security Advisor" + jobtype = /datum/job/veteran_advisor + + id_trim = /datum/id_trim/job/veteran_advisor + backpack_contents = list( + /obj/item/modular_computer/pda/veteran_advisor = 1, + /obj/item/storage/fancy/cigarettes/cigars = 1, + /obj/item/lighter = 1, + /obj/item/clothing/accessory/medal/bronze_heart = 1, + ) + + uniform = /obj/item/clothing/under/rank/security/officer/formal + head = /obj/item/clothing/head/soft/veteran + mask = /obj/item/clothing/mask/cigarette/cigar + suit = /obj/item/clothing/suit/jacket/trenchcoat + belt = /obj/item/storage/belt/holster/detective/full/ert //M1911 pistol + ears = /obj/item/radio/headset/heads/hos/advisor + glasses = /obj/item/clothing/glasses/eyepatch + shoes = /obj/item/clothing/shoes/jackboots + l_pocket = /obj/item/coin/antagtoken + r_pocket = /obj/item/melee/baton/telescopic + r_hand = /obj/item/cane + + implants = list(/obj/item/implant/mindshield) diff --git a/code/modules/library/bibles.dm b/code/modules/library/bibles.dm index 6a5d1b1d5c4e451..656c90d77bbda1b 100644 --- a/code/modules/library/bibles.dm +++ b/code/modules/library/bibles.dm @@ -77,30 +77,24 @@ GLOBAL_LIST_INIT(bibleitemstates, list( unique = TRUE /// Deity this bible is related to var/deity_name = "Space Jesus" - /// Component which catches bullets for us - var/datum/component/bullet_catcher /obj/item/book/bible/Initialize(mapload) . = ..() AddComponent(/datum/component/anti_magic, MAGIC_RESISTANCE_HOLY) - bullet_catcher = AddComponent(\ + AddComponent(\ /datum/component/bullet_intercepting,\ active_slots = ITEM_SLOT_SUITSTORE,\ on_intercepted = CALLBACK(src, PROC_REF(on_intercepted_bullet)),\ + block_charges = 1,\ ) - carve_out() - -/obj/item/book/bible/Destroy(force) - QDEL_NULL(bullet_catcher) - return ..() /// Destroy the bible when it's shot by a bullet /obj/item/book/bible/proc/on_intercepted_bullet(mob/living/victim, obj/projectile/bullet) victim.add_mood_event("blessing", /datum/mood_event/blessing) playsound(victim, 'sound/magic/magic_block_holy.ogg', 50, TRUE) - victim.visible_message(span_warning("\The [src] takes \the [bullet] in [victim]'s place!")) + victim.visible_message(span_warning("[src] takes [bullet] in [victim]'s place!")) var/obj/structure/fluff/paper/stack/pages = new(get_turf(src)) - pages.dir = pick(GLOB.alldirs) + pages.setDir(pick(GLOB.alldirs)) name = "punctured bible" desc = "A memento of good luck, or perhaps divine intervention?" icon_state = "shot" @@ -108,7 +102,6 @@ GLOBAL_LIST_INIT(bibleitemstates, list( GLOB.bible_icon_state = "shot" // New symbol of your religion if you hadn't picked one atom_storage?.remove_all(get_turf(src)) QDEL_NULL(atom_storage) - QDEL_NULL(bullet_catcher) /obj/item/book/bible/examine(mob/user) . = ..() @@ -345,6 +338,7 @@ GLOBAL_LIST_INIT(bibleitemstates, list( /obj/item/book/bible/booze/Initialize(mapload) . = ..() + carve_out() new /obj/item/reagent_containers/cup/glass/bottle/whiskey(src) /obj/item/book/bible/syndicate diff --git a/code/modules/lighting/lighting_area.dm b/code/modules/lighting/lighting_area.dm index 84170b6964fce97..ea31f61c8becd4d 100644 --- a/code/modules/lighting/lighting_area.dm +++ b/code/modules/lighting/lighting_area.dm @@ -51,7 +51,7 @@ UnregisterSignal(SSdcs, COMSIG_STARLIGHT_COLOR_CHANGED) var/list/z_offsets = SSmapping.z_level_to_plane_offset if(length(lighting_effects) > 1) - for(var/area_zlevel as anything in 1 to get_highest_zlevel()) + for(var/area_zlevel in 1 to get_highest_zlevel()) if(z_offsets[area_zlevel]) for(var/turf/T as anything in get_turfs_by_zlevel(area_zlevel)) T.cut_overlay(lighting_effects[z_offsets[T.z] + 1]) diff --git a/code/modules/logging/categories/log_category_misc.dm b/code/modules/logging/categories/log_category_misc.dm index 2d200e63aa27afd..4d69c7cb35bdd49 100644 --- a/code/modules/logging/categories/log_category_misc.dm +++ b/code/modules/logging/categories/log_category_misc.dm @@ -65,3 +65,6 @@ category = LOG_CATEGORY_QDEL // We want this human readable so it's easy to see at a glance entry_flags = ENTRY_USE_DATA_W_READABLE + +/datum/log_category/cave_generation + category = LOG_CATEGORY_CAVE_GENERATION diff --git a/code/modules/mapfluff/ruins/objects_and_mobs/museum.dm b/code/modules/mapfluff/ruins/objects_and_mobs/museum.dm index 20210d56cc95c5d..8a2949f98935e3f 100644 --- a/code/modules/mapfluff/ruins/objects_and_mobs/museum.dm +++ b/code/modules/mapfluff/ruins/objects_and_mobs/museum.dm @@ -33,6 +33,10 @@ new_replica.name = "[appearance_object.name][obvious_replica ? " replica" : ""]" new_replica.desc = "[appearance_object.desc][obvious_replica ? " ..except this one is a replica.": ""]" + + new_replica.pixel_y = pixel_y + new_replica.pixel_x = pixel_x + qdel(appearance_object) qdel(src) return INITIALIZE_HINT_QDEL @@ -129,3 +133,68 @@
sometimes i can catch them moving

we should have never come here"} + +/obj/item/paper/fluff/museum/chefs_ultimatum + name = "old note" + default_raw_text = {"I messed it up big times. +
I broke the button and now I'm stuck. +
Anyway, I don't have the key on me. I flushed it down. +
Hell knows where it's now, shit's like all linked together here."} + +/obj/item/paper/fluff/museum/numbers_on_walls + name = "reprimanding note" + default_raw_text = "Please refraim from writing the pass all over the place. I know you've the memory of a goldfish, but, like, just put it on a piece of paper, no?" + +/obj/effect/mob_spawn/corpse/human/skeleton/museum_chef + name = "Dead Museum Cafeteria Chef" + mob_name = "Nameless Chef" + outfit = /datum/outfit/museum_chef + +/datum/outfit/museum_chef + name = "Dead Museum Cafeteria Chef" + uniform = /obj/item/clothing/under/color/green + suit = /obj/item/clothing/suit/toggle/chef + head = /obj/item/clothing/head/utility/chefhat + shoes = /obj/item/clothing/shoes/laceup + mask = /obj/item/clothing/mask/fakemoustache/italian + +/obj/machinery/vending/hotdog/museum + obj_flags = parent_type::obj_flags|NO_DECONSTRUCTION + onstation_override = TRUE + +#define CAFE_KEYCARD_TOILETS "museum_cafe_key_toilets" + +///Do not place these beyond the cafeteria shutters, or you might lock people out of reaching it. +/obj/structure/toilet/museum + +/obj/structure/toilet/museum/Initialize(mapload) + . = ..() + if(mapload) + SSqueuelinks.add_to_queue(src, CAFE_KEYCARD_TOILETS) + +/obj/item/keycard/cafeteria + name = "museum cafeteria keycard" + color = COLOR_OLIVE + puzzle_id = "museum_cafeteria" + desc = "The key to the cafeteria, as the name implies." + +/obj/item/keycard/cafeteria/Initialize(mapload) + . = ..() + if(mapload) + SSqueuelinks.add_to_queue(src, CAFE_KEYCARD_TOILETS) + return INITIALIZE_HINT_LATELOAD + +/obj/item/keycard/cafeteria/LateInitialize() + . = ..() + if(SSqueuelinks.queues[CAFE_KEYCARD_TOILETS]) + SSqueuelinks.pop_link(CAFE_KEYCARD_TOILETS) + +/obj/item/keycard/cafeteria/MatchedLinks(id, partners) + if(id != CAFE_KEYCARD_TOILETS) + return ..() + var/obj/structure/toilet/destination = pick(partners) + forceMove(destination) + destination.w_items += w_class + destination.contents += src + +#undef CAFE_KEYCARD_TOILETS diff --git a/code/modules/mapfluff/ruins/spaceruin_code/meatderelict.dm b/code/modules/mapfluff/ruins/spaceruin_code/meatderelict.dm index 5647b5aca2382a8..0db718e399bf6d4 100644 --- a/code/modules/mapfluff/ruins/spaceruin_code/meatderelict.dm +++ b/code/modules/mapfluff/ruins/spaceruin_code/meatderelict.dm @@ -76,12 +76,12 @@ SEND_SIGNAL(src, COMSIG_PUZZLE_COMPLETED) qdel(src) -/obj/machinery/puzzle_button/meatderelict +/obj/machinery/puzzle/button/meatderelict name = "lockdown panel" desc = "A panel that controls the lockdown of this outpost." id = "md_prevault" -/obj/machinery/puzzle_button/meatderelict/open_doors() +/obj/machinery/puzzle/button/meatderelict/on_puzzle_complete() . = ..() playsound(src, 'sound/effects/alert.ogg', 100, TRUE) visible_message(span_warning("[src] lets out an alarm as the lockdown is lifted!")) @@ -121,7 +121,7 @@ /obj/lightning_thrower/Initialize(mapload) . = ..() - START_PROCESSING(SSprocessing, src) + START_PROCESSING(SSprocessing, src) /obj/lightning_thrower/Destroy() . = ..() diff --git a/code/modules/meteors/meteor_types.dm b/code/modules/meteors/meteor_types.dm index c59a153b02238ac..2b37a55aaa4137e 100644 --- a/code/modules/meteors/meteor_types.dm +++ b/code/modules/meteors/meteor_types.dm @@ -257,15 +257,17 @@ desc = "An irradiated chunk of space rock. You could probably stop and appreciate its incandescent green glow, if it weren't moving so fast." icon_state = "glowing" heavy = TRUE + hits = 9 meteordrop = list(/obj/item/stack/ore/uranium) - threat = 15 + threat = 35 signature = "radiation" /obj/effect/meteor/irradiated/meteor_effect() ..() - explosion(src, light_impact_range = 4, flash_range = 3, adminlog = FALSE) - new /obj/effect/decal/cleanable/greenglow(get_turf(src)) - radiation_pulse(src, max_range = 3, threshold = RAD_MEDIUM_INSULATION, chance = 80) + explosion(src, heavy_impact_range = 1, light_impact_range = 3, flash_range = 6, adminlog = FALSE) + for(var/turf/open/floor/surviving_ground in range(2, get_turf(src))) + if(prob(70)) + new /obj/effect/decal/cleanable/greenglow/radioactive(get_turf(surviving_ground)) //Cluster meteor /obj/effect/meteor/cluster diff --git a/code/modules/meteors/meteor_waves.dm b/code/modules/meteors/meteor_waves.dm index 7d832d53713372f..5edaed4c867ee30 100644 --- a/code/modules/meteors/meteor_waves.dm +++ b/code/modules/meteors/meteor_waves.dm @@ -5,14 +5,14 @@ GLOBAL_VAR_INIT(meteor_wave_delay, 625) //minimum wait between waves in tenths o //Meteors probability of spawning during a given wave GLOBAL_LIST_INIT(meteors_normal, list(/obj/effect/meteor/dust=3, /obj/effect/meteor/medium=8, /obj/effect/meteor/big=3, \ - /obj/effect/meteor/flaming=1, /obj/effect/meteor/irradiated=3, /obj/effect/meteor/carp=1, /obj/effect/meteor/bluespace=1, \ + /obj/effect/meteor/flaming=1, /obj/effect/meteor/irradiated=2, /obj/effect/meteor/carp=1, /obj/effect/meteor/bluespace=1, \ /obj/effect/meteor/banana=1, /obj/effect/meteor/emp = 1)) //for normal meteor event GLOBAL_LIST_INIT(meteors_threatening, list(/obj/effect/meteor/medium=4, /obj/effect/meteor/big=8, /obj/effect/meteor/flaming=3, \ /obj/effect/meteor/irradiated=3, /obj/effect/meteor/cluster=1, /obj/effect/meteor/carp=1, /obj/effect/meteor/bluespace=2, /obj/effect/meteor/emp = 2)) //for threatening meteor event GLOBAL_LIST_INIT(meteors_catastrophic, list(/obj/effect/meteor/medium=5, /obj/effect/meteor/big=75, \ - /obj/effect/meteor/flaming=10, /obj/effect/meteor/irradiated=10, /obj/effect/meteor/cluster=8, /obj/effect/meteor/tunguska=1, \ + /obj/effect/meteor/flaming=10, /obj/effect/meteor/irradiated=8, /obj/effect/meteor/cluster=8, /obj/effect/meteor/tunguska=1, \ /obj/effect/meteor/carp=2, /obj/effect/meteor/bluespace=10, /obj/effect/meteor/emp = 8)) //for catastrophic meteor event GLOBAL_LIST_INIT(meateors, list(/obj/effect/meteor/meaty=5, /obj/effect/meteor/meaty/xeno=1)) //for meaty ore event diff --git a/code/modules/mining/boulder_processing/_boulder_processing.dm b/code/modules/mining/boulder_processing/_boulder_processing.dm index d7d4be2557e109a..b79bfe36dc6d3ee 100644 --- a/code/modules/mining/boulder_processing/_boulder_processing.dm +++ b/code/modules/mining/boulder_processing/_boulder_processing.dm @@ -66,9 +66,9 @@ else if(istype(held_item, /obj/item/card/id) && points_held > 0) context[SCREENTIP_CONTEXT_LMB] = "Claim mining points" else if(held_item.tool_behaviour == TOOL_SCREWDRIVER) - context[SCREENTIP_CONTEXT_LMB] = "[panel_open ? "Close" : "Open"] Panel" + context[SCREENTIP_CONTEXT_LMB] = "[panel_open ? "Close" : "Open"] panel" else if(held_item.tool_behaviour == TOOL_WRENCH) - context[SCREENTIP_CONTEXT_LMB] = "[anchored ? "" : "Un"] Anchor" + context[SCREENTIP_CONTEXT_LMB] = "[anchored ? "Un" : ""]Anchor" else if(panel_open && held_item.tool_behaviour == TOOL_CROWBAR) context[SCREENTIP_CONTEXT_LMB] = "Deconstruct" @@ -96,37 +96,17 @@ /obj/machinery/bouldertech/update_icon_state() . = ..() var/suffix = "" - if(!anchored || !is_operational || (machine_stat & (BROKEN | NOPOWER)) || panel_open) + if(!anchored || panel_open || !is_operational || (machine_stat & (BROKEN | NOPOWER))) suffix = "-off" icon_state ="[initial(icon_state)][suffix]" -/obj/machinery/bouldertech/wrench_act(mob/living/user, obj/item/tool) - . = ITEM_INTERACT_BLOCKING - if(default_unfasten_wrench(user, tool, time = 1.5 SECONDS) == SUCCESSFUL_UNFASTEN) - if(anchored) - begin_processing() - else - end_processing() - update_appearance(UPDATE_ICON_STATE) - return ITEM_INTERACT_SUCCESS - -/obj/machinery/bouldertech/screwdriver_act(mob/living/user, obj/item/tool) - . = ITEM_INTERACT_BLOCKING - if(default_deconstruction_screwdriver(user, "[initial(icon_state)]-off", initial(icon_state), tool)) - update_appearance(UPDATE_ICON_STATE) - return ITEM_INTERACT_SUCCESS - -/obj/machinery/bouldertech/crowbar_act(mob/living/user, obj/item/tool) - . = ITEM_INTERACT_BLOCKING - if(default_deconstruction_crowbar(tool)) - return ITEM_INTERACT_SUCCESS - /obj/machinery/bouldertech/CanAllowThrough(atom/movable/mover, border_dir) if(!anchored) return FALSE if(istype(mover, /obj/item/boulder)) - var/obj/item/boulder/boulder = mover - return can_process_boulder(boulder) + return can_process_boulder(mover) + if(isgolem(mover)) + return can_process_golem(mover) return ..() /** @@ -140,7 +120,7 @@ SHOULD_BE_PURE(TRUE) //machine not operational - if(!anchored || panel_open || !is_operational || machine_stat & (BROKEN | NOPOWER)) + if(!anchored || panel_open || !is_operational || (machine_stat & (BROKEN | NOPOWER))) return FALSE //not a valid boulder @@ -168,6 +148,8 @@ * * obj/item/boulder/new_boulder - the boulder to accept */ /obj/machinery/bouldertech/proc/accept_boulder(obj/item/boulder/new_boulder) + PRIVATE_PROC(TRUE) + if(!can_process_boulder(new_boulder)) return FALSE @@ -177,13 +159,67 @@ return TRUE +/** + * Can we maim this golem + * Arguments + * + * * [rockman][mob/living/carbon/human] - the golem we are trying to main + */ +/obj/machinery/bouldertech/proc/can_process_golem(mob/living/carbon/human/rockman) + PRIVATE_PROC(TRUE) + SHOULD_BE_PURE(TRUE) + + //not operatinal + if(!anchored || panel_open || !is_operational || (machine_stat & (BROKEN | NOPOWER))) + return FALSE + + //still in cooldown + if(!COOLDOWN_FINISHED(src, accept_cooldown)) + return FALSE + + //not processable + if(!istype(rockman) || QDELETED(rockman) || rockman.body_position != LYING_DOWN) + return FALSE + + return TRUE + +/** + * Accepts a golem to be processed, mainly for memes + * Arguments + * + * * [rockman][mob/living/carbon/human] - the golem we are trying to main + */ +/obj/machinery/bouldertech/proc/accept_golem(mob/living/carbon/human/rockman) + PRIVATE_PROC(TRUE) + + if(!can_process_golem(rockman)) + return + + maim_golem(rockman) + use_power(active_power_usage * 1.5) + playsound(src, usage_sound, 50, TRUE, SHORT_RANGE_SOUND_EXTRARANGE) + + COOLDOWN_START(src, accept_cooldown, 3 SECONDS) + +/// What effects actually happens to a golem when it is "processed" +/obj/machinery/bouldertech/proc/maim_golem(mob/living/carbon/human/rockman) + PROTECTED_PROC(TRUE) + + Shake(duration = 1 SECONDS) + rockman.visible_message(span_warning("[rockman] is processed by [src]!"), span_userdanger("You get processed into bits by [src]!")) + rockman.investigate_log("was gibbed by [src] for being a golem", INVESTIGATE_DEATHS) + rockman.gib(DROP_ALL_REMAINS) + /obj/machinery/bouldertech/proc/on_entered(datum/source, atom/movable/atom_movable) SIGNAL_HANDLER - if(!can_process_boulder(atom_movable)) + if(istype(atom_movable, /obj/item/boulder)) + INVOKE_ASYNC(src, PROC_REF(accept_boulder), atom_movable) return - INVOKE_ASYNC(src, PROC_REF(accept_boulder), atom_movable) + if(isgolem(atom_movable)) + INVOKE_ASYNC(src, PROC_REF(accept_golem), atom_movable) + return /** * Looks for a boost to the machine's efficiency, and applies it if found. @@ -205,42 +241,61 @@ return FALSE -/obj/machinery/bouldertech/attackby(obj/item/attacking_item, mob/user, params) - if(panel_open) +/obj/machinery/bouldertech/item_interaction(mob/living/user, obj/item/tool, list/modifiers, is_right_clicking) + if(panel_open || user.combat_mode) return ..() - if(istype(attacking_item, /obj/item/boulder)) - . = TRUE - var/obj/item/boulder/my_boulder = attacking_item + if(istype(tool, /obj/item/boulder)) + var/obj/item/boulder/my_boulder = tool if(!accept_boulder(my_boulder)) balloon_alert_to_viewers("cannot accept!") - return + return ITEM_INTERACT_BLOCKING balloon_alert_to_viewers("accepted") - return + return ITEM_INTERACT_SUCCESS - if(istype(attacking_item, /obj/item/card/id)) - . = TRUE + if(istype(tool, /obj/item/card/id)) if(points_held <= 0) balloon_alert_to_viewers("no points to claim!") if(!COOLDOWN_FINISHED(src, sound_cooldown)) - return + return ITEM_INTERACT_BLOCKING COOLDOWN_START(src, sound_cooldown, 1.5 SECONDS) playsound(src, 'sound/machines/buzz-sigh.ogg', 30, FALSE) - return + return ITEM_INTERACT_BLOCKING - var/obj/item/card/id/id_card = attacking_item + var/obj/item/card/id/id_card = tool var/amount = tgui_input_number(user, "How many mining points do you wish to claim? ID Balance: [id_card.registered_account.mining_points], stored mining points: [points_held]", "Transfer Points", max_value = points_held, min_value = 0, round_value = 1) if(!amount) - return + return ITEM_INTERACT_BLOCKING if(amount > points_held) amount = points_held id_card.registered_account.mining_points += amount points_held = round(points_held - amount) to_chat(user, span_notice("You claim [amount] mining points from \the [src] to [id_card].")) - return + return ITEM_INTERACT_SUCCESS return ..() +/obj/machinery/bouldertech/wrench_act(mob/living/user, obj/item/tool) + . = ITEM_INTERACT_BLOCKING + if(default_unfasten_wrench(user, tool, time = 1.5 SECONDS) == SUCCESSFUL_UNFASTEN) + if(anchored) + begin_processing() + else + end_processing() + update_appearance(UPDATE_ICON_STATE) + return ITEM_INTERACT_SUCCESS + +/obj/machinery/bouldertech/screwdriver_act(mob/living/user, obj/item/tool) + . = ITEM_INTERACT_BLOCKING + if(default_deconstruction_screwdriver(user, "[initial(icon_state)]-off", initial(icon_state), tool)) + update_appearance(UPDATE_ICON_STATE) + return ITEM_INTERACT_SUCCESS + +/obj/machinery/bouldertech/crowbar_act(mob/living/user, obj/item/tool) + . = ITEM_INTERACT_BLOCKING + if(default_deconstruction_crowbar(tool)) + return ITEM_INTERACT_SUCCESS + /obj/machinery/bouldertech/attack_hand_secondary(mob/user, list/modifiers) . = ..() if(. == SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN || panel_open) @@ -266,15 +321,17 @@ * Accepts a boulder into the machinery, then converts it into minerals. * If the boulder can be fully processed by this machine, we take the materials, insert it into the silo, and destroy the boulder. * If the boulder has materials left, we make a copy of the boulder to hold the processable materials, take the processable parts, and eject the original boulder. - * @param chosen_boulder The boulder to being breaking down into minerals. + * Arguments + * + * * obj/item/boulder/chosen_boulder - The boulder to being breaking down into minerals. */ /obj/machinery/bouldertech/proc/breakdown_boulder(obj/item/boulder/chosen_boulder) PRIVATE_PROC(TRUE) if(QDELETED(chosen_boulder)) - return FALSE + return if(chosen_boulder.loc != src) - return FALSE + return //if boulders are kept inside because there is no space to eject them, then they could be reprocessed, lets avoid that if(!chosen_boulder.processed_by) @@ -301,7 +358,7 @@ if(istype(chosen_boulder, /obj/item/boulder/artifact)) points_held = round((points_held + MINER_POINT_MULTIPLIER) * MINING_POINT_MACHINE_MULTIPLIER) /// Artifacts give bonus points! chosen_boulder.break_apart() - return TRUE //We've processed all the materials in the boulder, so we can just destroy it in break_apart. + return//We've processed all the materials in the boulder, so we can just destroy it in break_apart. chosen_boulder.processed_by = src @@ -309,7 +366,7 @@ remove_boulder(chosen_boulder) /obj/machinery/bouldertech/process() - if(!anchored || panel_open || !is_operational || machine_stat & (BROKEN | NOPOWER)) + if(!anchored || panel_open || !is_operational || (machine_stat & (BROKEN | NOPOWER))) return var/boulders_found = FALSE diff --git a/code/modules/mining/boulder_processing/boulder.dm b/code/modules/mining/boulder_processing/boulder.dm index 0cc310eb170ed41..5c211c8b49a20dc 100644 --- a/code/modules/mining/boulder_processing/boulder.dm +++ b/code/modules/mining/boulder_processing/boulder.dm @@ -109,6 +109,7 @@ /obj/item/boulder/proc/manual_process(obj/item/weapon, mob/living/user, override_speed_multiplier, continued = FALSE) var/process_speed = 0 //Handle weapon conditions. + var/skill_modifier = user.mind?.get_skill_modifier(/datum/skill/mining, SKILL_SPEED_MODIFIER) || 1 if(weapon) if(HAS_TRAIT(weapon, TRAIT_INSTANTLY_PROCESSES_BOULDERS)) durability = 0 @@ -119,25 +120,24 @@ // Handle user conditions/override conditions. else if (override_speed_multiplier || HAS_TRAIT(user, TRAIT_BOULDER_BREAKER)) - if(user) - if(HAS_TRAIT(user, TRAIT_INSTANTLY_PROCESSES_BOULDERS)) - durability = 0 + if(HAS_TRAIT(user, TRAIT_INSTANTLY_PROCESSES_BOULDERS)) + durability = 0 else if(override_speed_multiplier) process_speed = override_speed_multiplier else process_speed = INATE_BOULDER_SPEED_MULTIPLIER playsound(src, 'sound/effects/rocktap1.ogg', 50) if(!continued) - to_chat(user, span_notice("You scrape away at \the [src]... speed is [process_speed].")) + to_chat(user, span_notice("You scrape away at \the [src]...")) else CRASH("No weapon, acceptable user, or override speed multiplier passed to manual_process()") if(durability > 0) - if(!do_after(user, (2 * process_speed SECONDS), target = src)) + if(!do_after(user, (2 * process_speed * skill_modifier SECONDS), target = src)) return if(!user.Adjacent(src)) return durability-- - user.apply_damage(4, STAMINA) + user.apply_damage(4 * skill_modifier, STAMINA) if(durability <= 0) convert_to_ore() to_chat(user, span_notice("You finish working on \the [src], and it crumbles into ore.")) diff --git a/code/modules/mining/boulder_processing/brm.dm b/code/modules/mining/boulder_processing/brm.dm index e4d525bff056c1f..592ade5b75796f5 100644 --- a/code/modules/mining/boulder_processing/brm.dm +++ b/code/modules/mining/boulder_processing/brm.dm @@ -37,26 +37,23 @@ register_context() /obj/machinery/brm/add_context(atom/source, list/context, obj/item/held_item, mob/user) - . = CONTEXTUAL_SCREENTIP_SET + . = NONE if(isnull(held_item)) context[SCREENTIP_CONTEXT_LMB] = "Teleport single boulder" context[SCREENTIP_CONTEXT_RMB] = "Toggle [toggled_on ? "Off" : "On"] automatic boulder retrieval" - return + return CONTEXTUAL_SCREENTIP_SET if(!isnull(held_item)) if(held_item.tool_behaviour == TOOL_WRENCH) - context[SCREENTIP_CONTEXT_LMB] = "[anchored ? "" : "Un"] Anchor" - return - if(held_item.tool_behaviour == TOOL_SCREWDRIVER) - context[SCREENTIP_CONTEXT_LMB] = "[panel_open ? "Close" : "Open"] Panel" - return - - if(panel_open) - if(held_item.tool_behaviour == TOOL_CROWBAR) - context[SCREENTIP_CONTEXT_LMB] = "Deconstruct" - - return CONTEXTUAL_SCREENTIP_SET + context[SCREENTIP_CONTEXT_LMB] = "[anchored ? "Un" : ""]Anchor" + return CONTEXTUAL_SCREENTIP_SET + else if(held_item.tool_behaviour == TOOL_SCREWDRIVER) + context[SCREENTIP_CONTEXT_LMB] = "[panel_open ? "Close" : "Open"] panel" + return CONTEXTUAL_SCREENTIP_SET + else if(panel_open && held_item.tool_behaviour == TOOL_CROWBAR) + context[SCREENTIP_CONTEXT_LMB] = "Deconstruct" + return CONTEXTUAL_SCREENTIP_SET /obj/machinery/brm/examine(mob/user) . = ..() @@ -131,8 +128,6 @@ var/result = pre_collect_boulder() if(result == TURF_BLOCKED_BY_BOULDER) balloon_alert(user, "no space") - else if(result) - balloon_alert(user, "teleporting") COOLDOWN_START(src, manual_teleport_cooldown, TELEPORTATION_TIME) return TRUE diff --git a/code/modules/mining/boulder_processing/refinery.dm b/code/modules/mining/boulder_processing/refinery.dm index 662bb3e75e1e501..a751566efa107b1 100644 --- a/code/modules/mining/boulder_processing/refinery.dm +++ b/code/modules/mining/boulder_processing/refinery.dm @@ -85,3 +85,7 @@ /obj/machinery/bouldertech/refinery/smelter/on_set_is_operational(old_value) set_light_on(TRUE) +/obj/machinery/bouldertech/refinery/smelter/maim_golem(mob/living/carbon/human/rockman) + rockman.visible_message(span_warning("[rockman] is processed by [src]!"), span_userdanger("You get melted into rock by [src]!")) + rockman.investigate_log("was melted by [src] for being a golem", INVESTIGATE_DEATHS) + rockman.dust() diff --git a/code/modules/mining/equipment/kinetic_crusher.dm b/code/modules/mining/equipment/kinetic_crusher.dm index e1df98239e2cd43..92ded187109fbb2 100644 --- a/code/modules/mining/equipment/kinetic_crusher.dm +++ b/code/modules/mining/equipment/kinetic_crusher.dm @@ -1,4 +1,10 @@ -/*********************Mining Hammer****************/ +/** + * Kinetic Crusher + * + * Lavaland's "Hard Mode" option for players, requiring melee attacks (backstabs even better), + * but allowing you to upgrade it with trophies gained from fighting lavaland monsters, making it + * a good tradeoff and a decent playstyle. + */ /obj/item/kinetic_crusher icon = 'icons/obj/mining.dmi' icon_state = "crusher" @@ -6,8 +12,9 @@ lefthand_file = 'icons/mob/inhands/weapons/hammers_lefthand.dmi' righthand_file = 'icons/mob/inhands/weapons/hammers_righthand.dmi' name = "proto-kinetic crusher" - desc = "An early design of the proto-kinetic accelerator, it is little more than a combination of various mining tools cobbled together, forming a high-tech club. \ - While it is an effective mining tool, it did little to aid any but the most skilled and/or suicidal miners against local fauna." + desc = "An early design of the proto-kinetic accelerator, it is little more than a combination of various mining tools cobbled together, \ + forming a high-tech club. While it is an effective mining tool, it did little to aid any but the most skilled and/or \ + suicidal miners against local fauna." force = 0 //You can't hit stuff unless wielded w_class = WEIGHT_CLASS_BULKY slot_flags = ITEM_SLOT_BACK @@ -23,10 +30,13 @@ obj_flags = UNIQUE_RENAME light_system = OVERLAY_LIGHT light_range = 5 + light_power = 1.2 + light_color = "#ffff66" light_on = FALSE - var/list/trophies = list() + ///List of all crusher trophies attached to this. + var/list/obj/item/crusher_trophy/trophies = list() var/charged = TRUE - var/charge_time = 15 + var/charge_time = 1.5 SECONDS var/detonation_damage = 50 var/backstab_bonus = 30 @@ -52,75 +62,81 @@ . = ..() . += span_notice("Mark a large creature with a destabilizing force with right-click, then hit them in melee to do [force + detonation_damage] damage.") . += span_notice("Does [force + detonation_damage + backstab_bonus] damage if the target is backstabbed, instead of [force + detonation_damage].") - for(var/t in trophies) - var/obj/item/crusher_trophy/T = t - . += span_notice("It has \a [T] attached, which causes [T.effect_desc()].") - -/obj/item/kinetic_crusher/attackby(obj/item/I, mob/living/user) - if(I.tool_behaviour == TOOL_CROWBAR) - if(LAZYLEN(trophies)) - to_chat(user, span_notice("You remove [src]'s trophies.")) - I.play_tool_sound(src) - for(var/t in trophies) - var/obj/item/crusher_trophy/T = t - T.remove_from(src, user) - else - to_chat(user, span_warning("There are no trophies on [src].")) - else if(istype(I, /obj/item/crusher_trophy)) - var/obj/item/crusher_trophy/T = I - T.add_to(src, user) - else - return ..() + for(var/obj/item/crusher_trophy/crusher_trophy as anything in trophies) + . += span_notice("It has \a [crusher_trophy] attached, which causes [crusher_trophy.effect_desc()].") + +/obj/item/kinetic_crusher/attackby(obj/item/attacking_item, mob/user, params) + if(istype(attacking_item, /obj/item/crusher_trophy)) + var/obj/item/crusher_trophy/crusher_trophy = attacking_item + crusher_trophy.add_to(src, user) + return + return ..() + +/obj/item/kinetic_crusher/crowbar_act(mob/living/user, obj/item/tool) + . = ..() + if(!LAZYLEN(trophies)) + user.balloon_alert(user, "no trophies!") + return ITEM_INTERACT_BLOCKING + user.balloon_alert(user, "trophies removed") + tool.play_tool_sound(src) + for(var/obj/item/crusher_trophy/crusher_trophy as anything in trophies) + crusher_trophy.remove_from(src, user) + return ITEM_INTERACT_SUCCESS /obj/item/kinetic_crusher/attack(mob/living/target, mob/living/carbon/user) if(!HAS_TRAIT(src, TRAIT_WIELDED)) to_chat(user, span_warning("[src] is too heavy to use with one hand! You fumble and drop everything.")) user.drop_all_held_items() return - var/datum/status_effect/crusher_damage/C = target.has_status_effect(/datum/status_effect/crusher_damage) - if(!C) - C = target.apply_status_effect(/datum/status_effect/crusher_damage) + var/datum/status_effect/crusher_damage/crusher_damage_effect = target.has_status_effect(/datum/status_effect/crusher_damage) + if(!crusher_damage_effect) + crusher_damage_effect = target.apply_status_effect(/datum/status_effect/crusher_damage) var/target_health = target.health ..() - for(var/t in trophies) + for(var/obj/item/crusher_trophy/crusher_trophy as anything in trophies) if(!QDELETED(target)) - var/obj/item/crusher_trophy/T = t - T.on_melee_hit(target, user) - if(!QDELETED(C) && !QDELETED(target)) - C.total_damage += target_health - target.health //we did some damage, but let's not assume how much we did - -/obj/item/kinetic_crusher/afterattack(atom/target, mob/living/user, proximity_flag, clickparams) - if(proximity_flag && isliving(target)) - var/mob/living/L = target - var/datum/status_effect/crusher_mark/CM = L.has_status_effect(/datum/status_effect/crusher_mark) - if(!CM || CM.hammer_synced != src || !L.remove_status_effect(/datum/status_effect/crusher_mark)) - return - var/datum/status_effect/crusher_damage/C = L.has_status_effect(/datum/status_effect/crusher_damage) - if(!C) - C = L.apply_status_effect(/datum/status_effect/crusher_damage) - var/target_health = L.health - for(var/t in trophies) - var/obj/item/crusher_trophy/T = t - T.on_mark_detonation(target, user) - if(!QDELETED(L)) - if(!QDELETED(C)) - C.total_damage += target_health - L.health //we did some damage, but let's not assume how much we did - new /obj/effect/temp_visual/kinetic_blast(get_turf(L)) - var/backstabbed = FALSE - var/combined_damage = detonation_damage - var/backstab_dir = get_dir(user, L) - var/def_check = L.getarmor(type = BOMB) - if((user.dir & backstab_dir) && (L.dir & backstab_dir)) - backstabbed = TRUE - combined_damage += backstab_bonus - playsound(user, 'sound/weapons/kinetic_accel.ogg', 100, TRUE) //Seriously who spelled it wrong - - if(!QDELETED(C)) - C.total_damage += combined_damage - - - SEND_SIGNAL(user, COMSIG_LIVING_CRUSHER_DETONATE, L, src, backstabbed) - L.apply_damage(combined_damage, BRUTE, blocked = def_check) + crusher_trophy.on_melee_hit(target, user) + if(!QDELETED(crusher_damage_effect) && !QDELETED(target)) + crusher_damage_effect.total_damage += target_health - target.health //we did some damage, but let's not assume how much we did + +/obj/item/kinetic_crusher/afterattack(mob/living/target, mob/living/user, proximity_flag, clickparams) + . = ..() + if(.) + return + if(!proximity_flag || !isliving(target)) + return + var/valid_crusher_attack = FALSE + for(var/datum/status_effect/crusher_mark/crusher_mark_effect as anything in target.get_all_status_effect_of_id(/datum/status_effect/crusher_mark)) + //this will erase ALL crusher marks, not only ones by you. + if(crusher_mark_effect.hammer_synced != src || !target.remove_status_effect(/datum/status_effect/crusher_mark, src)) + continue + valid_crusher_attack = TRUE + break + if(!valid_crusher_attack) + return + var/datum/status_effect/crusher_damage/crusher_damage_effect = target.has_status_effect(/datum/status_effect/crusher_damage) + if(!crusher_damage_effect) + crusher_damage_effect = target.apply_status_effect(/datum/status_effect/crusher_damage) + var/target_health = target.health + for(var/obj/item/crusher_trophy/crusher_trophy as anything in trophies) + crusher_trophy.on_mark_detonation(target, user) + if(QDELETED(target)) + return + if(!QDELETED(crusher_damage_effect)) + crusher_damage_effect.total_damage += target_health - target.health //we did some damage, but let's not assume how much we did + new /obj/effect/temp_visual/kinetic_blast(get_turf(target)) + var/backstabbed = FALSE + var/combined_damage = detonation_damage + var/backstab_dir = get_dir(user, target) + var/def_check = target.getarmor(type = BOMB) + if((user.dir & backstab_dir) && (target.dir & backstab_dir)) + backstabbed = TRUE + combined_damage += backstab_bonus + playsound(user, 'sound/weapons/kinetic_accel.ogg', 100, TRUE) //Seriously who spelled it wrong + if(!QDELETED(crusher_damage_effect)) + crusher_damage_effect.total_damage += combined_damage + SEND_SIGNAL(user, COMSIG_LIVING_CRUSHER_DETONATE, target, src, backstabbed) + target.apply_damage(combined_damage, BRUTE, blocked = def_check) /obj/item/kinetic_crusher/attack_secondary(atom/target, mob/living/user, clickparams) return SECONDARY_ATTACK_CONTINUE_CHAIN @@ -153,9 +169,9 @@ destabilizer.fire() charged = FALSE update_appearance() - addtimer(CALLBACK(src, PROC_REF(Recharge)), charge_time) + addtimer(CALLBACK(src, PROC_REF(recharge_projectile)), charge_time) -/obj/item/kinetic_crusher/proc/Recharge() +/obj/item/kinetic_crusher/proc/recharge_projectile() if(!charged) charged = TRUE update_appearance() @@ -195,6 +211,7 @@ armor_flag = BOMB range = 6 log_override = TRUE + ///The crusher that's firing this projectile. var/obj/item/kinetic_crusher/hammer_synced /obj/projectile/destabilizer/Destroy() @@ -203,19 +220,21 @@ /obj/projectile/destabilizer/on_hit(atom/target, blocked = 0, pierce_hit) if(isliving(target)) - var/mob/living/L = target - var/had_effect = (L.has_status_effect(/datum/status_effect/crusher_mark)) //used as a boolean - var/datum/status_effect/crusher_mark/CM = L.apply_status_effect(/datum/status_effect/crusher_mark, hammer_synced) - if(hammer_synced) - for(var/t in hammer_synced.trophies) - var/obj/item/crusher_trophy/T = t - T.on_mark_application(target, CM, had_effect) + var/mob/living/living_target = target + var/has_mark_from_this_crusher = FALSE + for(var/datum/status_effect/crusher_mark/crusher_mark_effect as anything in living_target.get_all_status_effect_of_id(/datum/status_effect/crusher_mark)) + if(crusher_mark_effect.hammer_synced != hammer_synced) + continue + has_mark_from_this_crusher = TRUE + break + if(!has_mark_from_this_crusher) + living_target.apply_status_effect(/datum/status_effect/crusher_mark, hammer_synced) var/target_turf = get_turf(target) if(ismineralturf(target_turf)) - var/turf/closed/mineral/M = target_turf - new /obj/effect/temp_visual/kinetic_blast(M) - M.gets_drilled(firer) - ..() + var/turf/closed/mineral/hit_mineral = target_turf + new /obj/effect/temp_visual/kinetic_blast(hit_mineral) + hit_mineral.gets_drilled(firer) + return ..() //trophies /obj/item/crusher_trophy @@ -256,7 +275,6 @@ /obj/item/crusher_trophy/proc/on_melee_hit(mob/living/target, mob/living/user) //the target and the user /obj/item/crusher_trophy/proc/on_projectile_fire(obj/projectile/destabilizer/marker, mob/living/user) //the projectile fired and the user -/obj/item/crusher_trophy/proc/on_mark_application(mob/living/target, datum/status_effect/crusher_mark/mark, had_mark) //the target, the mark applied, and if the target had a mark before /obj/item/crusher_trophy/proc/on_mark_detonation(mob/living/target, mob/living/user) //the target and the user //watcher @@ -348,13 +366,13 @@ return "mark detonation to do [bonus_value] damage to nearby creatures and push them back" /obj/item/crusher_trophy/tail_spike/on_mark_detonation(mob/living/target, mob/living/user) - for(var/mob/living/L in oview(2, user)) - if(L.stat == DEAD) + for(var/mob/living/living_target in oview(2, user)) + if(user.faction_check_atom(living_target) || living_target.stat == DEAD) continue - playsound(L, 'sound/magic/fireball.ogg', 20, TRUE) - new /obj/effect/temp_visual/fire(L.loc) - addtimer(CALLBACK(src, PROC_REF(pushback), L, user), 1) //no free backstabs, we push AFTER module stuff is done - L.adjustFireLoss(bonus_value, forced = TRUE) + playsound(living_target, 'sound/magic/fireball.ogg', 20, TRUE) + new /obj/effect/temp_visual/fire(living_target.loc) + addtimer(CALLBACK(src, PROC_REF(pushback), living_target, user), 1) //no free backstabs, we push AFTER module stuff is done + living_target.adjustFireLoss(bonus_value, forced = TRUE) /obj/item/crusher_trophy/tail_spike/proc/pushback(mob/living/target, mob/living/user) if(!QDELETED(target) && !QDELETED(user) && (!target.anchored || ismegafauna(target))) //megafauna will always be pushed @@ -470,3 +488,17 @@ continue return possible_turf return get_turf(user) + +//wolf trophy + +/obj/item/crusher_trophy/wolf_ear + name = "wolf ear" + desc = "It's a wolf ear." + icon_state = "wolf_ear" + denied_type = /obj/item/crusher_trophy/wolf_ear + +/obj/item/crusher_trophy/wolf_ear/effect_desc() + return "mark detonation to gain a slight speed boost temporarily" + +/obj/item/crusher_trophy/wolf_ear/on_mark_detonation(mob/living/target, mob/living/user) + user.apply_status_effect(/datum/status_effect/speed_boost, 1 SECONDS) diff --git a/code/modules/mining/lavaland/tendril_loot.dm b/code/modules/mining/lavaland/tendril_loot.dm index 310c12940a708d1..240c62203954f71 100644 --- a/code/modules/mining/lavaland/tendril_loot.dm +++ b/code/modules/mining/lavaland/tendril_loot.dm @@ -272,7 +272,9 @@ icon = 'icons/obj/lighting.dmi' icon_state = "orb" light_system = OVERLAY_LIGHT - light_range = 7 + light_range = 6 + light_power = 1.2 + light_color = "#79f1ff" light_flags = LIGHT_ATTACHED layer = ABOVE_ALL_MOB_LAYER plane = ABOVE_GAME_PLANE diff --git a/code/modules/mining/machine_processing.dm b/code/modules/mining/machine_processing.dm index 62458347bf013c7..11a941c409861c0 100644 --- a/code/modules/mining/machine_processing.dm +++ b/code/modules/mining/machine_processing.dm @@ -147,21 +147,10 @@ /obj/machinery/mineral/processing_unit/Initialize(mapload) . = ..() proximity_monitor = new(src, 1) - var/list/allowed_materials = list( - /datum/material/iron, - /datum/material/glass, - /datum/material/silver, - /datum/material/gold, - /datum/material/diamond, - /datum/material/plasma, - /datum/material/uranium, - /datum/material/bananium, - /datum/material/titanium, - /datum/material/bluespace, - ) + materials = AddComponent( \ /datum/component/material_container, \ - allowed_materials, \ + SSmaterials.materials_by_category[MAT_CATEGORY_SILO], \ INFINITY, \ MATCONTAINER_EXAMINE, \ allowed_items = /obj/item/stack \ diff --git a/code/modules/mining/machine_silo.dm b/code/modules/mining/machine_silo.dm index 9320bc012264c9b..97c3a90b78eb135 100644 --- a/code/modules/mining/machine_silo.dm +++ b/code/modules/mining/machine_silo.dm @@ -18,22 +18,9 @@ /obj/machinery/ore_silo/Initialize(mapload) . = ..() - var/static/list/materials_list = list( - /datum/material/iron, - /datum/material/glass, - /datum/material/silver, - /datum/material/gold, - /datum/material/diamond, - /datum/material/plasma, - /datum/material/uranium, - /datum/material/bananium, - /datum/material/titanium, - /datum/material/bluespace, - /datum/material/plastic, - ) materials = AddComponent( \ /datum/component/material_container, \ - materials_list, \ + SSmaterials.materials_by_category[MAT_CATEGORY_SILO], \ INFINITY, \ MATCONTAINER_EXAMINE, \ container_signals = list( \ diff --git a/code/modules/mining/ores_coins.dm b/code/modules/mining/ores_coins.dm index 0b499f590d66835..4fe26281b10a71c 100644 --- a/code/modules/mining/ores_coins.dm +++ b/code/modules/mining/ores_coins.dm @@ -614,7 +614,7 @@ GLOBAL_LIST_INIT(sand_recipes, list(\ /obj/item/coin/eldritch name = "eldritch coin" - desc = "Everytime it lands it bolts or opens doors, except for you." + desc = "A surprisingly heavy, ornate coin. Its sides seem to depict a different image each time you look." icon_state = "coin_heretic" custom_materials = list(/datum/material/diamond =HALF_SHEET_MATERIAL_AMOUNT, /datum/material/plasma =HALF_SHEET_MATERIAL_AMOUNT) sideslist = list("heretic", "blade") diff --git a/code/modules/mob/dead/observer/observer.dm b/code/modules/mob/dead/observer/observer.dm index 26250d0d7a7f745..bfd4e3bd0019cc4 100644 --- a/code/modules/mob/dead/observer/observer.dm +++ b/code/modules/mob/dead/observer/observer.dm @@ -17,8 +17,8 @@ GLOBAL_VAR_INIT(observer_default_invisibility, INVISIBILITY_OBSERVER) hud_type = /datum/hud/ghost movement_type = GROUND | FLYING light_system = OVERLAY_LIGHT - light_range = 1 - light_power = 2 + light_range = 2.5 + light_power = 0.6 light_on = FALSE shift_to_open_context_menu = FALSE var/can_reenter_corpse diff --git a/code/modules/mob/dead/observer/observer_movement.dm b/code/modules/mob/dead/observer/observer_movement.dm index 9e156913a98a70d..6972d3b265ff6dd 100644 --- a/code/modules/mob/dead/observer/observer_movement.dm +++ b/code/modules/mob/dead/observer/observer_movement.dm @@ -1,11 +1,17 @@ +/mob/dead/observer/down() + set name = "Move Down" + set category = "IC" + + if(zMove(DOWN, z_move_flags = ZMOVE_FEEDBACK)) + to_chat(src, span_notice("You move down.")) + /mob/dead/observer/up() set name = "Move Upwards" set category = "IC" if(zMove(UP, z_move_flags = ZMOVE_FEEDBACK)) - to_chat(src, "You move upwards.") + to_chat(src, span_notice("You move upwards.")) /mob/dead/observer/can_z_move(direction, turf/start, turf/destination, z_move_flags = NONE, mob/living/rider) z_move_flags |= ZMOVE_IGNORE_OBSTACLES //observers do not respect these FLOORS you speak so much of. return ..() - diff --git a/code/modules/mob/living/basic/bots/_bots.dm b/code/modules/mob/living/basic/bots/_bots.dm index 56fdc4fc938426d..13298d8fa2f4f92 100644 --- a/code/modules/mob/living/basic/bots/_bots.dm +++ b/code/modules/mob/living/basic/bots/_bots.dm @@ -6,7 +6,6 @@ GLOBAL_LIST_INIT(command_strings, list( "home" = "RETURN HOME", )) - /mob/living/basic/bot icon = 'icons/mob/silicon/aibots.dmi' layer = MOB_LAYER @@ -37,7 +36,7 @@ GLOBAL_LIST_INIT(command_strings, list( faction = list(FACTION_NEUTRAL, FACTION_SILICON, FACTION_TURRET) light_system = OVERLAY_LIGHT light_range = 3 - light_power = 0.9 + light_power = 0.6 speed = 3 ///Access required to access this Bot's maintenance protocols var/maints_access_required = list(ACCESS_ROBOTICS) diff --git a/code/modules/mob/living/basic/bots/cleanbot/cleanbot.dm b/code/modules/mob/living/basic/bots/cleanbot/cleanbot.dm index a81f48c9c95aa01..025ef906c228297 100644 --- a/code/modules/mob/living/basic/bots/cleanbot/cleanbot.dm +++ b/code/modules/mob/living/basic/bots/cleanbot/cleanbot.dm @@ -10,6 +10,7 @@ anchored = FALSE health = 25 maxHealth = 25 + light_color = "#99ccff" maints_access_required = list(ACCESS_ROBOTICS, ACCESS_JANITOR) radio_key = /obj/item/encryptionkey/headset_service @@ -331,7 +332,7 @@ INVOKE_ASYNC(our_mop, TYPE_PROC_REF(/obj/item, melee_attack_chain), src, target) return COMPONENT_CANCEL_ATTACK_CHAIN - if(!iscarbon(target) && !is_type_in_typecache(target, huntable_trash)) + if(!(iscarbon(target) && (bot_access_flags & BOT_COVER_EMAGGED)) && !is_type_in_typecache(target, huntable_trash)) return NONE visible_message(span_danger("[src] sprays hydrofluoric acid at [target]!")) diff --git a/code/modules/mob/living/basic/bots/medbot/medbot.dm b/code/modules/mob/living/basic/bots/medbot/medbot.dm index 7e801d5379803fa..83425e72b3771f8 100644 --- a/code/modules/mob/living/basic/bots/medbot/medbot.dm +++ b/code/modules/mob/living/basic/bots/medbot/medbot.dm @@ -11,6 +11,8 @@ health = 20 maxHealth = 20 speed = 2 + light_power = 0.8 + light_color = "#99ccff" pass_flags = PASSMOB | PASSFLAPS status_flags = (CANPUSH | CANSTUN) ai_controller = /datum/ai_controller/basic_controller/bot/medbot diff --git a/code/modules/mob/living/basic/clown/clown.dm b/code/modules/mob/living/basic/clown/clown.dm index 88c2b9496a9295e..a1a7014b26354dd 100644 --- a/code/modules/mob/living/basic/clown/clown.dm +++ b/code/modules/mob/living/basic/clown/clown.dm @@ -403,7 +403,7 @@ GRANT_ACTION(/datum/action/cooldown/regurgitate) AddElement(/datum/element/swabable, CELL_LINE_TABLE_GLUTTON, CELL_VIRUS_TABLE_GENERIC_MOB, 1, 5) - AddComponent(/datum/component/tameable, food_types = list(/obj/item/food/cheesiehonkers, /obj/item/food/cornchips), tame_chance = 30, bonus_tame_chance = 0, after_tame = CALLBACK(src, PROC_REF(tamed))) + AddComponent(/datum/component/tameable, food_types = list(/obj/item/food/cheesiehonkers, /obj/item/food/cornchips), tame_chance = 30, bonus_tame_chance = 0) AddElement(/datum/element/damage_threshold, 10) //lots of fat to cushion blows. /mob/living/basic/clown/mutant/glutton/attacked_by(obj/item/item, mob/living/user) @@ -461,7 +461,7 @@ playsound(loc,'sound/items/eatfood.ogg', rand(30,50), TRUE) flick("glutton_mouth", src) -/mob/living/basic/clown/mutant/glutton/proc/tamed(mob/living/tamer) +/mob/living/basic/clown/mutant/glutton/tamed(mob/living/tamer, atom/food) buckle_lying = 0 AddElement(/datum/element/ridable, /datum/component/riding/creature/glutton) diff --git a/code/modules/mob/living/basic/drone/_drone.dm b/code/modules/mob/living/basic/drone/_drone.dm index 9b0729954dc1dc3..6432377374e3942 100644 --- a/code/modules/mob/living/basic/drone/_drone.dm +++ b/code/modules/mob/living/basic/drone/_drone.dm @@ -47,7 +47,6 @@ lighting_cutoff_red = 30 lighting_cutoff_green = 35 lighting_cutoff_blue = 25 - can_be_held = TRUE worn_slot_flags = ITEM_SLOT_HEAD /// `TRUE` if we have picked our visual appearance, `FALSE` otherwise (default) @@ -265,6 +264,9 @@ /mob/living/basic/drone/gib() dust() +/mob/living/basic/drone/get_butt_sprite() + return BUTT_SPRITE_DRONE + /mob/living/basic/drone/examine(mob/user) . = list("This is [icon2html(src, user)] \a [src]!", EXAMINE_SECTION_BREAK) //SKYRAT EDIT CHANGE diff --git a/code/modules/mob/living/basic/farm_animals/cow/_cow.dm b/code/modules/mob/living/basic/farm_animals/cow/_cow.dm index e5d49aa867b5036..1472a64039a7710 100644 --- a/code/modules/mob/living/basic/farm_animals/cow/_cow.dm +++ b/code/modules/mob/living/basic/farm_animals/cow/_cow.dm @@ -61,10 +61,10 @@ var/static/list/food_types if(!food_types) food_types = src.food_types.Copy() - AddComponent(/datum/component/tameable, food_types = food_types, tame_chance = 25, bonus_tame_chance = 15, after_tame = CALLBACK(src, PROC_REF(tamed))) + AddComponent(/datum/component/tameable, food_types = food_types, tame_chance = 25, bonus_tame_chance = 15) AddElement(/datum/element/basic_eating, food_types = food_types) -/mob/living/basic/cow/proc/tamed(mob/living/tamer) +/mob/living/basic/cow/tamed(mob/living/tamer, atom/food) buckle_lying = 0 visible_message("[src] [tame_message] as it seems to bond with [tamer].", "You [self_tame_message], recognizing [tamer] as your new pal.") AddElement(/datum/element/ridable, /datum/component/riding/creature/cow) diff --git a/code/modules/mob/living/basic/farm_animals/cow/cow_moonicorn.dm b/code/modules/mob/living/basic/farm_animals/cow/cow_moonicorn.dm index b3af3c59a12b248..f4c1849883fe21d 100644 --- a/code/modules/mob/living/basic/farm_animals/cow/cow_moonicorn.dm +++ b/code/modules/mob/living/basic/farm_animals/cow/cow_moonicorn.dm @@ -35,9 +35,9 @@ if(!food_types) food_types = src.food_types.Copy() AddElement(/datum/element/basic_eating, food_types = food_types) - AddComponent(/datum/component/tameable, food_types = food_types, tame_chance = 25, bonus_tame_chance = 15, after_tame = CALLBACK(src, PROC_REF(tamed))) + AddComponent(/datum/component/tameable, food_types = food_types, tame_chance = 25, bonus_tame_chance = 15) -/mob/living/basic/cow/moonicorn/tamed(mob/living/tamer) +/mob/living/basic/cow/moonicorn/tamed(mob/living/tamer, atom/food) . = ..() ///stop killing my FRIENDS faction |= tamer.faction diff --git a/code/modules/mob/living/basic/farm_animals/pig.dm b/code/modules/mob/living/basic/farm_animals/pig.dm index 94183d044c53151..6f732f16844791c 100644 --- a/code/modules/mob/living/basic/farm_animals/pig.dm +++ b/code/modules/mob/living/basic/farm_animals/pig.dm @@ -37,9 +37,9 @@ ///wrapper for the tameable component addition so you can have non tamable cow subtypes /mob/living/basic/pig/proc/make_tameable() - AddComponent(/datum/component/tameable, food_types = list(/obj/item/food/grown/carrot), tame_chance = 25, bonus_tame_chance = 15, after_tame = CALLBACK(src, PROC_REF(tamed))) + AddComponent(/datum/component/tameable, food_types = list(/obj/item/food/grown/carrot), tame_chance = 25, bonus_tame_chance = 15) -/mob/living/basic/pig/proc/tamed(mob/living/tamer) +/mob/living/basic/pig/tamed(mob/living/tamer, atom/food) can_buckle = TRUE buckle_lying = 0 AddElement(/datum/element/ridable, /datum/component/riding/creature/pig) diff --git a/code/modules/mob/living/basic/farm_animals/pony.dm b/code/modules/mob/living/basic/farm_animals/pony.dm index 7795ec630e6d5ac..4c2c76e84c2029b 100644 --- a/code/modules/mob/living/basic/farm_animals/pony.dm +++ b/code/modules/mob/living/basic/farm_animals/pony.dm @@ -41,9 +41,9 @@ AddElement(/datum/element/ai_retaliate) AddElement(/datum/element/ai_flee_while_injured) AddElementTrait(TRAIT_WADDLING, INNATE_TRAIT, /datum/element/waddling) - AddComponent(/datum/component/tameable, food_types = list(/obj/item/food/grown/apple), tame_chance = 25, bonus_tame_chance = 15, after_tame = CALLBACK(src, PROC_REF(tamed)), unique = unique_tamer) + AddComponent(/datum/component/tameable, food_types = list(/obj/item/food/grown/apple), tame_chance = 25, bonus_tame_chance = 15, unique = unique_tamer) -/mob/living/basic/pony/proc/tamed(mob/living/tamer) +/mob/living/basic/pony/tamed(mob/living/tamer, atom/food) can_buckle = TRUE buckle_lying = 0 playsound(src, 'sound/creatures/pony/snort.ogg', 50) @@ -151,4 +151,4 @@ ponycolors = list("#5d566f", pick_weight(mane_colors)) name = pick("Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday") // Only one person can tame these fellas, and they only need one apple - AddComponent(/datum/component/tameable, food_types = list(/obj/item/food/grown/apple), tame_chance = 100, bonus_tame_chance = 15, after_tame = CALLBACK(src, PROC_REF(tamed)), unique = unique_tamer) + AddComponent(/datum/component/tameable, food_types = list(/obj/item/food/grown/apple), tame_chance = 100, bonus_tame_chance = 15, unique = unique_tamer) diff --git a/code/modules/mob/living/basic/guardian/guardian_types/protector.dm b/code/modules/mob/living/basic/guardian/guardian_types/protector.dm index 27ec9cace810b31..a7a9e718e5434b3 100644 --- a/code/modules/mob/living/basic/guardian/guardian_types/protector.dm +++ b/code/modules/mob/living/basic/guardian/guardian_types/protector.dm @@ -16,7 +16,6 @@ /mob/living/basic/guardian/protector/Initialize(mapload, datum/guardian_fluff/theme) . = ..() shield = new(src) - shield.owner_has_control = FALSE // Hide it from the user, it's integrated with guardian UI shield.Grant(src) /mob/living/basic/guardian/protector/Destroy() @@ -49,6 +48,7 @@ background_icon_state = "base" cooldown_time = 1 SECONDS click_to_activate = FALSE + owner_has_control = FALSE // Hide it from the user, it's integrated with guardian UI /datum/action/cooldown/mob_cooldown/protector_shield/Activate(mob/living/target) if (!isliving(target)) diff --git a/code/modules/mob/living/basic/icemoon/wolf/wolf.dm b/code/modules/mob/living/basic/icemoon/wolf/wolf.dm index c657fa4284338a5..e452c1564744859 100644 --- a/code/modules/mob/living/basic/icemoon/wolf/wolf.dm +++ b/code/modules/mob/living/basic/icemoon/wolf/wolf.dm @@ -65,15 +65,9 @@ make_tameable() /mob/living/basic/mining/wolf/proc/make_tameable() - AddComponent(\ - /datum/component/tameable,\ - food_types = list(/obj/item/food/meat/slab),\ - tame_chance = 15,\ - bonus_tame_chance = 5,\ - after_tame = CALLBACK(src, PROC_REF(tame_wolf)),\ - ) + AddComponent(/datum/component/tameable, food_types = list(/obj/item/food/meat/slab), tame_chance = 15, bonus_tame_chance = 5) -/mob/living/basic/mining/wolf/proc/tame_wolf() +/mob/living/basic/mining/wolf/tamed(mob/living/tamer, atom/food) new /obj/effect/temp_visual/heart(src.loc) // ride wolf, life good AddElement(/datum/element/ridable, /datum/component/riding/creature/wolf) diff --git a/code/modules/mob/living/basic/lavaland/goldgrub/goldgrub.dm b/code/modules/mob/living/basic/lavaland/goldgrub/goldgrub.dm index f35f78ba80f67c1..ce9f24393580985 100644 --- a/code/modules/mob/living/basic/lavaland/goldgrub/goldgrub.dm +++ b/code/modules/mob/living/basic/lavaland/goldgrub/goldgrub.dm @@ -106,15 +106,9 @@ return ..() /mob/living/basic/mining/goldgrub/proc/make_tameable() - AddComponent(\ - /datum/component/tameable,\ - food_types = list(/obj/item/stack/ore),\ - tame_chance = 25,\ - bonus_tame_chance = 5,\ - after_tame = CALLBACK(src, PROC_REF(tame_grub)),\ - ) + AddComponent(/datum/component/tameable, food_types = list(/obj/item/stack/ore), tame_chance = 25, bonus_tame_chance = 5) -/mob/living/basic/mining/goldgrub/proc/tame_grub() +/mob/living/basic/mining/goldgrub/tamed(mob/living/tamer, atom/food) new /obj/effect/temp_visual/heart(src.loc) AddElement(/datum/element/ridable, /datum/component/riding/creature/goldgrub) AddComponent(/datum/component/obeys_commands, pet_commands) diff --git a/code/modules/mob/living/basic/lavaland/goliath/goliath.dm b/code/modules/mob/living/basic/lavaland/goliath/goliath.dm index 6d197d8853a761a..db47e91ad26d91f 100644 --- a/code/modules/mob/living/basic/lavaland/goliath/goliath.dm +++ b/code/modules/mob/living/basic/lavaland/goliath/goliath.dm @@ -68,13 +68,7 @@ AddComponent(/datum/component/basic_mob_attack_telegraph) AddComponentFrom(INNATE_TRAIT, /datum/component/shovel_hands) if (tameable) - AddComponent(\ - /datum/component/tameable,\ - food_types = list(/obj/item/food/grown/ash_flora),\ - tame_chance = 10,\ - bonus_tame_chance = 5,\ - after_tame = CALLBACK(src, PROC_REF(tamed)),\ - ) + AddComponent(/datum/component/tameable, food_types = list(/obj/item/food/grown/ash_flora), tame_chance = 10, bonus_tame_chance = 5) tentacles = new (src) tentacles.Grant(src) @@ -120,6 +114,9 @@ return balloon_alert(user, "ready to ride") qdel(attacking_item) + make_rideable() + +/mob/living/basic/mining/goliath/proc/make_rideable() saddled = TRUE buckle_lying = 0 add_overlay("goliath_saddled") @@ -149,7 +146,7 @@ icon_state = tentacle_warning_state /// Get ready for mounting -/mob/living/basic/mining/goliath/proc/tamed() +/mob/living/basic/mining/goliath/tamed(mob/living/tamer, atom/food) tamed = TRUE // Copy entire faction rather than just placing user into faction, to avoid tentacle peril on station @@ -163,6 +160,12 @@ /mob/living/basic/mining/goliath/ranged_secondary_attack(atom/atom_target, modifiers) tentacle_line?.Trigger(target = atom_target) +/mob/living/basic/mining/goliath/saddled + +/mob/living/basic/mining/goliath/saddled/Initialize(mapload) + . = ..() + make_rideable() + /// Legacy Goliath mob with different sprites, largely the same behaviour /mob/living/basic/mining/goliath/ancient name = "ancient goliath" diff --git a/code/modules/mob/living/basic/minebots/minebot.dm b/code/modules/mob/living/basic/minebots/minebot.dm index 5422ab4ee2e9885..30f486e9416a293 100644 --- a/code/modules/mob/living/basic/minebots/minebot.dm +++ b/code/modules/mob/living/basic/minebots/minebot.dm @@ -25,6 +25,9 @@ death_message = "blows apart!" light_system = OVERLAY_LIGHT light_range = 6 + // I want this to be a bit more dim, for vibes + light_power = 0.6 + light_color = "#ff9933" light_on = FALSE combat_mode = FALSE ai_controller = /datum/ai_controller/basic_controller/minebot @@ -50,13 +53,7 @@ AddElement(/datum/element/death_drops, death_drops) add_traits(list(TRAIT_LAVA_IMMUNE, TRAIT_ASHSTORM_IMMUNE), INNATE_TRAIT) AddElement(/datum/element/footstep, FOOTSTEP_OBJ_ROBOT, 1, -6, sound_vary = TRUE) - AddComponent(\ - /datum/component/tameable,\ - food_types = list(/obj/item/stack/ore),\ - tame_chance = 100,\ - bonus_tame_chance = 5,\ - after_tame = CALLBACK(src, PROC_REF(activate_bot)),\ - ) + AddComponent(/datum/component/tameable, food_types = list(/obj/item/stack/ore), tame_chance = 100, bonus_tame_chance = 5) var/static/list/innate_actions = list( /datum/action/cooldown/mob_cooldown/minedrone/toggle_light = BB_MINEBOT_LIGHT_ABILITY, @@ -151,7 +148,7 @@ return ACCESS_ALLOWED return ACCESS_DISALLOWED -/mob/living/basic/mining_drone/proc/activate_bot() +/mob/living/basic/mining_drone/tamed(mob/living/tamer, atom/food) AddComponent(/datum/component/obeys_commands, pet_commands) /mob/living/basic/mining_drone/death(gibbed) diff --git a/code/modules/mob/living/basic/pets/dog/_dog.dm b/code/modules/mob/living/basic/pets/dog/_dog.dm index f835d7c5e17584a..f513795e7f685e2 100644 --- a/code/modules/mob/living/basic/pets/dog/_dog.dm +++ b/code/modules/mob/living/basic/pets/dog/_dog.dm @@ -50,7 +50,7 @@ AddElement(/datum/element/pet_bonus, "woofs happily!") AddElement(/datum/element/footstep, FOOTSTEP_MOB_CLAW) AddElement(/datum/element/unfriend_attacker, untamed_reaction = "%SOURCE% fixes %TARGET% with a look of betrayal.") - AddComponent(/datum/component/tameable, food_types = list(/obj/item/food/meat/slab/human/mutant/skeleton, /obj/item/stack/sheet/bone), tame_chance = 30, bonus_tame_chance = 15, after_tame = CALLBACK(src, PROC_REF(tamed)), unique = FALSE) + AddComponent(/datum/component/tameable, food_types = list(/obj/item/food/meat/slab/human/mutant/skeleton, /obj/item/stack/sheet/bone), tame_chance = 30, bonus_tame_chance = 15, unique = FALSE) AddComponent(/datum/component/obeys_commands, pet_commands) var/dog_area = get_area(src) for(var/obj/structure/bed/dogbed/dog_bed in dog_area) @@ -64,7 +64,7 @@ speech.emote_see = string_list(list("shakes [p_their()] head.", "chases [p_their()] tail.","shivers.")) ///Proc to run on a successful taming attempt -/mob/living/basic/pet/dog/proc/tamed(mob/living/tamer) +/mob/living/basic/pet/dog/tamed(mob/living/tamer, atom/food) visible_message(span_notice("[src] licks at [tamer] in a friendly manner!")) /// A dog bone fully heals a dog, and befriends it if it's not your friend. diff --git a/code/modules/mob/living/basic/pets/parrot/_parrot.dm b/code/modules/mob/living/basic/pets/parrot/_parrot.dm index 6dd5a9a40511e65..c23481d85a7ec1d 100644 --- a/code/modules/mob/living/basic/pets/parrot/_parrot.dm +++ b/code/modules/mob/living/basic/pets/parrot/_parrot.dm @@ -91,13 +91,7 @@ GLOBAL_LIST_INIT(strippable_parrot_items, create_strippable_list(list( AddElement(/datum/element/strippable, GLOB.strippable_parrot_items) AddElement(/datum/element/simple_flying) AddComponent(/datum/component/listen_and_repeat, desired_phrases = get_static_list_of_phrases(), blackboard_key = BB_PARROT_REPEAT_STRING) - AddComponent(\ - /datum/component/tameable,\ - food_types = edibles,\ - tame_chance = 100,\ - bonus_tame_chance = 0,\ - after_tame = CALLBACK(src, PROC_REF(tamed)),\ - ) + AddComponent(/datum/component/tameable, food_types = edibles, tame_chance = 100, bonus_tame_chance = 0) RegisterSignal(src, COMSIG_HOSTILE_PRE_ATTACKINGTARGET, PROC_REF(pre_attacking)) RegisterSignal(src, COMSIG_MOB_CLICKON, PROC_REF(on_click)) @@ -445,7 +439,7 @@ GLOBAL_LIST_INIT(strippable_parrot_items, create_strippable_list(list( return returnable_list -/mob/living/basic/parrot/proc/tamed() +/mob/living/basic/parrot/tamed(mob/living/tamer, atom/food) new /obj/effect/temp_visual/heart(drop_location()) /mob/living/basic/parrot/proc/drop_item_on_signal(mob/living/user) diff --git a/code/modules/mob/living/basic/pets/parrot/poly.dm b/code/modules/mob/living/basic/pets/parrot/poly.dm index f139a43d988df69..cba3dd6e588e322 100644 --- a/code/modules/mob/living/basic/pets/parrot/poly.dm +++ b/code/modules/mob/living/basic/pets/parrot/poly.dm @@ -197,6 +197,7 @@ butcher_results = list(/obj/item/ectoplasm = 1) ai_controller = /datum/ai_controller/basic_controller/parrot/ghost speech_probability_rate = 1 + resistance_flags = parent_type::resistance_flags | SHUTTLE_CRUSH_PROOF /mob/living/basic/parrot/poly/ghost/Initialize(mapload) // block anything and everything that could possibly happen with writing memory for ghosts diff --git a/code/modules/mob/living/basic/space_fauna/carp/carp.dm b/code/modules/mob/living/basic/space_fauna/carp/carp.dm index ebb6f1d23f7faa8..e0700892523fc79 100644 --- a/code/modules/mob/living/basic/space_fauna/carp/carp.dm +++ b/code/modules/mob/living/basic/space_fauna/carp/carp.dm @@ -95,10 +95,10 @@ AddComponent(/datum/component/aggro_emote, emote_list = string_list(list("gnashes"))) AddComponent(/datum/component/regenerator, outline_colour = regenerate_colour) if (tamer) - on_tamed(tamer, feedback = FALSE) + tamed(tamer, feedback = FALSE) befriend(tamer) else - AddComponent(/datum/component/tameable, food_types = list(/obj/item/food/meat), tame_chance = 10, bonus_tame_chance = 5, after_tame = CALLBACK(src, PROC_REF(on_tamed))) + AddComponent(/datum/component/tameable, food_types = list(/obj/item/food/meat), tame_chance = 10, bonus_tame_chance = 5) teleport = new(src) teleport.Grant(src) @@ -119,7 +119,7 @@ set_greyscale(colors = list(pick_weight(GLOB.carp_colors))) /// Called when another mob has forged a bond of friendship with this one, passed the taming mob as 'tamer' -/mob/living/basic/carp/proc/on_tamed(mob/tamer, feedback = TRUE) +/mob/living/basic/carp/tamed(mob/living/tamer, atom/food, feedback = TRUE) buckle_lying = 0 AddElement(/datum/element/ridable, ridable_data) AddComponent(/datum/component/obeys_commands, tamed_commands) diff --git a/code/modules/mob/living/basic/space_fauna/eyeball/_eyeball.dm b/code/modules/mob/living/basic/space_fauna/eyeball/_eyeball.dm index b72815d8325ab40..50685e1ebe0352d 100644 --- a/code/modules/mob/living/basic/space_fauna/eyeball/_eyeball.dm +++ b/code/modules/mob/living/basic/space_fauna/eyeball/_eyeball.dm @@ -58,7 +58,7 @@ grant_actions_by_list(innate_actions) AddElement(/datum/element/simple_flying) - AddComponent(/datum/component/tameable, food_types = list(/obj/item/food/grown/carrot), tame_chance = 100, after_tame = CALLBACK(src, PROC_REF(on_tame))) + AddComponent(/datum/component/tameable, food_types = list(/obj/item/food/grown/carrot), tame_chance = 100) ADD_TRAIT(src, TRAIT_SPACEWALK, INNATE_TRAIT) RegisterSignal(src, COMSIG_HOSTILE_PRE_ATTACKINGTARGET, PROC_REF(pre_attack)) on_hit_overlay = mutable_appearance(icon, "[icon_state]_crying") @@ -119,7 +119,7 @@ befriend(target) COOLDOWN_START(src, eye_healing, 15 SECONDS) -/mob/living/basic/eyeball/proc/on_tame(mob/tamer) +/mob/living/basic/eyeball/tamed(mob/living/tamer, atom/food) spin(spintime = 2 SECONDS, speed = 1) //become passive to the humens faction |= tamer.faction diff --git a/code/modules/mob/living/basic/space_fauna/ghost.dm b/code/modules/mob/living/basic/space_fauna/ghost.dm index 406d2ecefddc6b2..7545f9cfea39415 100644 --- a/code/modules/mob/living/basic/space_fauna/ghost.dm +++ b/code/modules/mob/living/basic/space_fauna/ghost.dm @@ -23,8 +23,8 @@ death_message = "wails, disintegrating into a pile of ectoplasm!" gold_core_spawnable = NO_SPAWN //too spooky for science light_system = OVERLAY_LIGHT - light_range = 1 // same glowing as visible player ghosts - light_power = 2 + light_range = 2.5 // same glowing as visible player ghosts + light_power = 0.6 ai_controller = /datum/ai_controller/basic_controller/ghost ///What hairstyle will this ghost have diff --git a/code/modules/mob/living/basic/space_fauna/netherworld/migo.dm b/code/modules/mob/living/basic/space_fauna/netherworld/migo.dm index 1be2a870de3ba7c..aab5a55aa4a1f39 100644 --- a/code/modules/mob/living/basic/space_fauna/netherworld/migo.dm +++ b/code/modules/mob/living/basic/space_fauna/netherworld/migo.dm @@ -36,6 +36,11 @@ /mob/living/basic/migo/Initialize(mapload) . = ..() migo_sounds = list('sound/items/bubblewrap.ogg', 'sound/items/change_jaws.ogg', 'sound/items/crowbar.ogg', 'sound/items/drink.ogg', 'sound/items/deconstruct.ogg', 'sound/items/carhorn.ogg', 'sound/items/change_drill.ogg', 'sound/items/dodgeball.ogg', 'sound/items/eatfood.ogg', 'sound/items/megaphone.ogg', 'sound/items/screwdriver.ogg', 'sound/items/weeoo1.ogg', 'sound/items/wirecutter.ogg', 'sound/items/welder.ogg', 'sound/items/zip.ogg', 'sound/items/rped.ogg', 'sound/items/ratchet.ogg', 'sound/items/polaroid1.ogg', 'sound/items/pshoom.ogg', 'sound/items/airhorn.ogg', 'sound/items/geiger/high1.ogg', 'sound/items/geiger/high2.ogg', 'sound/voice/beepsky/creep.ogg', 'sound/voice/beepsky/iamthelaw.ogg', 'sound/voice/ed209_20sec.ogg', 'sound/voice/hiss3.ogg', 'sound/voice/hiss6.ogg', 'sound/voice/medbot/patchedup.ogg', 'sound/voice/medbot/feelbetter.ogg', 'sound/voice/human/manlaugh1.ogg', 'sound/voice/human/womanlaugh.ogg', 'sound/weapons/sear.ogg', 'sound/ambience/antag/clockcultalr.ogg', 'sound/ambience/antag/ling_alert.ogg', 'sound/ambience/antag/tatoralert.ogg', 'sound/ambience/antag/monkey.ogg', 'sound/mecha/nominal.ogg', 'sound/mecha/weapdestr.ogg', 'sound/mecha/critdestr.ogg', 'sound/mecha/imag_enh.ogg', 'sound/effects/adminhelp.ogg', 'sound/effects/alert.ogg', 'sound/effects/attackblob.ogg', 'sound/effects/bamf.ogg', 'sound/effects/blobattack.ogg', 'sound/effects/break_stone.ogg', 'sound/effects/bubbles.ogg', 'sound/effects/bubbles2.ogg', 'sound/effects/clang.ogg', 'sound/effects/clockcult_gateway_disrupted.ogg', 'sound/effects/footstep/clownstep2.ogg', 'sound/effects/curse1.ogg', 'sound/effects/dimensional_rend.ogg', 'sound/effects/doorcreaky.ogg', 'sound/effects/empulse.ogg', 'sound/effects/explosion_distant.ogg', 'sound/effects/explosionfar.ogg', 'sound/effects/explosion1.ogg', 'sound/effects/grillehit.ogg', 'sound/effects/genetics.ogg', 'sound/effects/heart_beat.ogg', 'sound/runtime/hyperspace/hyperspace_begin.ogg', 'sound/runtime/hyperspace/hyperspace_end.ogg', 'sound/effects/his_grace_awaken.ogg', 'sound/effects/pai_boot.ogg', 'sound/effects/phasein.ogg', 'sound/effects/picaxe1.ogg', 'sound/effects/sparks1.ogg', 'sound/effects/smoke.ogg', 'sound/effects/splat.ogg', 'sound/effects/snap.ogg', 'sound/effects/tendril_destroyed.ogg', 'sound/effects/supermatter.ogg', 'sound/misc/desecration-01.ogg', 'sound/misc/desecration-02.ogg', 'sound/misc/desecration-03.ogg', 'sound/misc/bloblarm.ogg', 'sound/misc/airraid.ogg', 'sound/misc/bang.ogg','sound/misc/highlander.ogg', 'sound/misc/interference.ogg', 'sound/misc/notice1.ogg', 'sound/misc/notice2.ogg', 'sound/misc/sadtrombone.ogg', 'sound/misc/slip.ogg', 'sound/misc/splort.ogg', 'sound/weapons/armbomb.ogg', 'sound/weapons/beam_sniper.ogg', 'sound/weapons/chainsawhit.ogg', 'sound/weapons/emitter.ogg', 'sound/weapons/emitter2.ogg', 'sound/weapons/blade1.ogg', 'sound/weapons/bladeslice.ogg', 'sound/weapons/blastcannon.ogg', 'sound/weapons/blaster.ogg', 'sound/weapons/bulletflyby3.ogg', 'sound/weapons/circsawhit.ogg', 'sound/weapons/cqchit2.ogg', 'sound/weapons/drill.ogg', 'sound/weapons/genhit1.ogg', 'sound/weapons/gun/pistol/shot_suppressed.ogg', 'sound/weapons/gun/pistol/shot.ogg', 'sound/weapons/handcuffs.ogg', 'sound/weapons/homerun.ogg', 'sound/weapons/kinetic_accel.ogg', 'sound/machines/clockcult/steam_whoosh.ogg', 'sound/machines/fryer/deep_fryer_emerge.ogg', 'sound/machines/airlock.ogg', 'sound/machines/airlock_alien_prying.ogg', 'sound/machines/airlockclose.ogg', 'sound/machines/airlockforced.ogg', 'sound/machines/airlockopen.ogg', 'sound/machines/alarm.ogg', 'sound/machines/blender.ogg', 'sound/machines/boltsdown.ogg', 'sound/machines/boltsup.ogg', 'sound/machines/buzz-sigh.ogg', 'sound/machines/buzz-two.ogg', 'sound/machines/chime.ogg', 'sound/machines/cryo_warning.ogg', 'sound/machines/defib_charge.ogg', 'sound/machines/defib_failed.ogg', 'sound/machines/defib_ready.ogg', 'sound/machines/defib_zap.ogg', 'sound/machines/deniedbeep.ogg', 'sound/machines/ding.ogg', 'sound/machines/disposalflush.ogg', 'sound/machines/door_close.ogg', 'sound/machines/door_open.ogg', 'sound/machines/engine_alert1.ogg', 'sound/machines/engine_alert2.ogg', 'sound/machines/hiss.ogg', 'sound/machines/honkbot_evil_laugh.ogg', 'sound/machines/juicer.ogg', 'sound/machines/ping.ogg', 'sound/ambience/signal.ogg', 'sound/machines/synth_no.ogg', 'sound/machines/synth_yes.ogg', 'sound/machines/terminal_alert.ogg', 'sound/machines/triple_beep.ogg', 'sound/machines/twobeep.ogg', 'sound/machines/ventcrawl.ogg', 'sound/machines/warning-buzzer.ogg', 'sound/ai/default/outbreak5.ogg', 'sound/ai/default/outbreak7.ogg', 'sound/ai/default/poweroff.ogg', 'sound/ai/default/radiation.ogg', 'sound/ai/default/shuttlecalled.ogg', 'sound/ai/default/shuttledock.ogg', 'sound/ai/default/shuttlerecalled.ogg', 'sound/ai/default/aimalf.ogg') //hahahaha fuck you code divers + + if(!istype(src, /mob/living/basic/migo/hatsune) && prob(0.1)) // chance on-load mi-gos will spawn with a miku wig on (shiny variant) + new /mob/living/basic/migo/hatsune(get_turf(loc), mapload) + return INITIALIZE_HINT_QDEL + AddElement(/datum/element/swabable, CELL_LINE_TABLE_NETHER, CELL_VIRUS_TABLE_GENERIC_MOB, 1, 0) AddComponent(/datum/component/health_scaling_effects, min_health_slowdown = -1.5, additional_status_callback = CALLBACK(src, PROC_REF(update_dodge_chance))) @@ -71,3 +76,11 @@ . = Move(get_step(loc,pick(cdir, ccdir))) if(!.)//Can't dodge there so we just carry on . = Move(moving_to, move_direction) + +/// The special hatsune miku themed mi-go. +/mob/living/basic/migo/hatsune + name = "hatsune mi-go" + desc = parent_type::desc + " This one is wearing a bright blue wig." + icon_state = "mi-go-h" + icon_living = "mi-go-h" + gold_core_spawnable = NO_SPAWN diff --git a/code/modules/mob/living/basic/space_fauna/revenant/revenant_abilities.dm b/code/modules/mob/living/basic/space_fauna/revenant/revenant_abilities.dm index 63f4bbb9dbc3b90..ecfffb204bff1ca 100644 --- a/code/modules/mob/living/basic/space_fauna/revenant/revenant_abilities.dm +++ b/code/modules/mob/living/basic/space_fauna/revenant/revenant_abilities.dm @@ -206,6 +206,12 @@ bot.bot_cover_flags &= ~BOT_COVER_LOCKED bot.bot_cover_flags |= BOT_COVER_OPEN bot.emag_act(caster) + for(var/mob/living/basic/bot/bot in victim) + if(!(bot.bot_access_flags & BOT_COVER_EMAGGED)) + new /obj/effect/temp_visual/revenant(bot.loc) + bot.bot_access_flags |= BOT_CONTROL_PANEL_OPEN + bot.bot_access_flags |= BOT_MAINTS_PANEL_OPEN + bot.emag_act(caster) for(var/mob/living/carbon/human/human in victim) if(human == caster) continue diff --git a/code/modules/mob/living/basic/space_fauna/spider/giant_spider/giant_spider_subtrees.dm b/code/modules/mob/living/basic/space_fauna/spider/giant_spider/giant_spider_subtrees.dm index 56aacb11a961863..8682c8028e32e22 100644 --- a/code/modules/mob/living/basic/space_fauna/spider/giant_spider/giant_spider_subtrees.dm +++ b/code/modules/mob/living/basic/space_fauna/spider/giant_spider/giant_spider_subtrees.dm @@ -22,7 +22,7 @@ controller.clear_blackboard_key(target_key) var/turf/our_turf = get_turf(spider) - if (is_valid_web_turf(our_turf)) + if (is_valid_web_turf(our_turf, spider)) controller.set_blackboard_key(target_key, our_turf) finish_action(controller, succeeded = TRUE) return @@ -31,7 +31,7 @@ for (var/i in 1 to scan_range) turfs_by_range["[i]"] = list() for (var/turf/turf_in_view in oview(scan_range, our_turf)) - if (!is_valid_web_turf(turf_in_view)) + if (!is_valid_web_turf(turf_in_view, spider)) continue turfs_by_range["[get_dist(our_turf, turf_in_view)]"] += turf_in_view 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 fa44cb35b2d1216..5bb27b5109cbdca 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 @@ -3,7 +3,7 @@ name = "Spin Web" desc = "Spin a web to slow down potential prey." button_icon = 'icons/mob/actions/actions_animal.dmi' - button_icon_state = "lay_web" + button_icon_state = "spider_web" background_icon_state = "bg_alien" overlay_icon_state = "bg_alien_border" cooldown_time = 0 SECONDS @@ -17,10 +17,12 @@ . = ..() if (!owner) return + ADD_TRAIT(owner, TRAIT_WEB_WEAVER, REF(src)) RegisterSignals(owner, list(COMSIG_MOVABLE_MOVED, COMSIG_DO_AFTER_BEGAN, COMSIG_DO_AFTER_ENDED), PROC_REF(update_status_on_signal)) /datum/action/cooldown/mob_cooldown/lay_web/Remove(mob/removed_from) . = ..() + REMOVE_TRAIT(removed_from, TRAIT_WEB_WEAVER, REF(src)) UnregisterSignal(removed_from, list(COMSIG_MOVABLE_MOVED, COMSIG_DO_AFTER_BEGAN, COMSIG_DO_AFTER_ENDED)) /datum/action/cooldown/mob_cooldown/lay_web/IsAvailable(feedback = FALSE) @@ -72,7 +74,7 @@ /// Variant for genetics, created webs only allow the creator passage /datum/action/cooldown/mob_cooldown/lay_web/genetic desc = "Spin a web. Only you will be able to traverse your web easily." - cooldown_time = 4 SECONDS //the same time to lay a web + cooldown_time = 4 SECONDS /datum/action/cooldown/mob_cooldown/lay_web/genetic/plant_web(turf/target_turf, obj/structure/spider/stickyweb/existing_web) new /obj/structure/spider/stickyweb/genetic(target_turf, owner) @@ -94,20 +96,20 @@ /datum/action/cooldown/mob_cooldown/lay_web/solid_web name = "Spin Solid Web" desc = "Spin a web to obstruct potential prey." - button_icon_state = "lay_solid_web" + button_icon_state = "spider_wall" cooldown_time = 0 SECONDS webbing_time = 5 SECONDS /datum/action/cooldown/mob_cooldown/lay_web/solid_web/obstructed_by_other_web() - return !!(locate(/obj/structure/spider/solid) in get_turf(owner)) + return !!(locate(/obj/structure/spider/stickyweb/sealed/tough) in get_turf(owner)) /datum/action/cooldown/mob_cooldown/lay_web/solid_web/plant_web(turf/target_turf, obj/structure/spider/stickyweb/existing_web) - new /obj/structure/spider/solid(target_turf) + new /obj/structure/spider/stickyweb/sealed/tough(target_turf) /datum/action/cooldown/mob_cooldown/lay_web/web_passage name = "Spin Web Passage" desc = "Spin a web passage to hide the nest from prey view." - button_icon_state = "lay_web_passage" + button_icon_state = "spider_roof" cooldown_time = 0 SECONDS webbing_time = 4 SECONDS @@ -120,20 +122,20 @@ /datum/action/cooldown/mob_cooldown/lay_web/sticky_web name = "Spin Sticky Web" desc = "Spin a sticky web to trap intruders." - button_icon_state = "lay_sticky_web" + button_icon_state = "spider_ropes" cooldown_time = 20 SECONDS webbing_time = 3 SECONDS /datum/action/cooldown/mob_cooldown/lay_web/sticky_web/obstructed_by_other_web() - return !!(locate(/obj/structure/spider/sticky) in get_turf(owner)) + return !!(locate(/obj/structure/spider/stickyweb/very_sticky) in get_turf(owner)) /datum/action/cooldown/mob_cooldown/lay_web/sticky_web/plant_web(turf/target_turf, obj/structure/spider/stickyweb/existing_web) - new /obj/structure/spider/sticky(target_turf) + new /obj/structure/spider/stickyweb/very_sticky(target_turf) /datum/action/cooldown/mob_cooldown/lay_web/web_spikes name = "Spin Web Spikes" desc = "Extrude silk spikes to dissuade invaders." - button_icon_state = "lay_web_spikes" + button_icon_state = "spider_spikes" cooldown_time = 40 SECONDS webbing_time = 3 SECONDS @@ -174,12 +176,12 @@ /datum/action/cooldown/mob_cooldown/lay_web/web_reflector name = "Spin reflective silk screen" desc = "Spin a web to reflect missiles from the nest." - button_icon_state = "lay_web_reflector" + button_icon_state = "spider_mirror" cooldown_time = 30 SECONDS webbing_time = 4 SECONDS /datum/action/cooldown/mob_cooldown/lay_web/web_reflector/obstructed_by_other_web() - return !!(locate(/obj/structure/spider/reflector) in get_turf(owner)) + return !!(locate(/obj/structure/spider/stickyweb/sealed/reflector) in get_turf(owner)) /datum/action/cooldown/mob_cooldown/lay_web/web_reflector/plant_web(turf/target_turf, obj/structure/spider/stickyweb/existing_web) - new /obj/structure/spider/reflector(target_turf) + new /obj/structure/spider/stickyweb/sealed/reflector(target_turf) diff --git a/code/modules/mob/living/basic/vermin/mouse.dm b/code/modules/mob/living/basic/vermin/mouse.dm index c1ba3c12e364b06..cf12c2b4083d59d 100644 --- a/code/modules/mob/living/basic/vermin/mouse.dm +++ b/code/modules/mob/living/basic/vermin/mouse.dm @@ -63,7 +63,7 @@ if (tame) faction |= FACTION_NEUTRAL else - AddComponent(/datum/component/tameable, food_types = list(/obj/item/food/cheese), tame_chance = 100, after_tame = CALLBACK(src, PROC_REF(tamed))) + AddComponent(/datum/component/tameable, food_types = list(/obj/item/food/cheese), tame_chance = 100) /mob/living/basic/mouse/Destroy() SSmobs.cheeserats -= src @@ -148,7 +148,7 @@ to_chat(entered, span_notice("[icon2html(src, entered)] Squeak!")) /// Called when a mouse is hand-fed some cheese, it will stop being afraid of humans -/mob/living/basic/mouse/proc/tamed(mob/living/tamer, obj/item/food/cheese/cheese) +/mob/living/basic/mouse/tamed(mob/living/tamer, obj/item/food/cheese/cheese) new /obj/effect/temp_visual/heart(loc) faction |= FACTION_NEUTRAL tame = TRUE diff --git a/code/modules/mob/living/carbon/alien/adult/adult.dm b/code/modules/mob/living/carbon/alien/adult/adult.dm index 2cab03d670e590d..bbacffd4f6f32c5 100644 --- a/code/modules/mob/living/carbon/alien/adult/adult.dm +++ b/code/modules/mob/living/carbon/alien/adult/adult.dm @@ -143,6 +143,9 @@ GLOBAL_LIST_INIT(strippable_alien_humanoid_items, create_strippable_list(list( melting_pot.consume_thing(lucky_winner) return TRUE +/mob/living/carbon/alien/adult/get_butt_sprite() + return BUTT_SPRITE_XENOMORPH + // Aliens can touch acid /mob/living/carbon/alien/can_touch_acid(atom/acided_atom, acid_power, acid_volume) return TRUE diff --git a/code/modules/mob/living/carbon/alien/larva/powers.dm b/code/modules/mob/living/carbon/alien/larva/powers.dm index 93937adaeaf8483..7aeb94d448f8a9e 100644 --- a/code/modules/mob/living/carbon/alien/larva/powers.dm +++ b/code/modules/mob/living/carbon/alien/larva/powers.dm @@ -13,6 +13,7 @@ span_notice("[owner] slowly peeks up from the ground..."), span_noticealien("You stop hiding."), ) + ADD_TRAIT(owner, TRAIT_IGNORE_ELEVATION, ACTION_TRAIT) else owner.layer = hide_layer @@ -20,6 +21,7 @@ span_name("[owner] scurries to the ground!"), span_noticealien("You are now hiding."), ) + REMOVE_TRAIT(owner, TRAIT_IGNORE_ELEVATION, ACTION_TRAIT) return TRUE diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm index f19ca047c8c3ca4..4629f6e7efbd486 100644 --- a/code/modules/mob/living/carbon/carbon.dm +++ b/code/modules/mob/living/carbon/carbon.dm @@ -815,8 +815,7 @@ hud_used.stamina.icon_state = "stamina_full" /mob/living/carbon/proc/update_spacesuit_hud_icon(cell_state = "empty") - if(hud_used?.spacesuit) - hud_used.spacesuit.icon_state = "spacesuit_[cell_state]" + hud_used?.spacesuit?.icon_state = "spacesuit_[cell_state]" /mob/living/carbon/set_health(new_value) . = ..() diff --git a/code/modules/mob/living/carbon/human/_species.dm b/code/modules/mob/living/carbon/human/_species.dm index f361a3dcfb2f61a..fb2e30754432b80 100644 --- a/code/modules/mob/living/carbon/human/_species.dm +++ b/code/modules/mob/living/carbon/human/_species.dm @@ -167,9 +167,6 @@ GLOBAL_LIST_EMPTY(features_by_species) ///Unique cookie given by admins through prayers var/species_cookie = /obj/item/food/cookie - ///For custom overrides for species ass images - var/icon/ass_image - /// List of family heirlooms this species can get with the family heirloom quirk. List of types. var/list/family_heirlooms @@ -1423,7 +1420,7 @@ GLOBAL_LIST_EMPTY(features_by_species) humi.throw_alert(ALERT_TEMPERATURE, /atom/movable/screen/alert/hot, 3) // Body temperature is too cold, and we do not have resist traits - else if(bodytemp < bodytemp_cold_damage_limit && !HAS_TRAIT(humi, TRAIT_RESISTCOLD)) + else if(bodytemp < bodytemp_cold_damage_limit && !HAS_TRAIT(humi, TRAIT_RESISTCOLD) && !humi.has_status_effect(/datum/status_effect/inebriated)) // clear any hot moods and apply cold mood humi.clear_mood_event("hot") humi.add_mood_event("cold", /datum/mood_event/cold) diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index 4d5f9bfc234c869..dc3bddf3d901e95 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -61,7 +61,7 @@ /mob/living/carbon/human/Destroy() QDEL_NULL(physiology) if(biowares) - QDEL_LIST(biowares) + QDEL_LAZYLIST(biowares) GLOB.human_list -= src if (mob_mood) @@ -381,6 +381,10 @@ var/obj/item/bodypart/the_part = isbodypart(target_zone) ? target_zone : get_bodypart(check_zone(target_zone)) //keep these synced to_chat(user, span_alert("There is no exposed flesh or thin material on [p_their()] [the_part.name].")) +/mob/living/carbon/human/get_butt_sprite() + var/obj/item/bodypart/chest/chest = get_bodypart(BODY_ZONE_CHEST) + return chest?.get_butt_sprite() + /mob/living/carbon/human/get_footprint_sprite() var/obj/item/bodypart/leg/L = get_bodypart(BODY_ZONE_R_LEG) || get_bodypart(BODY_ZONE_L_LEG) return shoes?.footprint_sprite || L?.footprint_sprite @@ -391,7 +395,7 @@ if(judgement_criteria & JUDGE_EMAGGED || HAS_TRAIT(src, TRAIT_ALWAYS_WANTED)) return 10 //Everyone is a criminal! - var/threatcount = 0 + var/threatcount = judgement_criteria & JUDGE_CHILLOUT ? -THREAT_ASSESS_DANGEROUS : 0 //Lasertag bullshit if(lasercolor) diff --git a/code/modules/mob/living/carbon/human/species_types/abductors.dm b/code/modules/mob/living/carbon/human/species_types/abductors.dm index 74d2bedf3a70251..1eae13b0a5b2825 100644 --- a/code/modules/mob/living/carbon/human/species_types/abductors.dm +++ b/code/modules/mob/living/carbon/human/species_types/abductors.dm @@ -19,7 +19,6 @@ mutantlungs = null mutantbrain = /obj/item/organ/internal/brain/abductor changesource_flags = MIRROR_BADMIN | WABBAJACK | MIRROR_PRIDE | MIRROR_MAGIC | RACE_SWAP | ERT_SPAWN | SLIME_EXTRACT - ass_image = 'icons/ass/assgrey.png' bodypart_overrides = list( BODY_ZONE_HEAD = /obj/item/bodypart/head/abductor, diff --git a/code/modules/mob/living/carbon/human/species_types/felinid.dm b/code/modules/mob/living/carbon/human/species_types/felinid.dm index b3b18b53a24c2f4..7c41b25efb6a44a 100644 --- a/code/modules/mob/living/carbon/human/species_types/felinid.dm +++ b/code/modules/mob/living/carbon/human/species_types/felinid.dm @@ -20,7 +20,6 @@ changesource_flags = MIRROR_BADMIN | WABBAJACK | MIRROR_PRIDE | MIRROR_MAGIC | RACE_SWAP | ERT_SPAWN | SLIME_EXTRACT species_language_holder = /datum/language_holder/felinid payday_modifier = 1.0 - ass_image = 'icons/ass/asscat.png' family_heirlooms = list(/obj/item/toy/cattoy) /// When false, this is a felinid created by mass-purrbation var/original_felinid = TRUE diff --git a/code/modules/mob/living/carbon/human/species_types/jellypeople.dm b/code/modules/mob/living/carbon/human/species_types/jellypeople.dm index 96f91f6a379f5e9..75b0aa2947fde90 100644 --- a/code/modules/mob/living/carbon/human/species_types/jellypeople.dm +++ b/code/modules/mob/living/carbon/human/species_types/jellypeople.dm @@ -30,7 +30,6 @@ changesource_flags = MIRROR_BADMIN | WABBAJACK | MIRROR_PRIDE | MIRROR_MAGIC | RACE_SWAP | ERT_SPAWN | SLIME_EXTRACT inherent_factions = list(FACTION_SLIME) species_language_holder = /datum/language_holder/jelly - ass_image = 'icons/ass/assslime.png' bodypart_overrides = list( BODY_ZONE_L_ARM = /obj/item/bodypart/arm/left/jelly, diff --git a/code/modules/mob/living/carbon/human/species_types/lizardpeople.dm b/code/modules/mob/living/carbon/human/species_types/lizardpeople.dm index 81b7d5d79f5ffcc..4c185d398f0cccf 100644 --- a/code/modules/mob/living/carbon/human/species_types/lizardpeople.dm +++ b/code/modules/mob/living/carbon/human/species_types/lizardpeople.dm @@ -34,8 +34,6 @@ bodytemp_heat_damage_limit = BODYTEMP_HEAT_LAVALAND_SAFE bodytemp_cold_damage_limit = (BODYTEMP_COLD_DAMAGE_LIMIT - 10) - ass_image = 'icons/ass/asslizard.png' - bodypart_overrides = list( BODY_ZONE_HEAD = /obj/item/bodypart/head/lizard, BODY_ZONE_CHEST = /obj/item/bodypart/chest/lizard, diff --git a/code/modules/mob/living/carbon/human/species_types/plasmamen.dm b/code/modules/mob/living/carbon/human/species_types/plasmamen.dm index b6fe0234bac5fcb..9c59d4d1a9c60e5 100644 --- a/code/modules/mob/living/carbon/human/species_types/plasmamen.dm +++ b/code/modules/mob/living/carbon/human/species_types/plasmamen.dm @@ -51,13 +51,17 @@ // This effects how fast body temp stabilizes, also if cold resit is lost on the mob bodytemp_cold_damage_limit = (BODYTEMP_COLD_DAMAGE_LIMIT - 50) // about -50c - ass_image = 'icons/ass/assplasma.png' - outfit_override_registry = list( /datum/outfit/syndicate = /datum/outfit/syndicate/plasmaman, /datum/outfit/syndicate/full = /datum/outfit/syndicate/full/plasmaman, /datum/outfit/syndicate/leader = /datum/outfit/syndicate/leader/plasmaman, /datum/outfit/syndicate/reinforcement = /datum/outfit/syndicate/reinforcement/plasmaman, + /datum/outfit/syndicate/reinforcement/cybersun = /datum/outfit/syndicate/reinforcement/plasmaman, + /datum/outfit/syndicate/reinforcement/donk = /datum/outfit/syndicate/reinforcement/plasmaman, + /datum/outfit/syndicate/reinforcement/gorlex = /datum/outfit/syndicate/reinforcement/plasmaman, + /datum/outfit/syndicate/reinforcement/interdyne = /datum/outfit/syndicate/reinforcement/plasmaman, + /datum/outfit/syndicate/reinforcement/mi13 = /datum/outfit/syndicate/reinforcement/plasmaman, + /datum/outfit/syndicate/reinforcement/waffle = /datum/outfit/syndicate/reinforcement/plasmaman, ) /// If the bones themselves are burning clothes won't help you much diff --git a/code/modules/mob/living/carbon/human/species_types/podpeople.dm b/code/modules/mob/living/carbon/human/species_types/podpeople.dm index 5cf2355c86c3e1d..78a248a7f9e9df5 100644 --- a/code/modules/mob/living/carbon/human/species_types/podpeople.dm +++ b/code/modules/mob/living/carbon/human/species_types/podpeople.dm @@ -29,8 +29,6 @@ BODY_ZONE_CHEST = /obj/item/bodypart/chest/pod, ) - ass_image = 'icons/ass/asspodperson.png' - /datum/species/pod/on_species_gain(mob/living/carbon/new_podperson, datum/species/old_species, pref_load) . = ..() if(ishuman(new_podperson)) diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index ad61cf4d00d9754..922aab7cbf616fc 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -524,7 +524,7 @@ log_message("points at [pointing_at]", LOG_EMOTE) visible_message("[span_name("[src]")] points at [pointing_at].", span_notice("You point at [pointing_at].")) -/mob/living/verb/succumb(whispered as null) +/mob/living/verb/succumb(whispered as num|null) set hidden = TRUE if (!CAN_SUCCUMB(src)) if(HAS_TRAIT(src, TRAIT_SUCCUMB_OVERRIDE)) @@ -2330,6 +2330,9 @@ GLOBAL_LIST_EMPTY(fire_appearances) /mob/living/proc/is_face_visible() return TRUE +/// Sprite to show for photocopying mob butts +/mob/living/proc/get_butt_sprite() + return null ///Proc to modify the value of num_legs and hook behavior associated to this event. /mob/living/proc/set_num_legs(new_value) @@ -2722,3 +2725,20 @@ GLOBAL_LIST_EMPTY(fire_appearances) end_look_down() else look_down() + +/** + * Totals the physical cash on the mob and returns the total. + */ +/mob/living/verb/tally_physical_credits() + //Here is all the possible non-ID payment methods. + var/list/counted_money = list() + var/physical_cash_total = 0 + for(var/obj/item/credit as anything in typecache_filter_list(get_all_contents(), GLOB.allowed_money)) //Coins, cash, and credits. + physical_cash_total += credit.get_item_credit_value() + counted_money += credit + + if(is_type_in_typecache(pulling, GLOB.allowed_money)) //Coins(Pulled). + var/obj/item/counted_credit = pulling + physical_cash_total += counted_credit.get_item_credit_value() + counted_money += counted_credit + return round(physical_cash_total) diff --git a/code/modules/mob/living/living_say.dm b/code/modules/mob/living/living_say.dm index 8f5bc33d04149e8..0f6a0c1a1334d73 100644 --- a/code/modules/mob/living/living_say.dm +++ b/code/modules/mob/living/living_say.dm @@ -109,7 +109,7 @@ GLOBAL_LIST_INIT(message_modes_stat_limits, list( var/original_message = message message = get_message_mods(message, message_mods) saymode = SSradio.saymodes[message_mods[RADIO_KEY]] - if (!forced) + if (!forced && !saymode) message = check_for_custom_say_emote(message, message_mods) if(!message) diff --git a/code/modules/mob/living/silicon/robot/robot.dm b/code/modules/mob/living/silicon/robot/robot.dm index 01dbafd4f611354..8e055273e79b97e 100644 --- a/code/modules/mob/living/silicon/robot/robot.dm +++ b/code/modules/mob/living/silicon/robot/robot.dm @@ -478,7 +478,7 @@ SIGNAL_HANDLER if(lamp_enabled) toggle_headlamp(TRUE) - to_chat(src, span_warning("Your headlamp was forcibly turned off. Restarting it should fix it, though.")) + balloon_alert(src, "headlamp off!") return COMSIG_SABOTEUR_SUCCESS /** @@ -972,6 +972,12 @@ buckle_mob_flags= RIDER_NEEDS_ARM // just in case return ..() +/mob/living/silicon/robot/can_resist() + if(lockcharge) + balloon_alert(src, "locked down!") + return FALSE + return ..() + /mob/living/silicon/robot/execute_resist() . = ..() if(!has_buckled_mobs()) @@ -979,7 +985,6 @@ for(var/mob/unbuckle_me_now as anything in buckled_mobs) unbuckle_mob(unbuckle_me_now, FALSE) - /mob/living/silicon/robot/proc/TryConnectToAI() set_connected_ai(select_active_ai_with_fewest_borgs(z)) if(connected_ai) diff --git a/code/modules/mob/living/silicon/robot/robot_defines.dm b/code/modules/mob/living/silicon/robot/robot_defines.dm index d0c47141ffe5c05..0a0eea4fdd01723 100644 --- a/code/modules/mob/living/silicon/robot/robot_defines.dm +++ b/code/modules/mob/living/silicon/robot/robot_defines.dm @@ -4,7 +4,6 @@ * Definitions for /mob/living/silicon/robot and its children, including AI shells. * */ - /mob/living/silicon/robot name = "Cyborg" real_name = "Cyborg" diff --git a/code/modules/mob/living/silicon/silicon.dm b/code/modules/mob/living/silicon/silicon.dm index a399d0a7bafe74d..fb201faeeee6aa4 100644 --- a/code/modules/mob/living/silicon/silicon.dm +++ b/code/modules/mob/living/silicon/silicon.dm @@ -441,6 +441,9 @@ /mob/living/silicon/on_standing_up() return // Silicons are always standing by default. +/mob/living/silicon/get_butt_sprite() + return BUTT_SPRITE_QR_CODE + /** * Records an IC event log entry in the cyborg's internal tablet. * diff --git a/code/modules/mob/living/silicon/silicon_say.dm b/code/modules/mob/living/silicon/silicon_say.dm index 54c4a4f82d1c664..4592097dfa8e549 100644 --- a/code/modules/mob/living/silicon/silicon_say.dm +++ b/code/modules/mob/living/silicon/silicon_say.dm @@ -17,6 +17,11 @@ spans ) + var/namepart = name + // If carbon, use voice to account for voice changers + if(iscarbon(src)) + namepart = GetVoice() + for(var/mob/M in GLOB.player_list) if(M.binarycheck()) if(isAI(M)) @@ -24,7 +29,7 @@ M, span_binarysay("\ Robotic Talk, \ - [span_name("[name] ([designation])")] \ + [span_name("[namepart] ([designation])")] \ [quoted_message]\ "), avoid_highlighting = src == M @@ -34,7 +39,7 @@ M, span_binarysay("\ Robotic Talk, \ - [span_name("[name]")] [quoted_message]\ + [span_name("[namepart]")] [quoted_message]\ "), avoid_highlighting = src == M ) @@ -56,7 +61,7 @@ span_binarysay("\ [follow_link] \ Robotic Talk, \ - [span_name("[name]")] [quoted_message]\ + [span_name("[namepart]")] [quoted_message]\ "), avoid_highlighting = src == M ) diff --git a/code/modules/mob/living/simple_animal/bot/bot.dm b/code/modules/mob/living/simple_animal/bot/bot.dm index ff304332c8df6a3..99dc3b504b69fe1 100644 --- a/code/modules/mob/living/simple_animal/bot/bot.dm +++ b/code/modules/mob/living/simple_animal/bot/bot.dm @@ -25,7 +25,7 @@ faction = list(FACTION_NEUTRAL, FACTION_SILICON, FACTION_TURRET) light_system = OVERLAY_LIGHT light_range = 3 - light_power = 0.9 + light_power = 0.6 del_on_death = TRUE ///Will other (noncommissioned) bots salute this bot? diff --git a/code/modules/mob/living/simple_animal/bot/ed209bot.dm b/code/modules/mob/living/simple_animal/bot/ed209bot.dm index e91b532d96c8d78..6c0cd6d16ab55ca 100644 --- a/code/modules/mob/living/simple_animal/bot/ed209bot.dm +++ b/code/modules/mob/living/simple_animal/bot/ed209bot.dm @@ -2,6 +2,7 @@ name = "\improper ED-209 Security Robot" desc = "A security robot. He looks less than thrilled." icon_state = "ed209" + light_color = "#f84e4e" density = TRUE health = 100 maxHealth = 100 diff --git a/code/modules/mob/living/simple_animal/bot/firebot.dm b/code/modules/mob/living/simple_animal/bot/firebot.dm index da07d6f0efd1706..a210a2e23663d69 100644 --- a/code/modules/mob/living/simple_animal/bot/firebot.dm +++ b/code/modules/mob/living/simple_animal/bot/firebot.dm @@ -9,6 +9,8 @@ desc = "A little fire extinguishing bot. He looks rather anxious." icon = 'icons/mob/silicon/aibots.dmi' icon_state = "firebot1" + light_color = "#8cffc9" + light_power = 0.8 density = FALSE anchored = FALSE health = 25 diff --git a/code/modules/mob/living/simple_animal/bot/honkbot.dm b/code/modules/mob/living/simple_animal/bot/honkbot.dm index 1c77043eb1ff709..6a2ed0bbef40c81 100644 --- a/code/modules/mob/living/simple_animal/bot/honkbot.dm +++ b/code/modules/mob/living/simple_animal/bot/honkbot.dm @@ -2,6 +2,8 @@ name = "\improper Honkbot" desc = "A little robot. It looks happy with its bike horn." icon_state = "honkbot" + light_color = "#e084f7" + light_power = 1 damage_coeff = list(BRUTE = 1, BURN = 1, TOX = 0, STAMINA = 0, OXY = 0) combat_mode = FALSE diff --git a/code/modules/mob/living/simple_animal/bot/mulebot.dm b/code/modules/mob/living/simple_animal/bot/mulebot.dm index 7f13a1954ab8484..833ed124f6dc60c 100644 --- a/code/modules/mob/living/simple_animal/bot/mulebot.dm +++ b/code/modules/mob/living/simple_animal/bot/mulebot.dm @@ -13,6 +13,8 @@ name = "\improper MULEbot" desc = "A Multiple Utility Load Effector bot." icon_state = "mulebot0" + light_color = "#ffcc99" + light_power = 0.8 density = TRUE move_resist = MOVE_FORCE_STRONG animate_movement = SLIDE_STEPS diff --git a/code/modules/mob/living/simple_animal/bot/secbot.dm b/code/modules/mob/living/simple_animal/bot/secbot.dm index f4241809b339ace..76043693b05e7df 100644 --- a/code/modules/mob/living/simple_animal/bot/secbot.dm +++ b/code/modules/mob/living/simple_animal/bot/secbot.dm @@ -3,6 +3,8 @@ desc = "A little security robot. He looks less than thrilled." icon = 'icons/mob/silicon/aibots.dmi' icon_state = "secbot" + light_color = "#f56275" + light_power = 0.8 density = FALSE anchored = FALSE health = 25 @@ -95,6 +97,7 @@ /mob/living/simple_animal/bot/secbot/pingsky name = "Officer Pingsky" desc = "It's Officer Pingsky! Delegated to satellite guard duty for harbouring anti-human sentiment." + light_color = "#62baf5" radio_channel = RADIO_CHANNEL_AI_PRIVATE bot_mode_flags = ~(BOT_MODE_CAN_BE_SAPIENT|BOT_MODE_AUTOPATROL) security_mode_flags = SECBOT_DECLARE_ARRESTS | SECBOT_CHECK_IDS | SECBOT_CHECK_RECORDS @@ -129,6 +132,7 @@ ) AddElement(/datum/element/connect_loc, loc_connections) AddComponent(/datum/component/security_vision, judgement_criteria = NONE, update_judgement_criteria = CALLBACK(src, PROC_REF(judgement_criteria))) + RegisterSignal(src, COMSIG_HIT_BY_SABOTEUR, PROC_REF(on_saboteur)) /mob/living/simple_animal/bot/secbot/Destroy() QDEL_NULL(weapon) @@ -152,6 +156,16 @@ SSmove_manager.stop_looping(src) last_found = world.time +/mob/living/simple_animal/bot/secbot/proc/on_saboteur(datum/source, disrupt_duration) + SIGNAL_HANDLER + if(!(security_mode_flags & SECBOT_SABOTEUR_AFFECTED)) + security_mode_flags |= SECBOT_SABOTEUR_AFFECTED + addtimer(CALLBACK(src, PROC_REF(remove_saboteur_effect)), disrupt_duration) + return COMSIG_SABOTEUR_SUCCESS + +/mob/living/simple_animal/bot/secbot/proc/remove_saboteur_effect() + security_mode_flags &= ~SECBOT_SABOTEUR_AFFECTED + /mob/living/simple_animal/bot/secbot/electrocute_act(shock_damage, source, siemens_coeff = 1, flags = NONE)//shocks only make him angry if(base_speed < initial(base_speed) + 3) base_speed += 3 @@ -215,6 +229,8 @@ final |= JUDGE_RECORDCHECK if(security_mode_flags & SECBOT_CHECK_WEAPONS) final |= JUDGE_WEAPONCHECK + if(security_mode_flags & SECBOT_SABOTEUR_AFFECTED) + final |= JUDGE_CHILLOUT return final /mob/living/simple_animal/bot/secbot/proc/special_retaliate_after_attack(mob/user) //allows special actions to take place after being attacked. diff --git a/code/modules/mob/living/simple_animal/bot/vibebot.dm b/code/modules/mob/living/simple_animal/bot/vibebot.dm index d0d550f77379a7a..582b1b5371da5e6 100644 --- a/code/modules/mob/living/simple_animal/bot/vibebot.dm +++ b/code/modules/mob/living/simple_animal/bot/vibebot.dm @@ -10,8 +10,8 @@ maxHealth = 25 pass_flags = PASSMOB | PASSFLAPS light_system = OVERLAY_LIGHT - light_range = 7 - light_power = 3 + light_range = 6 + light_power = 2 hackables = "vibing scanners" radio_key = /obj/item/encryptionkey/headset_service diff --git a/code/modules/mob/living/simple_animal/hostile/alien.dm b/code/modules/mob/living/simple_animal/hostile/alien.dm index 593bf29535edcde..8ce6d28f2ab6200 100644 --- a/code/modules/mob/living/simple_animal/hostile/alien.dm +++ b/code/modules/mob/living/simple_animal/hostile/alien.dm @@ -110,6 +110,9 @@ egg_cooldown = initial(egg_cooldown) LayEggs() +/mob/living/simple_animal/hostile/alien/get_butt_sprite() + return BUTT_SPRITE_XENOMORPH + /mob/living/simple_animal/hostile/alien/proc/SpreadPlants() if(!isturf(loc) || isspaceturf(loc)) return diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm index ac9031f59c33f98..b8ad73c413c3344 100644 --- a/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm +++ b/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm @@ -166,7 +166,9 @@ layer = FLY_LAYER plane = ABOVE_GAME_PLANE light_system = OVERLAY_LIGHT - light_range = 2 + light_range = 2.5 + light_power = 1.2 + light_color = "#ffff66" duration = 8 var/target 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 375d4993cfdda57..d7fceecf0532f9b 100644 --- a/code/modules/mob/living/simple_animal/hostile/megafauna/hierophant.dm +++ b/code/modules/mob/living/simple_animal/hostile/megafauna/hierophant.dm @@ -618,6 +618,7 @@ Difficulty: Hard moving-- sleep(speed) targetturf = get_turf(target) + /obj/effect/temp_visual/hierophant/chaser/proc/make_blast() var/obj/effect/temp_visual/hierophant/blast/damaging/B = new(loc, caster, friendly_fire_check) B.damage = damage 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 6386fa272b7eb8d..a7edcb6ed0c8c3c 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 @@ -386,7 +386,7 @@ While using this makes the system rely on OnFire, it still gives options for tim to_chat(E, "Note that you now share the loyalties of [user]. You are expected not to intentionally sabotage their faction unless commanded to!") E.maxHealth = E.maxHealth * 0.4 E.health = E.maxHealth - E.desc = "[E.desc] However, this one appears appears less wild in nature, and calmer around people." + E.desc = "[E.desc] However, this one appears to be less wild in nature, and calmer around people." E.sentience_type = SENTIENCE_ORGANIC qdel(src) else diff --git a/code/modules/mob/living/simple_animal/hostile/mining_mobs/wolf.dm b/code/modules/mob/living/simple_animal/hostile/mining_mobs/wolf.dm deleted file mode 100644 index 56a8c77e2fd8b61..000000000000000 --- a/code/modules/mob/living/simple_animal/hostile/mining_mobs/wolf.dm +++ /dev/null @@ -1,72 +0,0 @@ -/mob/living/simple_animal/hostile/asteroid/wolf - name = "white wolf" - desc = "A beast that survives by feasting on weaker opponents, they're much stronger with numbers." - icon = 'icons/mob/simple/icemoon/icemoon_monsters.dmi' - icon_state = "whitewolf" - icon_living = "whitewolf" - icon_dead = "whitewolf_dead" - mob_biotypes = MOB_ORGANIC|MOB_BEAST - mouse_opacity = MOUSE_OPACITY_ICON - friendly_verb_continuous = "howls at" - friendly_verb_simple = "howl at" - speak_emote = list("howls") - speed = 5 - move_to_delay = 5 - maxHealth = 130 - health = 130 - obj_damage = 15 - melee_damage_lower = 7.5 - melee_damage_upper = 7.5 - rapid_melee = 2 // every second attack - dodging = TRUE - dodge_prob = 50 - attack_verb_continuous = "bites" - attack_verb_simple = "bite" - attack_sound = 'sound/weapons/bite.ogg' - attack_vis_effect = ATTACK_EFFECT_BITE - vision_range = 7 - aggro_vision_range = 7 - move_force = MOVE_FORCE_WEAK - move_resist = MOVE_FORCE_WEAK - pull_force = MOVE_FORCE_WEAK - butcher_results = list(/obj/item/food/meat/slab = 2, /obj/item/stack/sheet/sinew/wolf = 2, /obj/item/stack/sheet/bone = 2) - loot = list() - crusher_loot = /obj/item/crusher_trophy/wolf_ear - stat_attack = HARD_CRIT - robust_searching = TRUE - footstep_type = FOOTSTEP_MOB_CLAW - /// Message for when the wolf decides to start running away - var/retreat_message_said = FALSE - -/mob/living/simple_animal/hostile/asteroid/wolf/Move(atom/newloc) - if(newloc && newloc.z == z && (islava(newloc) || ischasm(newloc))) - return FALSE - return ..() - -/mob/living/simple_animal/hostile/asteroid/wolf/adjustHealth(amount, updating_health = TRUE, forced = FALSE) - . = ..() - if(stat == DEAD || health > maxHealth*0.1) - retreat_distance = initial(retreat_distance) - return - if(!retreat_message_said && target) - visible_message(span_danger("The [name] tries to flee from [target]!")) - retreat_message_said = TRUE - retreat_distance = 30 - -/mob/living/simple_animal/hostile/asteroid/wolf/Life(seconds_per_tick = SSMOBS_DT, times_fired) - . = ..() - if(!. || target) - return - retreat_message_said = FALSE - -/obj/item/crusher_trophy/wolf_ear - name = "wolf ear" - desc = "It's a wolf ear." - icon_state = "wolf_ear" - denied_type = /obj/item/crusher_trophy/wolf_ear - -/obj/item/crusher_trophy/wolf_ear/effect_desc() - return "mark detonation to gain a slight speed boost temporarily" - -/obj/item/crusher_trophy/wolf_ear/on_mark_detonation(mob/living/target, mob/living/user) - user.apply_status_effect(/datum/status_effect/speed_boost, 1 SECONDS) diff --git a/code/modules/mob/living/simple_animal/hostile/vatbeast.dm b/code/modules/mob/living/simple_animal/hostile/vatbeast.dm index f5184a8543461fb..a5dfface8110e54 100644 --- a/code/modules/mob/living/simple_animal/hostile/vatbeast.dm +++ b/code/modules/mob/living/simple_animal/hostile/vatbeast.dm @@ -31,9 +31,9 @@ GRANT_ACTION(/datum/action/cooldown/tentacle_slap) add_cell_sample() - AddComponent(/datum/component/tameable, list(/obj/item/food/fries, /obj/item/food/cheesyfries, /obj/item/food/cornchips, /obj/item/food/carrotfries), tame_chance = 30, bonus_tame_chance = 0, after_tame = CALLBACK(src, PROC_REF(tamed))) + AddComponent(/datum/component/tameable, list(/obj/item/food/fries, /obj/item/food/cheesyfries, /obj/item/food/cornchips, /obj/item/food/carrotfries), tame_chance = 30, bonus_tame_chance = 0) -/mob/living/simple_animal/hostile/vatbeast/proc/tamed(mob/living/tamer) +/mob/living/simple_animal/hostile/vatbeast/tamed(mob/living/tamer, obj/item/food) buckle_lying = 0 AddElement(/datum/element/ridable, /datum/component/riding/creature/vatbeast) faction = list(FACTION_NEUTRAL) diff --git a/code/modules/mob/living/status_procs.dm b/code/modules/mob/living/status_procs.dm index 96beb024fe9220f..c0e2058f23ed2af 100644 --- a/code/modules/mob/living/status_procs.dm +++ b/code/modules/mob/living/status_procs.dm @@ -303,6 +303,7 @@ Knockdown(amount) Stun(amount) Immobilize(amount) + Unconscious(amount) /mob/living/proc/SetAllImmobility(amount) @@ -310,6 +311,7 @@ SetKnockdown(amount) SetStun(amount) SetImmobilized(amount) + SetUnconscious(amount) /mob/living/proc/AdjustAllImmobility(amount) @@ -317,6 +319,7 @@ AdjustKnockdown(amount) AdjustStun(amount) AdjustImmobilized(amount) + AdjustUnconscious(amount) /* UNCONSCIOUS */ diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm index 31b1d84999e1846..b54d7fa578ce1a2 100644 --- a/code/modules/mob/mob.dm +++ b/code/modules/mob/mob.dm @@ -1124,7 +1124,7 @@ antimagic_color = LIGHT_COLOR_DARK_BLUE playsound(src, 'sound/magic/magic_block_mind.ogg', 50, TRUE) - mob_light(range = 2, color = antimagic_color, duration = 5 SECONDS) + mob_light(range = 2, power = 2, color = antimagic_color, duration = 5 SECONDS) add_overlay(antimagic_effect) addtimer(CALLBACK(src, TYPE_PROC_REF(/atom, cut_overlay), antimagic_effect), 5 SECONDS) diff --git a/code/modules/mob/mob_movement.dm b/code/modules/mob/mob_movement.dm index eeeb7815d197bfd..28dffcb6ee55e02 100644 --- a/code/modules/mob/mob_movement.dm +++ b/code/modules/mob/mob_movement.dm @@ -515,6 +515,8 @@ selector.update_appearance() update_move_intent_slowdown() + SEND_SIGNAL(user, COMSIG_MOVE_INTENT_TOGGLED) + ///Moves a mob upwards in z level /mob/verb/up() set name = "Move Upwards" diff --git a/code/modules/mob/mob_transformation_simple.dm b/code/modules/mob/mob_transformation_simple.dm index 6d2a8a9850dc29b..56cd102a59b8cf8 100644 --- a/code/modules/mob/mob_transformation_simple.dm +++ b/code/modules/mob/mob_transformation_simple.dm @@ -2,7 +2,7 @@ //This proc is the most basic of the procs. All it does is make a new mob on the same tile and transfer over a few variables. //Returns the new mob //Note that this proc does NOT do MMI related stuff! -/mob/proc/change_mob_type(new_type = null, turf/location = null, new_name = null as text, delete_old_mob = FALSE) +/mob/proc/change_mob_type(new_type = null, turf/location = null, new_name = null as text|null, delete_old_mob = FALSE) if(isnewplayer(src)) to_chat(usr, span_danger("Cannot convert players who have not entered yet.")) diff --git a/code/modules/mob_spawn/ghost_roles/spider_roles.dm b/code/modules/mob_spawn/ghost_roles/spider_roles.dm index 8ab32d9d4f4056f..102a73d6f92f4cb 100644 --- a/code/modules/mob_spawn/ghost_roles/spider_roles.dm +++ b/code/modules/mob_spawn/ghost_roles/spider_roles.dm @@ -1,5 +1,6 @@ /obj/structure/spider/eggcluster name = "egg cluster" + icon = 'icons/effects/effects.dmi' desc = "There's something alive in there, and sooner or later it's going to find its way out." icon_state = "eggs" /// Mob spawner handling the actual spawn of the spider diff --git a/code/modules/mod/mod_activation.dm b/code/modules/mod/mod_activation.dm index 3fca395e4b7b66b..7d698aa5a75584f 100644 --- a/code/modules/mod/mod_activation.dm +++ b/code/modules/mod/mod_activation.dm @@ -244,7 +244,8 @@ for(var/obj/item/mod/module/module as anything in modules) module.on_suit_deactivation() update_speed() - update_icon_state() + update_appearance(UPDATE_ICON_STATE) + update_charge_alert() wearer.update_clothing(slot_flags) /// Quickly deploys all the suit parts and if successful, seals them and turns on the suit. Intended mostly for outfits. diff --git a/code/modules/mod/mod_construction.dm b/code/modules/mod/mod_construction.dm index 8442783d331078e..ca7be41ec426f1f 100644 --- a/code/modules/mod/mod_construction.dm +++ b/code/modules/mod/mod_construction.dm @@ -60,7 +60,8 @@ Its shape is remarkably similar to that of a MOD core." light_system = OVERLAY_LIGHT light_color = "#cc00cc" - light_range = 2 + light_range = 2.5 + light_power = 1.5 /obj/item/mod/construction/lavalandcore/examine(mob/user) . = ..() diff --git a/code/modules/mod/mod_control.dm b/code/modules/mod/mod_control.dm index 88bb8ac7b6013a7..fbf062d291731db 100644 --- a/code/modules/mod/mod_control.dm +++ b/code/modules/mod/mod_control.dm @@ -246,7 +246,6 @@ if(malfunctioning) malfunctioning_charge_drain = rand(1,20) subtract_charge((charge_drain + malfunctioning_charge_drain) * seconds_per_tick) - update_charge_alert() for(var/obj/item/mod/module/module as anything in modules) if(malfunctioning && module.active && SPT_PROB(5, seconds_per_tick)) module.on_deactivation(display_message = TRUE) @@ -332,7 +331,6 @@ wrench.play_tool_sound(src, 100) balloon_alert(user, "core removed") core.forceMove(drop_location()) - update_charge_alert() return TRUE return ..() @@ -415,7 +413,6 @@ attacking_core.install(src) balloon_alert(user, "core installed") playsound(src, 'sound/machines/click.ogg', 50, TRUE, SILENCED_SOUND_EXTRARANGE) - update_charge_alert() return TRUE else if(is_wire_tool(attacking_item) && open) wires.interact(user) @@ -500,8 +497,8 @@ for(var/obj/item/mod/module/module as anything in modules) module.on_unequip() UnregisterSignal(wearer, list(COMSIG_ATOM_EXITED, COMSIG_SPECIES_GAIN)) - wearer.clear_alert(ALERT_MODSUIT_CHARGE) SEND_SIGNAL(src, COMSIG_MOD_WEARER_UNSET, wearer) + wearer.update_spacesuit_hud_icon("0") wearer = null /obj/item/mod/control/proc/clean_up() @@ -644,13 +641,21 @@ /obj/item/mod/control/proc/check_charge(amount) return core?.check_charge(amount) || FALSE +/** + * Updates the wearer's hud according to the current state of the MODsuit + */ /obj/item/mod/control/proc/update_charge_alert() - if(!wearer) - return - if(!core) - wearer.throw_alert(ALERT_MODSUIT_CHARGE, /atom/movable/screen/alert/nocore) + if(isnull(wearer)) return - core.update_charge_alert() + var/state_to_use + if(!active) + state_to_use = "0" + else if(isnull(core)) + state_to_use = "coreless" + else + state_to_use = core.get_charge_icon_state() + + wearer.update_spacesuit_hud_icon(state_to_use || "0") /obj/item/mod/control/proc/update_speed() var/list/all_parts = mod_parts + src @@ -718,7 +723,6 @@ return if(part == core) core.uninstall() - update_charge_alert() return if(part.loc == wearer) return diff --git a/code/modules/mod/mod_core.dm b/code/modules/mod/mod_core.dm index 75a5b2385b7bf2b..5e7183e2563a39a 100644 --- a/code/modules/mod/mod_core.dm +++ b/code/modules/mod/mod_core.dm @@ -18,9 +18,11 @@ mod = mod_unit mod.core = src forceMove(mod) + mod.update_charge_alert() /obj/item/mod/core/proc/uninstall() mod.core = null + mod.update_charge_alert() mod = null /obj/item/mod/core/proc/charge_source() @@ -41,8 +43,11 @@ /obj/item/mod/core/proc/check_charge(amount) return FALSE -/obj/item/mod/core/proc/update_charge_alert() - mod.wearer.clear_alert(ALERT_MODSUIT_CHARGE) +/** + * Gets what icon state to display on the HUD for the charge level of this core + */ +/obj/item/mod/core/proc/get_charge_icon_state() + return "0" /obj/item/mod/core/infinite name = "MOD infinite core" @@ -68,6 +73,9 @@ /obj/item/mod/core/infinite/check_charge(amount) return TRUE +/obj/item/mod/core/infinite/get_charge_icon_state() + return "high" + /obj/item/mod/core/standard name = "MOD standard core" icon_state = "mod-core-standard" @@ -80,8 +88,7 @@ var/obj/item/stock_parts/cell/cell /obj/item/mod/core/standard/Destroy() - if(cell) - QDEL_NULL(cell) + QDEL_NULL(cell) return ..() /obj/item/mod/core/standard/install(obj/item/mod/control/mod_unit) @@ -116,54 +123,57 @@ /obj/item/mod/core/standard/add_charge(amount) var/obj/item/stock_parts/cell/charge_source = charge_source() - if(!charge_source) + if(isnull(charge_source)) return FALSE - return charge_source.give(amount) + . = charge_source.give(amount) + if(.) + mod.update_charge_alert() + return . /obj/item/mod/core/standard/subtract_charge(amount) var/obj/item/stock_parts/cell/charge_source = charge_source() - if(!charge_source) + if(isnull(charge_source)) return FALSE - return charge_source.use(amount, TRUE) + . = charge_source.use(amount, TRUE) + if(.) + mod.update_charge_alert() + return . /obj/item/mod/core/standard/check_charge(amount) return charge_amount() >= amount -/obj/item/mod/core/standard/update_charge_alert() - var/obj/item/stock_parts/cell/charge_source = charge_source() - if(!charge_source) - mod.wearer.throw_alert(ALERT_MODSUIT_CHARGE, /atom/movable/screen/alert/nocell) - return - var/remaining_cell = charge_amount() / max_charge_amount() - switch(remaining_cell) +/obj/item/mod/core/standard/get_charge_icon_state() + if(isnull(charge_source())) + return "missing" + + switch(round(charge_amount() / max_charge_amount(), 0.01)) if(0.75 to INFINITY) - mod.wearer.clear_alert(ALERT_MODSUIT_CHARGE) + return "high" if(0.5 to 0.75) - mod.wearer.throw_alert(ALERT_MODSUIT_CHARGE, /atom/movable/screen/alert/lowcell, 1) + return "mid" if(0.25 to 0.5) - mod.wearer.throw_alert(ALERT_MODSUIT_CHARGE, /atom/movable/screen/alert/lowcell, 2) - if(0.01 to 0.25) - mod.wearer.throw_alert(ALERT_MODSUIT_CHARGE, /atom/movable/screen/alert/lowcell, 3) - else - mod.wearer.throw_alert(ALERT_MODSUIT_CHARGE, /atom/movable/screen/alert/emptycell) + return "low" + if(0.02 to 0.25) + return "very_low" + + return "empty" /obj/item/mod/core/standard/proc/install_cell(new_cell) cell = new_cell cell.forceMove(src) - RegisterSignal(src, COMSIG_ATOM_EXITED, PROC_REF(on_exit)) + mod.update_charge_alert() /obj/item/mod/core/standard/proc/uninstall_cell() if(!cell) return + cell.update_appearance() cell = null - UnregisterSignal(src, COMSIG_ATOM_EXITED) - -/obj/item/mod/core/standard/proc/on_exit(datum/source, obj/item/stock_parts/cell, direction) - SIGNAL_HANDLER + mod.update_charge_alert() - if(!istype(cell) || cell.loc == src) - return - uninstall_cell() +/obj/item/mod/core/standard/Exited(atom/movable/gone, direction) + . = ..() + if(gone == cell) + uninstall_cell() /obj/item/mod/core/standard/proc/on_examine(datum/source, mob/examiner, list/examine_text) SIGNAL_HANDLER @@ -195,7 +205,6 @@ var/obj/item/cell_to_move = cell cell_to_move.forceMove(drop_location()) user.put_in_hands(cell_to_move) - mod.update_charge_alert() /obj/item/mod/core/standard/proc/on_attackby(datum/source, obj/item/attacking_item, mob/user) SIGNAL_HANDLER @@ -212,7 +221,6 @@ install_cell(attacking_item) mod.balloon_alert(user, "cell installed") playsound(mod, 'sound/machines/click.ogg', 50, TRUE, SILENCED_SOUND_EXTRARANGE) - mod.update_charge_alert() return COMPONENT_NO_AFTERATTACK return NONE @@ -232,7 +240,6 @@ SIGNAL_HANDLER add_charge(amount) - mod.update_charge_alert() /obj/item/mod/core/ethereal name = "MOD ethereal core" @@ -272,12 +279,8 @@ /obj/item/mod/core/ethereal/check_charge(amount) return charge_amount() >= amount*charge_modifier -/obj/item/mod/core/ethereal/update_charge_alert() - var/obj/item/organ/internal/stomach/ethereal/charge_source = charge_source() - if(charge_source) - mod.wearer.clear_alert(ALERT_MODSUIT_CHARGE) - return - mod.wearer.throw_alert(ALERT_MODSUIT_CHARGE, /atom/movable/screen/alert/nocell) +/obj/item/mod/core/ethereal/get_charge_icon_state() + return charge_source() ? "0" : "missing" #define PLASMA_CORE_ORE_CHARGE 1500 #define PLASMA_CORE_SHEET_CHARGE 2000 @@ -318,28 +321,29 @@ /obj/item/mod/core/plasma/add_charge(amount) charge = min(maxcharge, charge + amount) + mod.update_charge_alert() return TRUE /obj/item/mod/core/plasma/subtract_charge(amount) charge = max(0, charge - amount) + mod.update_charge_alert() return TRUE /obj/item/mod/core/plasma/check_charge(amount) return charge_amount() >= amount -/obj/item/mod/core/plasma/update_charge_alert() - var/remaining_plasma = charge_amount() / max_charge_amount() - switch(remaining_plasma) +/obj/item/mod/core/plasma/get_charge_icon_state() + switch(round(charge_amount() / max_charge_amount(), 0.01)) if(0.75 to INFINITY) - mod.wearer.clear_alert(ALERT_MODSUIT_CHARGE) + return "high" if(0.5 to 0.75) - mod.wearer.throw_alert(ALERT_MODSUIT_CHARGE, /atom/movable/screen/alert/lowcell/plasma, 1) + return "mid" if(0.25 to 0.5) - mod.wearer.throw_alert(ALERT_MODSUIT_CHARGE, /atom/movable/screen/alert/lowcell/plasma, 2) - if(0.01 to 0.25) - mod.wearer.throw_alert(ALERT_MODSUIT_CHARGE, /atom/movable/screen/alert/lowcell/plasma, 3) - else - mod.wearer.throw_alert(ALERT_MODSUIT_CHARGE, /atom/movable/screen/alert/emptycell/plasma) + return "low" + if(0.02 to 0.25) + return "very_low" + + return "empty" /obj/item/mod/core/plasma/proc/on_attackby(datum/source, obj/item/attacking_item, mob/user) SIGNAL_HANDLER @@ -369,7 +373,8 @@ The wires coming out of it could be hooked into a MODsuit." light_system = OVERLAY_LIGHT light_color = "#cc00cc" - light_range = 2 + light_range = 2.5 + light_power = 1.5 // Slightly better than the normal plasma core. // Not super sure if this should just be the same, but will see. maxcharge = 15000 diff --git a/code/modules/mod/mod_theme.dm b/code/modules/mod/mod_theme.dm index 509cdfc1ed7dea2..88f697ccd48bd98 100644 --- a/code/modules/mod/mod_theme.dm +++ b/code/modules/mod/mod_theme.dm @@ -1506,6 +1506,19 @@ acid = 90 wound = 10 +/datum/mod_theme/responsory/traitor + name = "dark paladin" + desc = "A high-speed suit stolen by the Gorlex Maradeurs, purposed for less than honest intents." + extended_desc = "A streamlined suit of Nanotrasen Syndicate design, these sleek black suits are only worn by \ + elite emergency response personnel traitors to help save ruin the day. While the slim and nimble design of the suit \ + cuts the ceramics and ablatives in it down, dropping the protection, \ + it keeps the wearer safe from the harsh void of space while sacrificing no speed whatsoever. \ + While wearing it you feel an extreme deference to darkness light." + armor_type = /datum/armor/mod_theme_elite + resistance_flags = FIRE_PROOF|ACID_PROOF + complexity_max = DEFAULT_MAX_COMPLEXITY + 5 + inbuilt_modules = list(/obj/item/mod/module/armor_booster/no_speedbost) + /datum/mod_theme/apocryphal name = "apocryphal" desc = "A high-tech, only technically legal, armored suit created by a collaboration effort between Nanotrasen and Apadyne Technologies." diff --git a/code/modules/mod/mod_types.dm b/code/modules/mod/mod_types.dm index 0659dd6208ba64c..47f588eb80b9b8f 100644 --- a/code/modules/mod/mod_types.dm +++ b/code/modules/mod/mod_types.dm @@ -477,6 +477,25 @@ /obj/item/mod/module/quick_cuff, ) +/obj/item/mod/control/pre_equipped/responsory/inquisitory/syndie + starting_frequency = MODLINK_FREQ_SYNDICATE + req_access = null + applied_cell = /obj/item/stock_parts/cell/super + theme = /datum/mod_theme/responsory/traitor + applied_modules = list( + /obj/item/mod/module/storage/syndicate, + /obj/item/mod/module/emp_shield, + /obj/item/mod/module/magnetic_harness, + /obj/item/mod/module/jetpack, + /obj/item/mod/module/pathfinder, + /obj/item/mod/module/flashlight/darkness, + /obj/item/mod/module/dna_lock, + /obj/item/mod/module/quick_cuff, + /obj/item/mod/module/visor/night, + /obj/item/mod/module/shove_blocker, + /obj/item/mod/module/noslip, + ) + /obj/item/mod/control/pre_equipped/responsory/inquisitory/commander insignia_type = /obj/item/mod/module/insignia/commander additional_module = /obj/item/mod/module/power_kick diff --git a/code/modules/mod/mod_ui.dm b/code/modules/mod/mod_ui.dm index 575518affbb567e..ec3f393ed506ebb 100644 --- a/code/modules/mod/mod_ui.dm +++ b/code/modules/mod/mod_ui.dm @@ -80,19 +80,23 @@ if(.) return if(malfunctioning && prob(75)) - balloon_alert(usr, "button malfunctions!") + balloon_alert(ui.user, "button malfunctions!") return switch(action) if("lock") - locked = !locked - balloon_alert(usr, "[locked ? "locked" : "unlocked"]!") + if(!locked || allowed(ui.user)) + locked = !locked + balloon_alert(ui.user, "[locked ? "locked" : "unlocked"]!") + else + balloon_alert(ui.user, "access insufficent!") + playsound(src, 'sound/machines/scanbuzz.ogg', 25, TRUE, SILENCED_SOUND_EXTRARANGE) if("call") if(!mod_link.link_call) - call_link(usr, mod_link) + call_link(ui.user, mod_link) else mod_link.end_call() if("activate") - toggle_activate(usr) + toggle_activate(ui.user) if("select") var/obj/item/mod/module/module = locate(params["ref"]) in modules if(!module) @@ -107,9 +111,9 @@ var/obj/item/mod/module/module = locate(params["ref"]) in modules if(!module) return - module.pin(usr) + module.pin(ui.user) if("eject_pai") - if (!ishuman(usr)) + if (!ishuman(ui.user)) return - remove_pai(usr) + remove_pai(ui.user) return TRUE diff --git a/code/modules/mod/modules/_module.dm b/code/modules/mod/modules/_module.dm index 874f5f3dbdf88a4..10a7ea074c391a8 100644 --- a/code/modules/mod/modules/_module.dm +++ b/code/modules/mod/modules/_module.dm @@ -238,7 +238,6 @@ if(!check_power(amount)) return FALSE mod.subtract_charge(amount) - mod.update_charge_alert() return TRUE /// Checks if there is enough power in the suit diff --git a/code/modules/mod/modules/modules_antag.dm b/code/modules/mod/modules/modules_antag.dm index a35e39365b948e6..2e53e380fd02f4c 100644 --- a/code/modules/mod/modules/modules_antag.dm +++ b/code/modules/mod/modules/modules_antag.dm @@ -29,6 +29,9 @@ /// List of traits added when the mod is activated var/list/traits_to_add = list(TRAIT_HEAD_INJURY_BLOCKED) +/obj/item/mod/module/armor_booster/no_speedbost + speed_added = 0 + /datum/armor/mod_module_armor_boost melee = 25 bullet = 30 @@ -236,6 +239,9 @@ /obj/item/mod/module/insignia/chaplain color = "#f0a00c" +/obj/item/mod/module/insignia/syndie + color = COLOR_SYNDIE_RED + ///Anti Slip - Prevents you from slipping on water. /obj/item/mod/module/noslip name = "MOD anti slip module" diff --git a/code/modules/mod/modules/modules_general.dm b/code/modules/mod/modules/modules_general.dm index 9962bc8b9a44dbd..59f0055dd8717ea 100644 --- a/code/modules/mod/modules/modules_general.dm +++ b/code/modules/mod/modules/modules_general.dm @@ -377,6 +377,12 @@ /// Maximum range we can set. var/max_range = 5 +/obj/item/mod/module/flashlight/on_suit_activation() + RegisterSignal(mod.wearer, COMSIG_HIT_BY_SABOTEUR, PROC_REF(on_saboteur)) + +/obj/item/mod/module/flashlight/on_suit_deactivation(deleting = FALSE) + UnregisterSignal(mod.wearer, COMSIG_HIT_BY_SABOTEUR) + /obj/item/mod/module/flashlight/on_activation() . = ..() if(!.) @@ -392,6 +398,12 @@ set_light_flags(light_flags & ~LIGHT_ATTACHED) set_light_on(active) +/obj/item/mod/module/flashlight/proc/on_saboteur(datum/source, disrupt_duration) + SIGNAL_HANDLER + if(active) + on_deactivation() + return COMSIG_SABOTEUR_SUCCESS + /obj/item/mod/module/flashlight/on_process(seconds_per_tick) active_power_cost = base_power * light_range return ..() @@ -424,6 +436,21 @@ if("light_range") set_light_range(clamp(value, min_range, max_range)) +///Like the flashlight module, except the light color is stuck to black and cannot be changed. +/obj/item/mod/module/flashlight/darkness + name = "MOD flashdark module" + desc = "A quirky pair of configurable flashdarks installed on the sides of the helmet, \ + useful for providing darkness at a configurable range." + light_color = COLOR_BLACK + light_system = OVERLAY_LIGHT + light_range = 2 + min_range = 1 + max_range = 3 + +/obj/item/mod/module/flashlight/darkness/get_configuration() + . = ..() + . -= "light_color" + ///Dispenser - Dispenses an item after a time passes. /obj/item/mod/module/dispenser name = "MOD burger dispenser module" @@ -788,19 +815,7 @@ /obj/item/cigbutt, ) /// Materials that will be extracted. - var/list/accepted_mats = list( - /datum/material/iron, - /datum/material/glass, - /datum/material/silver, - /datum/material/plasma, - /datum/material/gold, - /datum/material/diamond, - /datum/material/plastic, - /datum/material/uranium, - /datum/material/bananium, - /datum/material/titanium, - /datum/material/bluespace, - ) + var/list/accepted_mats var/static/list/loc_connections = list( COMSIG_ATOM_ENTERED = PROC_REF(on_obj_entered), COMSIG_ATOM_AFTER_SUCCESSFUL_INITIALIZED_ON = PROC_REF(on_atom_initialized_on), @@ -810,10 +825,15 @@ /obj/item/mod/module/recycler/Initialize(mapload) . = ..() + + if(!length(accepted_mats)) + accepted_mats = SSmaterials.materials_by_category[MAT_CATEGORY_SILO] + container = AddComponent( \ /datum/component/material_container, \ - accepted_mats, 50 * SHEET_MATERIAL_AMOUNT, \ - MATCONTAINER_EXAMINE|MATCONTAINER_NO_INSERT, \ + accepted_mats, \ + 50 * SHEET_MATERIAL_AMOUNT, \ + MATCONTAINER_EXAMINE | MATCONTAINER_NO_INSERT, \ container_signals = list( \ COMSIG_MATCONTAINER_SHEETS_RETRIEVED = TYPE_PROC_REF(/obj/item/mod/module/recycler, InsertSheets) \ ) \ diff --git a/code/modules/modular_computers/computers/item/computer.dm b/code/modules/modular_computers/computers/item/computer.dm index fd689c3bc16531e..688c30ef6019efe 100644 --- a/code/modules/modular_computers/computers/item/computer.dm +++ b/code/modules/modular_computers/computers/item/computer.dm @@ -7,6 +7,7 @@ icon = 'icons/obj/machines/computer.dmi' icon_state = "laptop" light_on = FALSE + light_power = 1.2 integrity_failure = 0.5 max_integrity = 100 armor_type = /datum/armor/item_modular_computer diff --git a/code/modules/modular_computers/computers/item/disks/role_disks.dm b/code/modules/modular_computers/computers/item/disks/role_disks.dm index da52ee76281a167..f7f20efb70b4371 100644 --- a/code/modules/modular_computers/computers/item/disks/role_disks.dm +++ b/code/modules/modular_computers/computers/item/disks/role_disks.dm @@ -98,6 +98,7 @@ starting_programs = list( /datum/computer_file/program/shipping, /datum/computer_file/program/budgetorders, + /datum/computer_file/program/restock_tracker, ) /** @@ -123,6 +124,6 @@ /datum/computer_file/program/alarm_monitor, /datum/computer_file/program/atmosscan, /datum/computer_file/program/supermatter_monitor, - + ) diff --git a/code/modules/modular_computers/computers/item/role_tablet_presets.dm b/code/modules/modular_computers/computers/item/role_tablet_presets.dm index 339def50add632a..f47a8c9a4e66cc4 100644 --- a/code/modules/modular_computers/computers/item/role_tablet_presets.dm +++ b/code/modules/modular_computers/computers/item/role_tablet_presets.dm @@ -114,6 +114,7 @@ /datum/computer_file/program/robocontrol, /datum/computer_file/program/budgetorders, /datum/computer_file/program/shipping, + /datum/computer_file/program/restock_tracker, ) /** @@ -264,6 +265,7 @@ /datum/computer_file/program/shipping, /datum/computer_file/program/budgetorders, /datum/computer_file/program/robocontrol, + /datum/computer_file/program/restock_tracker, ) /obj/item/modular_computer/pda/shaftminer @@ -431,6 +433,17 @@ /datum/computer_file/program/status, ) +/obj/item/modular_computer/pda/veteran_advisor + name = "security advisor PDA" + greyscale_colors = "#EA3232#FFD700" + inserted_item = /obj/item/pen/fountain + starting_programs = list( + /datum/computer_file/program/records/security, + /datum/computer_file/program/crew_manifest, + /datum/computer_file/program/coupon, //veteran discount + /datum/computer_file/program/skill_tracker, + ) + /** * Non-roles */ diff --git a/code/modules/modular_computers/file_system/programs/budgetordering.dm b/code/modules/modular_computers/file_system/programs/budgetordering.dm index 17ab7faf0f9b8ce..ae950bf6f7b7c0a 100644 --- a/code/modules/modular_computers/file_system/programs/budgetordering.dm +++ b/code/modules/modular_computers/file_system/programs/budgetordering.dm @@ -57,7 +57,7 @@ return FALSE -/datum/computer_file/program/budgetorders/ui_data() +/datum/computer_file/program/budgetorders/ui_data(mob/user) var/list/data = list() data["location"] = SSshuttle.supply.getStatusText() data["department"] = "Cargo" @@ -79,12 +79,12 @@ if(buyer) data["points"] = buyer.account_balance -//Otherwise static data, that is being applied in ui_data as the crates visible and buyable are not static, and are determined by inserted ID. + //Otherwise static data, that is being applied in ui_data as the crates visible and buyable are not static, and are determined by inserted ID. data["requestonly"] = requestonly data["supplies"] = list() for(var/pack in SSshuttle.supply_packs) var/datum/supply_pack/P = SSshuttle.supply_packs[pack] - if(!is_visible_pack(usr, P.access_view , null, P.contraband) || P.hidden) + if(!is_visible_pack(user, P.access_view , null, P.contraband) || P.hidden) continue if(!data["supplies"][P.group]) data["supplies"][P.group] = list( @@ -102,7 +102,7 @@ "access" = P.access )) -//Data regarding the User's capability to buy things. + //Data regarding the User's capability to buy things. data["has_id"] = id_card data["away"] = SSshuttle.supply.getDockedId() == docking_away data["self_paid"] = self_paid diff --git a/code/modules/modular_computers/file_system/programs/card.dm b/code/modules/modular_computers/file_system/programs/card.dm index 238d05704e23de3..a9bbff8db1b91e0 100644 --- a/code/modules/modular_computers/file_system/programs/card.dm +++ b/code/modules/modular_computers/file_system/programs/card.dm @@ -51,7 +51,7 @@ authenticated_user = auth_card.registered_name ? auth_card.registered_name : "Unknown" job_templates = is_centcom ? SSid_access.centcom_job_templates.Copy() : SSid_access.station_job_templates.Copy() valid_access = is_centcom ? SSid_access.get_region_access_list(list(REGION_CENTCOM)) : SSid_access.get_region_access_list(list(REGION_ALL_STATION)) - update_static_data(user) + computer.update_static_data_for_all_viewers() return TRUE // Otherwise, we're minor and now we have to build a list of restricted departments we can change access for. @@ -67,7 +67,7 @@ minor = TRUE valid_access |= SSid_access.get_region_access_list(region_access) authenticated_card = "[auth_card.name] \[LIMITED ACCESS\]" - update_static_data(user) + computer.update_static_data_for_all_viewers() return TRUE return FALSE diff --git a/code/modules/modular_computers/file_system/programs/restock_tracker.dm b/code/modules/modular_computers/file_system/programs/restock_tracker.dm new file mode 100644 index 000000000000000..46462c0c6b5316a --- /dev/null +++ b/code/modules/modular_computers/file_system/programs/restock_tracker.dm @@ -0,0 +1,31 @@ +/datum/computer_file/program/restock_tracker + filename = "restockapp" + filedesc = "NT Restock Tracker" + downloader_category = PROGRAM_CATEGORY_SUPPLY + program_open_overlay = "restock" + extended_desc = "Nanotrasen IoT network listing all the vending machines found on station, and how well stocked they are each. Profitable!" + program_flags = PROGRAM_ON_NTNET_STORE | PROGRAM_REQUIRES_NTNET + can_run_on_flags = PROGRAM_LAPTOP | PROGRAM_PDA + size = 4 + program_icon = "cash-register" + tgui_id = "NtosRestock" + +/datum/computer_file/program/restock_tracker/ui_data() + var/list/data = list() + var/list/vending_list = list() + var/id_increment = 1 + for(var/obj/machinery/vending/vendor as anything in GLOB.vending_machines_to_restock) + var/stock = vendor.total_loaded_stock() + var/max_stock = vendor.total_max_stock() + if((max_stock == 0 || (stock >= max_stock)) && vendor.credits_contained == 0) + continue + vending_list += list(list( + "name" = vendor.name, + "location" = get_area_name(vendor), + "credits" = vendor.credits_contained, + "percentage" = (stock / max_stock) * 100, + "id" = id_increment, + )) + id_increment++ + data["vending_list"] = vending_list + return data diff --git a/code/modules/movespeed/modifiers/reagent.dm b/code/modules/movespeed/modifiers/reagent.dm index 6700854b11dd51b..55726363310b101 100644 --- a/code/modules/movespeed/modifiers/reagent.dm +++ b/code/modules/movespeed/modifiers/reagent.dm @@ -5,7 +5,8 @@ multiplicative_slowdown = -0.55 /datum/movespeed_modifier/reagent/ephedrine - multiplicative_slowdown = -0.5 + variable = TRUE + // speed is based on purity of the reagent at the time of metabolization /datum/movespeed_modifier/reagent/pepperspray multiplicative_slowdown = 0.25 diff --git a/code/modules/pai/card.dm b/code/modules/pai/card.dm index c1a9c5a88ba04ac..77ca42aeebcee3e 100644 --- a/code/modules/pai/card.dm +++ b/code/modules/pai/card.dm @@ -21,6 +21,14 @@ /// Prevents a crew member from hitting "request pAI" repeatedly var/request_spam = FALSE +/obj/item/pai_card/Initialize(mapload) + . = ..() + + update_appearance() + SSpai.pai_card_list += src + ADD_TRAIT(src, TRAIT_CASTABLE_LOC, INNATE_TRAIT) + RegisterSignal(src, COMSIG_HIT_BY_SABOTEUR, PROC_REF(on_saboteur)) + /obj/item/pai_card/attackby(obj/item/used, mob/user, params) if(pai && istype(used, /obj/item/encryptionkey)) if(!pai.encrypt_mod) @@ -63,12 +71,10 @@ emotion_icon = initial(emotion_icon) update_appearance() -/obj/item/pai_card/Initialize(mapload) - . = ..() - - update_appearance() - SSpai.pai_card_list += src - ADD_TRAIT(src, TRAIT_CASTABLE_LOC, INNATE_TRAIT) +/obj/item/pai_card/proc/on_saboteur(datum/source, disrupt_duration) + SIGNAL_HANDLER + if(pai) + return pai.on_saboteur(source, disrupt_duration) /obj/item/pai_card/suicide_act(mob/living/user) user.visible_message(span_suicide("[user] is staring sadly at [src]! [user.p_They()] can't keep living without real human intimacy!")) diff --git a/code/modules/pai/pai.dm b/code/modules/pai/pai.dm index 8162702158305f7..b4414027368ee24 100644 --- a/code/modules/pai/pai.dm +++ b/code/modules/pai/pai.dm @@ -230,6 +230,7 @@ RegisterSignal(src, COMSIG_LIVING_CULT_SACRIFICED, PROC_REF(on_cult_sacrificed)) RegisterSignals(src, list(COMSIG_LIVING_ADJUST_BRUTE_DAMAGE, COMSIG_LIVING_ADJUST_BURN_DAMAGE), PROC_REF(on_shell_damaged)) RegisterSignal(src, COMSIG_LIVING_ADJUST_STAMINA_DAMAGE, PROC_REF(on_shell_weakened)) + RegisterSignal(src, COMSIG_HIT_BY_SABOTEUR, PROC_REF(on_saboteur)) /mob/living/silicon/pai/make_laws() laws = new /datum/ai_laws/pai() @@ -343,6 +344,12 @@ to_chat(src, span_danger("WARN: Holochasis range restrictions disabled.")) return TRUE +/mob/living/silicon/pai/proc/on_saboteur(datum/source, disrupt_duration) + SIGNAL_HANDLER + set_silence_if_lower(disrupt_duration) + balloon_alert(src, "muted!") + return COMSIG_SABOTEUR_SUCCESS + /** * Resets the pAI and any emagged status. * diff --git a/code/modules/paperwork/paperbin.dm b/code/modules/paperwork/paperbin.dm index 9971c0da7f7bbd8..86db803322f0564 100644 --- a/code/modules/paperwork/paperbin.dm +++ b/code/modules/paperwork/paperbin.dm @@ -124,7 +124,7 @@ return if(istype(I, /obj/item/paper)) var/obj/item/paper/paper = I - if(!user.transferItemToLoc(paper, src)) + if(!user.transferItemToLoc(paper, src, silent = FALSE)) return to_chat(user, span_notice("You put [paper] in [src].")) paper_stack += paper @@ -132,7 +132,7 @@ update_appearance() else if(istype(I, /obj/item/pen) && !bin_pen) var/obj/item/pen/pen = I - if(!user.transferItemToLoc(pen, src)) + if(!user.transferItemToLoc(pen, src, silent = FALSE)) return to_chat(user, span_notice("You put [pen] in [src].")) bin_pen = pen diff --git a/code/modules/paperwork/pen.dm b/code/modules/paperwork/pen.dm index 10a15e88196cc22..27072b8674e1338 100644 --- a/code/modules/paperwork/pen.dm +++ b/code/modules/paperwork/pen.dm @@ -327,7 +327,7 @@ item_flags = NO_BLOOD_ON_ITEM light_system = OVERLAY_LIGHT light_range = 1.5 - light_power = 0.75 + light_power = 1.3 light_color = COLOR_SOFT_RED light_on = FALSE dart_insert_projectile_icon_state = "overlay_edagger" diff --git a/code/modules/paperwork/photocopier.dm b/code/modules/paperwork/photocopier.dm index e5a30474f8721ff..4b495ae9148aefc 100644 --- a/code/modules/paperwork/photocopier.dm +++ b/code/modules/paperwork/photocopier.dm @@ -199,7 +199,7 @@ GLOBAL_LIST_INIT(paper_blanks, init_paper_blanks()) else to_chat(usr, span_notice("You feel kind of silly, copying [ass]\'s ass with [ass.p_their()] clothes on.")) return FALSE - do_copies(CALLBACK(src, PROC_REF(make_ass_copy), usr), usr, ASS_PAPER_USE, ASS_TONER_USE, num_copies) + do_copies(CALLBACK(src, PROC_REF(make_ass_copy)), usr, ASS_PAPER_USE, ASS_TONER_USE, num_copies) return TRUE else // Basic paper @@ -489,24 +489,13 @@ GLOBAL_LIST_INIT(paper_blanks, init_paper_blanks()) * Calls `check_ass()` first to make sure that `ass` exists, among other conditions. Since this proc is called from a timer, it's possible that it was removed. * Additionally checks that the mob has their clothes off. */ -/obj/machinery/photocopier/proc/make_ass_copy(mob/user) +/obj/machinery/photocopier/proc/make_ass_copy() if(!check_ass()) return null - var/icon/temp_img - if(ishuman(ass)) - var/mob/living/carbon/human/H = ass - var/datum/species/spec = H.dna.species - if(spec.ass_image) - temp_img = icon(spec.ass_image) - else - temp_img = icon(ass.gender == FEMALE ? 'icons/ass/assfemale.png' : 'icons/ass/assmale.png') - else if(isalienadult(ass)) //Xenos have their own asses, thanks to Pybro. - temp_img = icon('icons/ass/assalien.png') - else if(issilicon(ass)) - temp_img = icon('icons/ass/assmachine.png') - else if(isdrone(ass)) //Drones are hot - temp_img = icon('icons/ass/assdrone.png') - + var/butt_icon_state = ass.get_butt_sprite() + if(isnull(butt_icon_state)) + return null + var/icon/temp_img = icon('icons/mob/butts.dmi', butt_icon_state) var/obj/item/photo/copied_ass = new /obj/item/photo(src) var/datum/picture/toEmbed = new(name = "[ass]'s Ass", desc = "You see [ass]'s ass on the photo.", image = temp_img) toEmbed.psize_x = 128 @@ -629,7 +618,7 @@ GLOBAL_LIST_INIT(paper_blanks, init_paper_blanks()) * Returns FALSE if `ass` doesn't exist or is not at the copier's location. Returns TRUE otherwise. */ /obj/machinery/photocopier/proc/check_ass() //I'm not sure wether I made this proc because it's good form or because of the name. - if(!ass) + if(!isliving(ass)) return FALSE if(ass.loc != loc) ass = null diff --git a/code/modules/photography/camera/camera.dm b/code/modules/photography/camera/camera.dm index 4bdb1c4d93aa862..0d5f37cb86737e5 100644 --- a/code/modules/photography/camera/camera.dm +++ b/code/modules/photography/camera/camera.dm @@ -10,8 +10,8 @@ worn_icon_state = "camera" lefthand_file = 'icons/mob/inhands/items/devices_lefthand.dmi' righthand_file = 'icons/mob/inhands/items/devices_righthand.dmi' - light_system = OVERLAY_LIGHT //Used as a flash here. - light_range = 8 + light_system = OVERLAY_LIGHT_DIRECTIONAL //Used as a flash here. + light_range = 6 light_color = COLOR_WHITE light_power = FLASH_LIGHT_POWER light_on = FALSE diff --git a/code/modules/power/apc/apc_attack.dm b/code/modules/power/apc/apc_attack.dm index 509eb4f05b90d9b..fc6b33f275785e3 100644 --- a/code/modules/power/apc/apc_attack.dm +++ b/code/modules/power/apc/apc_attack.dm @@ -221,7 +221,7 @@ return stomach.drain_time = world.time + APC_DRAIN_TIME addtimer(CALLBACK(src, TYPE_PROC_REF(/atom, balloon_alert), ethereal, "draining power"), alert_timer_duration) - if(do_after(user, APC_DRAIN_TIME, target = src)) + while(do_after(user, APC_DRAIN_TIME, target = src)) if(cell.charge <= (cell.maxcharge / 2) || (stomach.crystal_charge > charge_limit)) return balloon_alert(ethereal, "received charge") @@ -243,9 +243,10 @@ balloon_alert(ethereal, "can't transfer power!") return if(istype(stomach)) - balloon_alert(ethereal, "transferred power") - stomach.adjust_charge(-APC_POWER_GAIN) - cell.give(APC_POWER_GAIN) + while(do_after(user, APC_DRAIN_TIME, target = src)) + balloon_alert(ethereal, "transferred power") + stomach.adjust_charge(-APC_POWER_GAIN) + cell.give(APC_POWER_GAIN) else balloon_alert(ethereal, "can't transfer power!") diff --git a/code/modules/power/apc/apc_main.dm b/code/modules/power/apc/apc_main.dm index 6960e6da5995c01..65de109b5e34b0f 100644 --- a/code/modules/power/apc/apc_main.dm +++ b/code/modules/power/apc/apc_main.dm @@ -205,6 +205,7 @@ register_context() addtimer(CALLBACK(src, PROC_REF(update)), 5) RegisterSignal(SSdcs, COMSIG_GLOB_GREY_TIDE, PROC_REF(grey_tide)) + RegisterSignal(src, COMSIG_HIT_BY_SABOTEUR, PROC_REF(on_saboteur)) update_appearance() var/static/list/hovering_mob_typechecks = list( @@ -235,6 +236,11 @@ disconnect_terminal() return ..() +/obj/machinery/power/apc/proc/on_saboteur(datum/source, disrupt_duration) + SIGNAL_HANDLER + energy_fail(disrupt_duration) + return COMSIG_SABOTEUR_SUCCESS + /obj/machinery/power/apc/proc/assign_to_area(area/target_area = get_area(src)) if(area == target_area) return diff --git a/code/modules/power/cell.dm b/code/modules/power/cell.dm index 842772ed0b9d52a..2addc045a0c5126 100644 --- a/code/modules/power/cell.dm +++ b/code/modules/power/cell.dm @@ -254,7 +254,7 @@ return to_chat(H, span_notice("You begin clumsily channeling power from [src] into your body.")) stomach.drain_time = world.time + CELL_DRAIN_TIME - if(do_after(user, CELL_DRAIN_TIME, target = src)) + while(do_after(user, CELL_DRAIN_TIME, target = src)) if((charge < CELL_POWER_DRAIN) || (stomach.crystal_charge > charge_limit)) return if(istype(stomach)) diff --git a/code/modules/power/lighting/light.dm b/code/modules/power/lighting/light.dm index 3125772d2679c02..caaebf7b2cc0538 100644 --- a/code/modules/power/lighting/light.dm +++ b/code/modules/power/lighting/light.dm @@ -122,6 +122,7 @@ /obj/machinery/light/LateInitialize() . = ..() +#ifndef MAP_TEST switch(fitting) if("tube") if(prob(2)) @@ -129,6 +130,7 @@ if("bulb") if(prob(5)) break_light_tube(TRUE) +#endif update(trigger = FALSE) /obj/machinery/light/Destroy() diff --git a/code/modules/power/singularity/singularity.dm b/code/modules/power/singularity/singularity.dm index b21b26dcea0ae95..5b712d52da2ff0e 100644 --- a/code/modules/power/singularity/singularity.dm +++ b/code/modules/power/singularity/singularity.dm @@ -50,7 +50,7 @@ pass_flags = PASSTABLE | PASSGLASS | PASSGRILLE | PASSCLOSEDTURF | PASSMACHINE | PASSSTRUCTURE | PASSDOORS flags_1 = SUPERMATTER_IGNORES_1 - resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF | FREEZE_PROOF + resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF | FREEZE_PROOF | SHUTTLE_CRUSH_PROOF obj_flags = CAN_BE_HIT | DANGEROUS_POSSESSION /obj/singularity/Initialize(mapload, starting_energy = 50) diff --git a/code/modules/power/tesla/energy_ball.dm b/code/modules/power/tesla/energy_ball.dm index 3e0f3baef0d13c1..d3b68caaa314678 100644 --- a/code/modules/power/tesla/energy_ball.dm +++ b/code/modules/power/tesla/energy_ball.dm @@ -26,7 +26,7 @@ obj_flags = CAN_BE_HIT | DANGEROUS_POSSESSION pixel_x = -32 pixel_y = -32 - resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF | FREEZE_PROOF + resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF | FREEZE_PROOF | SHUTTLE_CRUSH_PROOF flags_1 = SUPERMATTER_IGNORES_1 var/energy diff --git a/code/modules/projectiles/guns/ballistic.dm b/code/modules/projectiles/guns/ballistic.dm index 5f512813182b247..f09d38fcbf3db23 100644 --- a/code/modules/projectiles/guns/ballistic.dm +++ b/code/modules/projectiles/guns/ballistic.dm @@ -130,6 +130,12 @@ ///What is the cap on our misfire probability? Do not set this to 100. var/misfire_probability_cap = 25 + /// Fire Selector Variables /// + /// Tracks the firemode of burst weapons. TRUE means it is in burst mode. + var/burst_fire_selection = FALSE + /// If it has an icon for a selector switch indicating current firemode. + var/selector_switch_icon = FALSE + /obj/item/gun/ballistic/Initialize(mapload) . = ..() if(!spawn_magazine_type) @@ -200,6 +206,14 @@ /obj/item/gun/ballistic/update_overlays() . = ..() + + if(selector_switch_icon) + switch(burst_fire_selection) + if(FALSE) + . += "[initial(icon_state)]_semi" + if(TRUE) + . += "[initial(icon_state)]_burst" + if(show_bolt_icon) if (bolt_type == BOLT_TYPE_LOCKING) . += "[icon_state]_bolt[bolt_locked ? "_locked" : ""]" @@ -249,6 +263,27 @@ if(capacity_number) . += "[icon_state]_mag_[capacity_number]" +/obj/item/gun/ballistic/ui_action_click(mob/user, actiontype) + if(istype(actiontype, /datum/action/item_action/toggle_firemode)) + burst_select() + else + ..() + +/obj/item/gun/ballistic/proc/burst_select() + var/mob/living/carbon/human/user = usr + burst_fire_selection = !burst_fire_selection + if(!burst_fire_selection) + burst_size = 1 + fire_delay = 0 + balloon_alert(user, "switched to semi-automatic") + else + burst_size = initial(burst_size) + fire_delay = initial(fire_delay) + balloon_alert(user, "switched to [burst_size]-round burst") + + playsound(user, 'sound/weapons/empty.ogg', 100, TRUE) + update_appearance() + update_item_action_buttons() /obj/item/gun/ballistic/handle_chamber(empty_chamber = TRUE, from_firing = TRUE, chamber_next_round = TRUE) if(!semi_auto && from_firing) diff --git a/code/modules/projectiles/guns/ballistic/automatic.dm b/code/modules/projectiles/guns/ballistic/automatic.dm index 4162ca9890f2ff7..3d6940692d890ea 100644 --- a/code/modules/projectiles/guns/ballistic/automatic.dm +++ b/code/modules/projectiles/guns/ballistic/automatic.dm @@ -9,41 +9,7 @@ fire_sound_volume = 90 rack_sound = 'sound/weapons/gun/smg/smgrack.ogg' suppressed_sound = 'sound/weapons/gun/smg/shot_suppressed.ogg' - var/select = 1 ///fire selector position. 1 = semi, 2 = burst. anything past that can vary between guns. - var/selector_switch_icon = FALSE ///if it has an icon for a selector switch indicating current firemode. - -/obj/item/gun/ballistic/automatic/update_overlays() - . = ..() - if(!selector_switch_icon) - return - - switch(select) - if(0) - . += "[initial(icon_state)]_semi" - if(1) - . += "[initial(icon_state)]_burst" - -/obj/item/gun/ballistic/automatic/ui_action_click(mob/user, actiontype) - if(istype(actiontype, /datum/action/item_action/toggle_firemode)) - burst_select() - else - ..() - -/obj/item/gun/ballistic/automatic/proc/burst_select() - var/mob/living/carbon/human/user = usr - select = !select - if(!select) - burst_size = 1 - fire_delay = 0 - balloon_alert(user, "switched to semi-automatic") - else - burst_size = initial(burst_size) - fire_delay = initial(fire_delay) - balloon_alert(user, "switched to [burst_size]-round burst") - - playsound(user, 'sound/weapons/empty.ogg', 100, TRUE) - update_appearance() - update_item_action_buttons() + burst_fire_selection = TRUE /obj/item/gun/ballistic/automatic/proto name = "\improper Nanotrasen Saber SMG" @@ -205,14 +171,6 @@ else ..() -/obj/item/gun/ballistic/automatic/m90/update_overlays() - . = ..() - switch(select) - if(0) - . += "[initial(icon_state)]_semi" - if(1) - . += "[initial(icon_state)]_burst" - /obj/item/gun/ballistic/automatic/tommygun name = "\improper Thompson SMG" desc = "Based on the classic 'Chicago Typewriter'." diff --git a/code/modules/projectiles/guns/ballistic/shotgun.dm b/code/modules/projectiles/guns/ballistic/shotgun.dm index a7186ae6439312f..38bcfe8d2f411b8 100644 --- a/code/modules/projectiles/guns/ballistic/shotgun.dm +++ b/code/modules/projectiles/guns/ballistic/shotgun.dm @@ -136,7 +136,7 @@ /obj/item/gun/ballistic/shotgun/bulldog name = "\improper Bulldog Shotgun" - desc = "A semi-auto, mag-fed shotgun for combat in narrow corridors, nicknamed 'Bulldog' by boarding parties. Compatible only with specialized 8-round drum magazines. Can have a secondary magazine attached to quickly swap between ammo types, or just to keep shooting." + desc = "A 2-round burst fire, mag-fed shotgun for combat in narrow corridors, nicknamed 'Bulldog' by boarding parties. Compatible only with specialized 8-round drum magazines. Can have a secondary magazine attached to quickly swap between ammo types, or just to keep shooting." icon_state = "bulldog" inhand_icon_state = "bulldog" worn_icon_state = "cshotgun" @@ -148,10 +148,11 @@ weapon_weight = WEAPON_MEDIUM accepted_magazine_type = /obj/item/ammo_box/magazine/m12g can_suppress = FALSE - burst_size = 1 - fire_delay = 10 //Skyrat edit - Original: 0 + burst_size = 2 + fire_delay = 10 //Skyrat edit - Original: 1 pin = /obj/item/firing_pin/implant/pindicate fire_sound = 'sound/weapons/gun/shotgun/shot_alt.ogg' + actions_types = list(/datum/action/item_action/toggle_firemode) mag_display = TRUE empty_indicator = TRUE empty_alarm = TRUE @@ -160,6 +161,7 @@ semi_auto = TRUE internal_magazine = FALSE tac_reloads = TRUE + burst_fire_selection = TRUE ///the type of secondary magazine for the bulldog var/secondary_magazine_type ///the secondary magazine diff --git a/code/modules/projectiles/guns/energy/crank_guns.dm b/code/modules/projectiles/guns/energy/crank_guns.dm index 23cd6a297ed34c5..5faaf3ea015df81 100644 --- a/code/modules/projectiles/guns/energy/crank_guns.dm +++ b/code/modules/projectiles/guns/energy/crank_guns.dm @@ -72,3 +72,56 @@ ammo_type = list(/obj/item/ammo_casing/energy/disabler/smoothbore/prime) charge_sections = 2 spread = 0 //could be like 5, but having just very tiny spread kinda feels like bullshit + +//Inferno and Cryo Pistols + +/obj/item/gun/energy/laser/thermal //the common parent of these guns, it just shoots hard bullets, somoene might like that? + name = "nanite pistol" + desc = "A modified handcannon with a metamorphic reserve of decommissioned weaponized nanites. Spit globs of angry robots into the bad guys." + icon_state = "infernopistol" + inhand_icon_state = null + ammo_type = list(/obj/item/ammo_casing/energy/nanite) + shaded_charge = TRUE + ammo_x_offset = 1 + obj_flags = UNIQUE_RENAME + can_bayonet = TRUE + knife_x_offset = 19 + knife_y_offset = 13 + w_class = WEIGHT_CLASS_NORMAL + dual_wield_spread = 5 //as intended by the coders + +/obj/item/gun/energy/laser/thermal/Initialize(mapload) + . = ..() + AddElement(/datum/element/empprotection, EMP_PROTECT_SELF|EMP_PROTECT_CONTENTS) + AddComponent( \ + /datum/component/crank_recharge, \ + charging_cell = get_cell(), \ + spin_to_win = TRUE, \ + charge_amount = 125, \ + cooldown_time = 0.8 SECONDS, \ + charge_sound = 'sound/weapons/kinetic_reload.ogg', \ + charge_sound_cooldown_time = 0.8 SECONDS, \ + ) + +/obj/item/gun/energy/laser/thermal/add_seclight_point() + AddComponent(/datum/component/seclite_attachable, \ + light_overlay_icon = 'icons/obj/weapons/guns/flashlights.dmi', \ + light_overlay = "flight", \ + overlay_x = 15, \ + overlay_y = 9) + +/obj/item/gun/energy/laser/thermal/inferno //the magma gun + name = "inferno pistol" + desc = "A modified handcannon with a metamorphic reserve of decommissioned weaponized nanites. Spit globs of molten angry robots into the bad guys. \ + While it doesn't manipulate temperature in and of itself, it does cause an violent eruption in anyone who is severely cold. Able to generate \ + ammunition by manually spinning the weapon's nanite canister." + icon_state = "infernopistol" + ammo_type = list(/obj/item/ammo_casing/energy/nanite/inferno) + +/obj/item/gun/energy/laser/thermal/cryo //the ice gun + name = "cryo pistol" + desc = "A modified handcannon with a metamorphic reserve of decommissioned weaponized nanites. Spit shards of frozen angry robots into the bad guys. \ + While it doesn't manipulate temperature in and of itself, it does cause an internal explosion in anyone who is severely hot. Able to generate \ + ammunition by manually spinning the weapon's nanite canister." + icon_state = "cryopistol" + ammo_type = list(/obj/item/ammo_casing/energy/nanite/cryo) diff --git a/code/modules/projectiles/guns/energy/kinetic_accelerator.dm b/code/modules/projectiles/guns/energy/kinetic_accelerator.dm index e3ed515a7081735..d30bfa1a6cf168b 100644 --- a/code/modules/projectiles/guns/energy/kinetic_accelerator.dm +++ b/code/modules/projectiles/guns/energy/kinetic_accelerator.dm @@ -11,11 +11,13 @@ can_bayonet = TRUE knife_x_offset = 20 knife_y_offset = 12 - var/mob/holder - var/max_mod_capacity = 100 - var/list/modkits = list() gun_flags = NOT_A_REAL_GUN - + ///List of all mobs that projectiles fired from this gun will ignore. + var/list/ignored_mob_types + ///List of all modkits currently in the kinetic accelerator. + var/list/obj/item/borg/upgrade/modkit/modkits = list() + ///The max capacity of modkits the PKA can have installed at once. + var/max_mod_capacity = 100 /obj/item/gun/energy/recharge/kinetic_accelerator/Initialize(mapload) . = ..() @@ -68,18 +70,16 @@ if(max_mod_capacity) . += "[get_remaining_mod_capacity()]% mod capacity remaining." . += span_info("You can use a crowbar to remove all modules or right-click with an empty hand to remove a specific one.") - for(var/A in modkits) - var/obj/item/borg/upgrade/modkit/M = A - . += span_notice("There is \a [M] installed, using [M.cost]% capacity.") + for(var/obj/item/borg/upgrade/modkit/modkit_upgrade as anything in modkits) + . += span_notice("There is \a [modkit_upgrade] installed, using [modkit_upgrade.cost]% capacity.") /obj/item/gun/energy/recharge/kinetic_accelerator/crowbar_act(mob/living/user, obj/item/I) . = TRUE if(modkits.len) to_chat(user, span_notice("You pry all the modifications out.")) I.play_tool_sound(src, 100) - for(var/a in modkits) - var/obj/item/borg/upgrade/modkit/M = a - M.forceMove(drop_location()) //uninstallation handled in Exited(), or /mob/living/silicon/robot/remove_from_upgrades() for borgs + for(var/obj/item/borg/upgrade/modkit/modkit_upgrade as anything in modkits) + modkit_upgrade.forceMove(drop_location()) //uninstallation handled in Exited(), or /mob/living/silicon/robot/remove_from_upgrades() for borgs else to_chat(user, span_notice("There are no modifications currently installed.")) @@ -138,16 +138,14 @@ /obj/item/gun/energy/recharge/kinetic_accelerator/proc/get_remaining_mod_capacity() var/current_capacity_used = 0 - for(var/A in modkits) - var/obj/item/borg/upgrade/modkit/M = A - current_capacity_used += M.cost + for(var/obj/item/borg/upgrade/modkit/modkit_upgrade as anything in modkits) + current_capacity_used += modkit_upgrade.cost return max_mod_capacity - current_capacity_used -/obj/item/gun/energy/recharge/kinetic_accelerator/proc/modify_projectile(obj/projectile/kinetic/K) - K.kinetic_gun = src //do something special on-hit, easy! - for(var/A in modkits) - var/obj/item/borg/upgrade/modkit/M = A - M.modify_projectile(K) +/obj/item/gun/energy/recharge/kinetic_accelerator/proc/modify_projectile(obj/projectile/kinetic/kinetic_projectile) + kinetic_projectile.kinetic_gun = src //do something special on-hit, easy! + for(var/obj/item/borg/upgrade/modkit/modkit_upgrade as anything in modkits) + modkit_upgrade.modify_projectile(kinetic_projectile) /obj/item/gun/energy/recharge/kinetic_accelerator/cyborg icon_state = "kineticgun" // SKYRAT EDIT CHANGE @@ -193,13 +191,14 @@ return ..() /obj/projectile/kinetic/prehit_pierce(atom/target) + if(is_type_in_typecache(target, kinetic_gun.ignored_mob_types)) + return PROJECTILE_PIERCE_PHASE . = ..() if(. == PROJECTILE_PIERCE_PHASE) return if(kinetic_gun) - var/list/mods = kinetic_gun.modkits - for(var/obj/item/borg/upgrade/modkit/modkit in mods) - modkit.projectile_prehit(src, target, kinetic_gun) + for(var/obj/item/borg/upgrade/modkit/modkit_upgrade as anything in kinetic_gun.modkits) + modkit_upgrade.projectile_prehit(src, target, kinetic_gun) if(!pressure_decrease_active && !lavaland_equipment_pressure_check(get_turf(target))) name = "weakened [name]" damage = damage * pressure_decrease @@ -219,10 +218,10 @@ target_turf = get_turf(src) if(kinetic_gun) //hopefully whoever shot this was not very, very unfortunate. var/list/mods = kinetic_gun.modkits - for(var/obj/item/borg/upgrade/modkit/M in mods) - M.projectile_strike_predamage(src, target_turf, target, kinetic_gun) - for(var/obj/item/borg/upgrade/modkit/M in mods) - M.projectile_strike(src, target_turf, target, kinetic_gun) + for(var/obj/item/borg/upgrade/modkit/modkit_upgrade as anything in mods) + modkit_upgrade.projectile_strike_predamage(src, target_turf, target, kinetic_gun) + for(var/obj/item/borg/upgrade/modkit/modkit_upgrade as anything in mods) + modkit_upgrade.projectile_strike(src, target_turf, target, kinetic_gun) if(ismineralturf(target_turf)) var/turf/closed/mineral/M = target_turf M.gets_drilled(firer, TRUE) @@ -284,9 +283,8 @@ return FALSE if(denied_type) var/number_of_denied = 0 - for(var/A in KA.modkits) - var/obj/item/borg/upgrade/modkit/M = A - if(istype(M, denied_type)) + for(var/obj/item/borg/upgrade/modkit/modkit_upgrade as anything in KA.modkits) + if(istype(modkit_upgrade, denied_type)) number_of_denied++ if(number_of_denied >= maximum_of_type) . = FALSE @@ -434,8 +432,31 @@ /obj/item/borg/upgrade/modkit/minebot_passthrough name = "minebot passthrough" desc = "Causes kinetic accelerator shots to pass through minebots." + denied_type = /obj/item/borg/upgrade/modkit/human_passthrough + cost = 0 + +/obj/item/borg/upgrade/modkit/minebot_passthrough/install(obj/item/gun/energy/recharge/kinetic_accelerator/KA, mob/user, transfer_to_loc) + . = ..() + LAZYADD(KA.ignored_mob_types, typecacheof(/mob/living/basic/mining_drone)) + +/obj/item/borg/upgrade/modkit/minebot_passthrough/uninstall(obj/item/gun/energy/recharge/kinetic_accelerator/KA) + . = ..() + LAZYREMOVE(KA.ignored_mob_types, typecacheof(/mob/living/basic/mining_drone)) + +/obj/item/borg/upgrade/modkit/human_passthrough + name = "human passthrough" + desc = "Causes kinetic accelerator shots to pass through humans, good for preventing friendly fire." + denied_type = /obj/item/borg/upgrade/modkit/minebot_passthrough cost = 0 +/obj/item/borg/upgrade/modkit/human_passthrough/install(obj/item/gun/energy/recharge/kinetic_accelerator/KA, mob/user, transfer_to_loc) + . = ..() + LAZYADD(KA.ignored_mob_types, typecacheof(/mob/living/carbon/human)) + +/obj/item/borg/upgrade/modkit/human_passthrough/uninstall(obj/item/gun/energy/recharge/kinetic_accelerator/KA) + . = ..() + LAZYREMOVE(KA.ignored_mob_types, typecacheof(/mob/living/carbon/human)) + //Tendril-unique modules /obj/item/borg/upgrade/modkit/cooldown/repeater name = "rapid repeater" diff --git a/code/modules/projectiles/guns/energy/laser.dm b/code/modules/projectiles/guns/energy/laser.dm index ded25392c6016b3..f194b5eb8647fb1 100644 --- a/code/modules/projectiles/guns/energy/laser.dm +++ b/code/modules/projectiles/guns/energy/laser.dm @@ -186,48 +186,6 @@ /obj/item/gun/energy/laser/redtag/hitscan ammo_type = list(/obj/item/ammo_casing/energy/laser/redtag/hitscan) -//Inferno and Cryo Pistols - -/obj/item/gun/energy/laser/thermal //the common parent of these guns, it just shoots hard bullets, somoene might like that? - name = "nanite pistol" - desc = "A modified handcannon with a metamorphic reserve of decommissioned weaponized nanites. Spit globs of angry robots into the bad guys." - icon_state = "infernopistol" - inhand_icon_state = null - ammo_type = list(/obj/item/ammo_casing/energy/nanite) - shaded_charge = TRUE - ammo_x_offset = 1 - obj_flags = UNIQUE_RENAME - can_bayonet = TRUE - knife_x_offset = 19 - knife_y_offset = 13 - w_class = WEIGHT_CLASS_NORMAL - dual_wield_spread = 10 //as intended by the coders - -/obj/item/gun/energy/laser/thermal/Initialize(mapload) - . = ..() - AddElement(/datum/element/empprotection, EMP_PROTECT_SELF|EMP_PROTECT_CONTENTS) - -/obj/item/gun/energy/laser/thermal/add_seclight_point() - AddComponent(/datum/component/seclite_attachable, \ - light_overlay_icon = 'icons/obj/weapons/guns/flashlights.dmi', \ - light_overlay = "flight", \ - overlay_x = 15, \ - overlay_y = 9) - -/obj/item/gun/energy/laser/thermal/inferno //the magma gun - name = "inferno pistol" - desc = "A modified handcannon with a metamorphic reserve of decommissioned weaponized nanites. Spit globs of molten angry robots into the bad guys. \ - While it doesn't manipulate temperature in and of itself, it does cause an violent eruption in anyone who is severely cold." - icon_state = "infernopistol" - ammo_type = list(/obj/item/ammo_casing/energy/nanite/inferno) - -/obj/item/gun/energy/laser/thermal/cryo //the ice gun - name = "cryo pistol" - desc = "A modified handcannon with a metamorphic reserve of decommissioned weaponized nanites. Spit shards of frozen angry robots into the bad guys. \ - While it doesn't manipulate temperature in and of itself, it does cause an internal explosion in anyone who is severely hot." - icon_state = "cryopistol" - ammo_type = list(/obj/item/ammo_casing/energy/nanite/cryo) - // luxury shuttle funnies /obj/item/firing_pin/paywall/luxury multi_payment = TRUE diff --git a/code/modules/projectiles/guns/special/syringe_gun.dm b/code/modules/projectiles/guns/special/syringe_gun.dm index 805378c1ffcc40c..71ad31dd4023167 100644 --- a/code/modules/projectiles/guns/special/syringe_gun.dm +++ b/code/modules/projectiles/guns/special/syringe_gun.dm @@ -48,11 +48,10 @@ return //SKYRAT EDIT SMARTDARTS if(istype(syringes[length(syringes)], /obj/item/reagent_containers/syringe/smartdart)) - chambered = new /obj/item/ammo_casing/syringegun/dart(src) + chambered.newshot(/obj/projectile/bullet/dart/syringe/dart) else - chambered = new /obj/item/ammo_casing/syringegun(src) + chambered.newshot() //SKYRAT EDIT SMARTDARTS END - chambered.newshot() /obj/item/gun/syringe/can_shoot() return syringes.len diff --git a/code/modules/projectiles/projectile.dm b/code/modules/projectiles/projectile.dm index 625b4d4df99655a..3e9109b1fe0713c 100644 --- a/code/modules/projectiles/projectile.dm +++ b/code/modules/projectiles/projectile.dm @@ -181,6 +181,8 @@ var/catastropic_dismemberment = FALSE //If TRUE, this projectile deals its damage to the chest if it dismembers a limb. var/impact_effect_type //what type of impact effect to show when hitting something var/log_override = FALSE //is this type spammed enough to not log? (KAs) + /// If true, the projectile won't cause any logging. Used for hallucinations and shit. + var/do_not_log = FALSE /// We ignore mobs with these factions. var/list/ignored_factions @@ -377,7 +379,7 @@ if(reagents?.reagent_list) reagent_note = "REAGENTS: [pretty_string_from_reagent_list(reagents.reagent_list)]" - if(ismob(firer)) + if(ismob(firer) && !do_not_log) log_combat(firer, living_target, "shot", src, reagent_note) return BULLET_ACT_HIT @@ -387,11 +389,12 @@ var/list/logging_mobs = firing_vehicle.return_controllers_with_flag(VEHICLE_CONTROL_EQUIPMENT) if(!LAZYLEN(logging_mobs)) logging_mobs = firing_vehicle.return_drivers() - for(var/mob/logged_mob as anything in logging_mobs) - log_combat(logged_mob, living_target, "shot", src, "from inside [firing_vehicle][logging_mobs.len > 1 ? " with multiple occupants" : null][reagent_note ? " and contained [reagent_note]" : null]") + if(!do_not_log) + for(var/mob/logged_mob as anything in logging_mobs) + log_combat(logged_mob, living_target, "shot", src, "from inside [firing_vehicle][logging_mobs.len > 1 ? " with multiple occupants" : null][reagent_note ? " and contained [reagent_note]" : null]") return BULLET_ACT_HIT - - living_target.log_message("has been shot by [firer] with [src][reagent_note ? " containing [reagent_note]" : null]", LOG_ATTACK, color="orange") + if(!do_not_log) + living_target.log_message("has been shot by [firer] with [src][reagent_note ? " containing [reagent_note]" : null]", LOG_ATTACK, color="orange") return BULLET_ACT_HIT /obj/projectile/proc/vol_by_damage() @@ -722,7 +725,7 @@ if(ismovable(A)) var/atom/movable/AM = A if(AM.throwing) - return (projectile_phasing & LETPASSTHROW)? PROJECTILE_PIERCE_PHASE : ((projectile_piercing & LETPASSTHROW)? PROJECTILE_PIERCE_HIT : PROJECTILE_PIERCE_NONE) + return (projectile_phasing & LETPASSTHROW) ? PROJECTILE_PIERCE_PHASE : ((projectile_piercing & LETPASSTHROW)? PROJECTILE_PIERCE_HIT : PROJECTILE_PIERCE_NONE) return PROJECTILE_PIERCE_NONE /obj/projectile/proc/check_ricochet(atom/A) @@ -789,7 +792,7 @@ SEND_SIGNAL(fired_from, COMSIG_PROJECTILE_BEFORE_FIRE, src, original) if(firer) SEND_SIGNAL(firer, COMSIG_PROJECTILE_FIRER_BEFORE_FIRE, src, fired_from, original) - if(!log_override && firer && original) + if(!log_override && firer && original && !do_not_log) log_combat(firer, original, "fired at", src, "from [get_area_name(src, TRUE)]") //note: mecha projectile logging is handled in /obj/item/mecha_parts/mecha_equipment/weapon/action(). try to keep these messages roughly the sameish just for consistency's sake. if(direct_target && (get_dist(direct_target, get_turf(fired_from)) <= 1)) // point blank shots // SKYRAT EDIT - ORIGINAL: if(direct_target && (get_dist(direct_target, get_turf(src)) <= 1)) diff --git a/code/modules/projectiles/projectile/beams.dm b/code/modules/projectiles/projectile/beams.dm index 5845ac0c9902f39..d78b9ec5a3189e8 100644 --- a/code/modules/projectiles/projectile/beams.dm +++ b/code/modules/projectiles/projectile/beams.dm @@ -11,7 +11,7 @@ impact_effect_type = /obj/effect/temp_visual/impact_effect/red_laser light_system = OVERLAY_LIGHT light_range = 1 - light_power = 1 + light_power = 1.4 light_color = COLOR_SOFT_RED ricochets_max = 50 //Honk! ricochet_chance = 80 diff --git a/code/modules/projectiles/projectile/energy/stun.dm b/code/modules/projectiles/projectile/energy/stun.dm index 67cbd4352ee90bf..c6f6b46da07cdc0 100644 --- a/code/modules/projectiles/projectile/energy/stun.dm +++ b/code/modules/projectiles/projectile/energy/stun.dm @@ -2,7 +2,7 @@ name = "electrode" icon_state = "spark" color = "#FFFF00" - stamina = 80 // SKYRAT EDIT CHANGE + stamina = 70 // SKYRAT EDIT CHANGE stutter = 10 SECONDS jitter = 40 SECONDS hitsound = 'sound/weapons/taserhit.ogg' diff --git a/code/modules/projectiles/projectile/special/lightbreaker.dm b/code/modules/projectiles/projectile/special/lightbreaker.dm deleted file mode 100644 index 2be6d9e4470dac1..000000000000000 --- a/code/modules/projectiles/projectile/special/lightbreaker.dm +++ /dev/null @@ -1,35 +0,0 @@ -/obj/projectile/energy/fisher - name = "attenuated kinetic force" - alpha = 0 - damage = 0 - damage_type = BRUTE - armor_flag = BOMB - range = 21 - projectile_phasing = PASSTABLE | PASSMOB | PASSMACHINE | PASSSTRUCTURE - hitscan = TRUE - var/disrupt_duration = 10 SECONDS - -/obj/projectile/energy/fisher/on_hit(atom/target, blocked, pierce_hit) - . = ..() - var/lights_flickered = 0 - if(SEND_SIGNAL(target, COMSIG_HIT_BY_SABOTEUR, disrupt_duration) & COMSIG_SABOTEUR_SUCCESS) - lights_flickered++ - if(!isliving(target)) - return - var/list/things_to_disrupt = list() - if(ishuman(target)) - var/mob/living/carbon/human/human_target = target - things_to_disrupt = human_target.get_all_gear() - else - var/mob/living/living_target = target // i guess this covers borgs too? - things_to_disrupt = living_target.get_equipped_items(include_pockets = TRUE, include_accessories = TRUE) - for(var/obj/item/thingy as anything in things_to_disrupt) - if(SEND_SIGNAL(thingy, COMSIG_HIT_BY_SABOTEUR, disrupt_duration) & COMSIG_SABOTEUR_SUCCESS) - lights_flickered++ - if(lights_flickered) - to_chat(target, span_warning("Your light [lights_flickered > 1 ? "sources flick" : "source flicks"] off.")) - -/obj/projectile/energy/fisher/melee - range = 1 - suppressed = SUPPRESSED_VERY - disrupt_duration = 20 SECONDS diff --git a/code/modules/projectiles/projectile/special/saboteur.dm b/code/modules/projectiles/projectile/special/saboteur.dm new file mode 100644 index 000000000000000..4ef6b9ffcbe6d9b --- /dev/null +++ b/code/modules/projectiles/projectile/special/saboteur.dm @@ -0,0 +1,30 @@ +/obj/projectile/energy/fisher + name = "attenuated kinetic force" + alpha = 0 + damage = 0 + damage_type = BRUTE + armor_flag = BOMB + range = 21 + projectile_phasing = PASSTABLE | PASSMOB | PASSMACHINE | PASSSTRUCTURE + hitscan = TRUE + var/disrupt_duration = 15 SECONDS + +/obj/projectile/energy/fisher/on_hit(atom/target, blocked, pierce_hit) + . = ..() + var/list/things_to_disrupt = list(target) + if(isliving(target)) + var/mob/living/live_target = target + things_to_disrupt += live_target.get_all_gear() + + var/success = FALSE + for(var/atom/disrupted as anything in things_to_disrupt) + if(SEND_SIGNAL(disrupted, COMSIG_HIT_BY_SABOTEUR, disrupt_duration) & COMSIG_SABOTEUR_SUCCESS) + success = TRUE + + if(success && ismob(firer)) + target.balloon_alert(firer, "disrupted") + +/obj/projectile/energy/fisher/melee + range = 1 + suppressed = SUPPRESSED_VERY + disrupt_duration = 25 SECONDS diff --git a/code/modules/reagents/chemistry/holder/holder.dm b/code/modules/reagents/chemistry/holder/holder.dm index d32cd92361b46cf..1d36747e8f46ca1 100644 --- a/code/modules/reagents/chemistry/holder/holder.dm +++ b/code/modules/reagents/chemistry/holder/holder.dm @@ -255,9 +255,9 @@ //if we reached here means we have found our specific reagent type so break if(!include_subtypes) - break + return total_removed_amount - return total_removed_amount + return round(total_removed_amount, CHEMICAL_VOLUME_ROUNDING) /** * Removes a reagent at random and by a random quantity till the specified amount has been removed. @@ -283,9 +283,8 @@ current_list_element = rand(1, cached_reagents.len) - while(total_removed != amount) - if(total_removed >= amount) - break + while(total_removed < amount) + // There's nothing left in the container if(total_volume <= 0 || !cached_reagents.len) break @@ -294,14 +293,16 @@ var/datum/reagent/target_holder = cached_reagents[current_list_element] var/remove_amt = min(amount - total_removed, round(amount / rand(2, initial_list_length), round(amount / 10, 0.01))) //double round to keep it at a somewhat even spread relative to amount without getting funky numbers. - //min ensures we don't go over amount. - remove_reagent(target_holder.type, remove_amt) + // If the logic above means removing really tiny amounts (or even zero if it's a remove amount of 10) instead choose a sensible smallish number + // so this proc will actually finish instead of looping forever + remove_amt = max(CHEMICAL_VOLUME_ROUNDING, remove_amt) + remove_amt = remove_reagent(target_holder.type, remove_amt) current_list_element++ total_removed += remove_amt - handle_reactions() - return total_removed //this should be amount unless the loop is prematurely broken, in which case it'll be lower. It shouldn't ever go OVER amount. + + return round(total_removed, CHEMICAL_VOLUME_ROUNDING) /** * Removes all reagents either proportionally(amount is the direct volume to remove) @@ -336,8 +337,8 @@ part /= total_volume for(var/datum/reagent/reagent as anything in cached_reagents) total_removed_amount += remove_reagent(reagent.type, reagent.volume * part) - handle_reactions() + return round(total_removed_amount, CHEMICAL_VOLUME_ROUNDING) /** diff --git a/code/modules/reagents/chemistry/machinery/chem_heater.dm b/code/modules/reagents/chemistry/machinery/chem_heater.dm index a07fd289f0784f5..e3208d8d461d7d4 100644 --- a/code/modules/reagents/chemistry/machinery/chem_heater.dm +++ b/code/modules/reagents/chemistry/machinery/chem_heater.dm @@ -25,15 +25,14 @@ create_reagents(200, NO_REACT) register_context() -/obj/machinery/chem_heater/on_deconstruction(disassembled) - beaker?.forceMove(drop_location()) - /obj/machinery/chem_heater/Destroy() if(beaker) UnregisterSignal(beaker.reagents, COMSIG_REAGENTS_REACTION_STEP) QDEL_NULL(beaker) return ..() +/obj/machinery/chem_heater/on_deconstruction(disassembled) + beaker?.forceMove(drop_location()) /obj/machinery/chem_heater/add_context(atom/source, list/context, obj/item/held_item, mob/user) if(isnull(held_item) || (held_item.item_flags & ABSTRACT) || (held_item.flags_1 & HOLOGRAM_1)) @@ -60,10 +59,74 @@ return NONE +/obj/machinery/chem_heater/examine(mob/user) + . = ..() + if(in_range(user, src) || isobserver(user)) + . += span_notice("The status display reads: Heating reagents at [heater_coefficient * 1000]% speed.") + if(!QDELETED(beaker)) + . += span_notice("It has a beaker of [beaker.reagents.total_volume] units capacity.") + if(beaker.reagents.is_reacting) + . += span_notice("Its contents are currently reacting.") + else + . += span_warning("There is no beaker inserted.") + . += span_notice("Its heating is turned [on ? "On" : "Off"].") + . += span_notice("The status display reads: Heating reagents at [heater_coefficient * 1000]% speed.") + if(panel_open) + . += span_notice("Its panel is open and can now be [EXAMINE_HINT("pried")] apart.") + else + . += span_notice("Its panel can be [EXAMINE_HINT("pried")] open") + /obj/machinery/chem_heater/update_icon_state() icon_state = "[base_icon_state][beaker ? 1 : 0]b" return ..() +/obj/machinery/chem_heater/Exited(atom/movable/gone, direction) + . = ..() + if(gone == beaker) + UnregisterSignal(beaker.reagents, COMSIG_REAGENTS_REACTION_STEP) + beaker = null + update_appearance() + +/obj/machinery/chem_heater/RefreshParts() + . = ..() + heater_coefficient = 0.1 + for(var/datum/stock_part/micro_laser/micro_laser in component_parts) + heater_coefficient *= micro_laser.tier + + +/obj/machinery/chem_heater/item_interaction(mob/living/user, obj/item/held_item, list/modifiers, is_right_clicking) + if((held_item.item_flags & ABSTRACT) || (held_item.flags_1 & HOLOGRAM_1)) + return ..() + + if(QDELETED(beaker)) + if(istype(held_item, /obj/item/reagent_containers/dropper) || istype(held_item, /obj/item/reagent_containers/syringe)) + var/obj/item/reagent_containers/injector = held_item + injector.afterattack(beaker, user, proximity_flag = TRUE) + return ITEM_INTERACT_SUCCESS + + if(is_reagent_container(held_item) && held_item.is_open_container()) + if(replace_beaker(user, held_item)) + ui_interact(user) + balloon_alert(user, "beaker added") + return ITEM_INTERACT_SUCCESS + + return ..() + +/obj/machinery/chem_heater/wrench_act(mob/living/user, obj/item/tool) + . = ITEM_INTERACT_BLOCKING + if(default_unfasten_wrench(user, tool) == SUCCESSFUL_UNFASTEN) + return ITEM_INTERACT_SUCCESS + +/obj/machinery/chem_heater/screwdriver_act(mob/living/user, obj/item/tool) + . = ITEM_INTERACT_BLOCKING + if(default_deconstruction_screwdriver(user, "mixer0b", "[base_icon_state][beaker ? 1 : 0]b", tool)) + return ITEM_INTERACT_SUCCESS + +/obj/machinery/chem_heater/crowbar_act(mob/living/user, obj/item/tool) + . = ITEM_INTERACT_BLOCKING + if(default_deconstruction_crowbar(tool)) + return ITEM_INTERACT_SUCCESS + /obj/machinery/chem_heater/attack_hand_secondary(mob/user, list/modifiers) . = ..() if(. == SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN) @@ -73,13 +136,6 @@ replace_beaker(user) return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN -/obj/machinery/chem_heater/Exited(atom/movable/gone, direction) - . = ..() - if(gone == beaker) - UnregisterSignal(beaker.reagents, COMSIG_REAGENTS_REACTION_STEP) - beaker = null - update_appearance() - /obj/machinery/chem_heater/attack_robot_secondary(mob/user, list/modifiers) return attack_hand_secondary(user, modifiers) @@ -109,12 +165,6 @@ return TRUE -/obj/machinery/chem_heater/RefreshParts() - . = ..() - heater_coefficient = 0.1 - for(var/datum/stock_part/micro_laser/micro_laser in component_parts) - heater_coefficient *= micro_laser.tier - /** * Heats the reagents of the currently inserted beaker only if machine is on & beaker has some reagents inside * Arguments @@ -142,23 +192,6 @@ for(var/datum/tgui/ui in src.open_uis) ui.send_update() -/obj/machinery/chem_heater/examine(mob/user) - . = ..() - if(in_range(user, src) || isobserver(user)) - . += span_notice("The status display reads: Heating reagents at [heater_coefficient * 1000]% speed.") - if(!QDELETED(beaker)) - . += span_notice("It has a beaker of [beaker.reagents.total_volume] units capacity.") - if(beaker.reagents.is_reacting) - . += span_notice("Its contents are currently reacting.") - else - . += span_warning("There is no beaker inserted.") - . += span_notice("Its heating is turned [on ? "On" : "Off"].") - . += span_notice("The status display reads: Heating reagents at [heater_coefficient * 1000]% speed.") - if(panel_open) - . += span_notice("Its panel is open and can now be [EXAMINE_HINT("pried")] apart.") - else - . += span_notice("Its panel can be [EXAMINE_HINT("pried")] open") - /obj/machinery/chem_heater/process(seconds_per_tick) //is_reacting is handled in reaction_step() if(QDELETED(beaker) || beaker.reagents.is_reacting) @@ -172,39 +205,6 @@ for(var/datum/tgui/ui in src.open_uis) ui.send_update() -/obj/machinery/chem_heater/wrench_act(mob/living/user, obj/item/tool) - . = ITEM_INTERACT_BLOCKING - if(default_unfasten_wrench(user, tool) == SUCCESSFUL_UNFASTEN) - return ITEM_INTERACT_SUCCESS - -/obj/machinery/chem_heater/screwdriver_act(mob/living/user, obj/item/tool) - . = ITEM_INTERACT_BLOCKING - if(default_deconstruction_screwdriver(user, "mixer0b", "[base_icon_state][beaker ? 1 : 0]b", tool)) - return ITEM_INTERACT_SUCCESS - -/obj/machinery/chem_heater/crowbar_act(mob/living/user, obj/item/tool) - . = ITEM_INTERACT_BLOCKING - if(default_deconstruction_crowbar(tool)) - return ITEM_INTERACT_SUCCESS - -/obj/machinery/chem_heater/attackby(obj/item/held_item, mob/user, params) - if((held_item.item_flags & ABSTRACT) || (held_item.flags_1 & HOLOGRAM_1)) - return ..() - - if(beaker) - if(istype(held_item, /obj/item/reagent_containers/dropper) || istype(held_item, /obj/item/reagent_containers/syringe)) - var/obj/item/reagent_containers/injector = held_item - injector.afterattack(beaker, user, proximity_flag = TRUE) - return TRUE - - if(is_reagent_container(held_item) && held_item.is_open_container()) - if(replace_beaker(user, held_item)) - ui_interact(user) - balloon_alert(user, "beaker added!") - return TRUE - - return ..() - /obj/machinery/chem_heater/ui_interact(mob/user, datum/tgui/ui) ui = SStgui.try_update_ui(user, src, ui) if(!ui) diff --git a/code/modules/reagents/chemistry/machinery/chem_mass_spec.dm b/code/modules/reagents/chemistry/machinery/chem_mass_spec.dm index c871fa47110aed8..e9ffc91cd34649e 100644 --- a/code/modules/reagents/chemistry/machinery/chem_mass_spec.dm +++ b/code/modules/reagents/chemistry/machinery/chem_mass_spec.dm @@ -1,21 +1,16 @@ - -#define BEAKER1 1 -#define BEAKER2 2 - /obj/machinery/chem_mass_spec name = "High-performance liquid chromatography machine" - desc = {"This machine can separate reagents based on charge, meaning it can clean reagents of some of their impurities, unlike the Chem Master 3000. -By selecting a range in the mass spectrograph certain reagents will be transferred from one beaker to another, which will clean it of any impurities up to a certain amount. -This will not clean any inverted reagents. Inverted reagents will still be correctly detected and displayed on the scanner, however. -\nLeft click with a beaker to add it to the input slot, Right click with a beaker to add it to the output slot. Alt + left/right click can let you quickly remove the corresponding beaker."} - density = TRUE - layer = BELOW_OBJ_LAYER + desc = "Allows you to purify reagents & seperate out inverse reagents" icon = 'icons/obj/medical/chemical.dmi' icon_state = "HPLC" base_icon_state = "HPLC" + density = TRUE + interaction_flags_atom = parent_type::interaction_flags_atom | INTERACT_ATOM_REQUIRES_ANCHORED idle_power_usage = BASE_MACHINE_IDLE_CONSUMPTION * 0.2 resistance_flags = FIRE_PROOF | ACID_PROOF + processing_flags = START_PROCESSING_MANUALLY circuit = /obj/item/circuitboard/machine/chem_mass_spec + ///If we're processing reagents or not var/processing_reagents = FALSE ///Time we started processing + the delay @@ -37,158 +32,244 @@ This will not clean any inverted reagents. Inverted reagents will still be corre /obj/machinery/chem_mass_spec/Initialize(mapload) . = ..() + ADD_TRAIT(src, TRAIT_DO_NOT_SPLASH, INNATE_TRAIT) + if(mapload) beaker2 = new /obj/item/reagent_containers/cup/beaker/large(src) - AddElement( \ - /datum/element/contextual_screentip_bare_hands, \ - lmb_text = "Add input beaker", \ - rmb_text = "Add output beaker", \ - ) + register_context() /obj/machinery/chem_mass_spec/Destroy() QDEL_NULL(beaker1) QDEL_NULL(beaker2) return ..() -/obj/machinery/chem_mass_spec/RefreshParts() +/obj/machinery/chem_mass_spec/on_deconstruction(disassembled) + var/location = drop_location() + beaker1?.forceMove(location) + beaker2?.forceMove(location) + +/obj/machinery/chem_mass_spec/add_context(atom/source, list/context, obj/item/held_item, mob/user) + . = NONE + + if(!QDELETED(beaker1)) + context[SCREENTIP_CONTEXT_ALT_LMB] = "Eject input beaker" + . = CONTEXTUAL_SCREENTIP_SET + if(!QDELETED(beaker2)) + context[SCREENTIP_CONTEXT_ALT_RMB] = "Eject output beaker" + . = CONTEXTUAL_SCREENTIP_SET + + if(isnull(held_item) || (held_item.item_flags & ABSTRACT) || (held_item.flags_1 & HOLOGRAM_1)) + return + + if(is_reagent_container(held_item)) + if(QDELETED(beaker1)) + context[SCREENTIP_CONTEXT_LMB] = "Insert input beaker" + else + context[SCREENTIP_CONTEXT_LMB] = "Replace input beaker" + + if(QDELETED(beaker2)) + context[SCREENTIP_CONTEXT_RMB] = "Insert output beaker" + else + context[SCREENTIP_CONTEXT_RMB] = "Replace output beaker" + + return CONTEXTUAL_SCREENTIP_SET + + if(held_item.tool_behaviour == TOOL_WRENCH) + context[SCREENTIP_CONTEXT_LMB] = "[anchored ? "Un" : ""]anchor" + return CONTEXTUAL_SCREENTIP_SET + else if(held_item.tool_behaviour == TOOL_SCREWDRIVER) + context[SCREENTIP_CONTEXT_LMB] = "[panel_open ? "Close" : "Open"] panel" + return CONTEXTUAL_SCREENTIP_SET + else if(panel_open && held_item.tool_behaviour == TOOL_CROWBAR) + context[SCREENTIP_CONTEXT_LMB] = "Deconstruct" + return CONTEXTUAL_SCREENTIP_SET + +/obj/machinery/chem_mass_spec/examine(mob/user) . = ..() - cms_coefficient = 1 - for(var/datum/stock_part/micro_laser/laser in component_parts) - cms_coefficient /= laser.tier -/obj/machinery/chem_mass_spec/on_deconstruction(disassembled) - if(beaker1) - beaker1.forceMove(drop_location()) - beaker1 = null - if(beaker2) - beaker2.forceMove(drop_location()) - beaker2 = null + if(!QDELETED(beaker1)) + . += span_notice("Input beaker of [beaker1.reagents.maximum_volume]u capacity is inserted.") + . += span_notice("Its Input beaker Can be ejected with [EXAMINE_HINT("LMB Alt")] click.") + else + . += span_warning("Its missing an input beaker. insert with [EXAMINE_HINT("Left Click")].") + if(!QDELETED(beaker2)) + . += span_notice("Output beaker of [beaker2.reagents.maximum_volume]u capacity is inserted.") + . += span_notice("Its Output beaker can be ejected with [EXAMINE_HINT("RMB Alt")] click.") + else + . += span_warning("Its missing an output beaker, insert with [EXAMINE_HINT("Right Click")].") + + if(anchored) + . += span_notice("Its [EXAMINE_HINT("anchored")] in place.") + else + . += span_warning("Needs to be [EXAMINE_HINT("wrenched")] to use.") + . += span_notice("Its maintainence panel can be [EXAMINE_HINT("screwed")] [panel_open ? "closed" : "open"].") + if(panel_open) + . += span_notice("It can be [EXAMINE_HINT("pried")] apart.") /obj/machinery/chem_mass_spec/update_overlays() . = ..() + if(panel_open) . += mutable_appearance(icon, "[base_icon_state]_panel-o") + return -/obj/machinery/chem_mass_spec/wrench_act(mob/living/user, obj/item/tool) + if(!QDELETED(beaker1)) + . += "HPLC_beaker1" + if(!QDELETED(beaker2)) + . += "HPLC_beaker2" + + if(is_operational && !panel_open && anchored && !(machine_stat & (BROKEN | NOPOWER))) + if(processing_reagents) + . += "HPLC_graph_active" + else if (length(beaker1?.reagents.reagent_list)) + . += "HPLC_graph_idle" + +/obj/machinery/chem_mass_spec/update_icon_state() + if(is_operational && !panel_open && anchored && !(machine_stat & (BROKEN | NOPOWER))) + icon_state = "HPLC_on" + else + icon_state = "HPLC" + return ..() + +/obj/machinery/chem_mass_spec/Exited(atom/movable/gone, direction) . = ..() - default_unfasten_wrench(user, tool) - return ITEM_INTERACT_SUCCESS + if(gone == beaker1) + beaker1 = null + if(gone == beaker2) + beaker2 = null -/* beaker swapping/attack code */ +/obj/machinery/chem_mass_spec/RefreshParts() + . = ..() -/obj/machinery/chem_mass_spec/attackby(obj/item/item, mob/user, params) - if(processing_reagents) - to_chat(user, " The [src] is currently processing a batch!") + cms_coefficient = 1 + for(var/datum/stock_part/micro_laser/laser in component_parts) + cms_coefficient /= laser.tier + +/obj/machinery/chem_mass_spec/item_interaction(mob/living/user, obj/item/item, list/modifiers, is_right_clicking) + if((item.item_flags & ABSTRACT) || (item.flags_1 & HOLOGRAM_1) || !can_interact(user) || !user.can_perform_action(src, FORBID_TELEKINESIS_REACH)) return ..() - if(default_deconstruction_screwdriver(user, icon_state, icon_state, item)) - update_appearance() - return + if(is_reagent_container(item) && item.is_open_container()) + if(processing_reagents) + balloon_alert(user, "still processing!") + return ITEM_INTERACT_BLOCKING - if(is_reagent_container(item) && !(item.item_flags & ABSTRACT) && item.is_open_container()) var/obj/item/reagent_containers/beaker = item - . = TRUE //no afterattack if(!user.transferItemToLoc(beaker, src)) - return - replace_beaker(user, BEAKER1, beaker) - to_chat(user, span_notice("You add [beaker] to [src].")) + return ITEM_INTERACT_BLOCKING + + replace_beaker(user, !is_right_clicking, beaker) + to_chat(user, span_notice("You add [beaker] to [is_right_clicking ? "output" : "input"] slot.")) update_appearance() ui_interact(user) - return - ..() + return ITEM_INTERACT_SUCCESS -/obj/machinery/chem_mass_spec/attackby_secondary(obj/item/item, mob/user, params) - . = ..() + return ..() +/obj/machinery/chem_mass_spec/wrench_act(mob/living/user, obj/item/tool) + . = ITEM_INTERACT_BLOCKING if(processing_reagents) - to_chat(user, " The [src] is currently processing a batch!") - return + balloon_alert(user, "still processing!") + return . - if(default_deconstruction_crowbar(item)) - return + if(default_unfasten_wrench(user, tool) == SUCCESSFUL_UNFASTEN) + return ITEM_INTERACT_SUCCESS - if(is_reagent_container(item) && !(item.item_flags & ABSTRACT) && item.is_open_container()) - var/obj/item/reagent_containers/beaker = item - if(!user.transferItemToLoc(beaker, src)) - return - replace_beaker(user, BEAKER2, beaker) - to_chat(user, span_notice("You add [beaker] to [src].")) - ui_interact(user) - . = SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN +/obj/machinery/chem_mass_spec/screwdriver_act(mob/living/user, obj/item/tool) + . = ITEM_INTERACT_BLOCKING + if(processing_reagents) + balloon_alert(user, "still processing!") + return . - update_appearance() + if(default_deconstruction_screwdriver(user, icon_state, icon_state, tool)) + update_appearance() + return ITEM_INTERACT_SUCCESS -/obj/machinery/chem_mass_spec/AltClick(mob/living/user) - . = ..() +/obj/machinery/chem_mass_spec/crowbar_act(mob/living/user, obj/item/tool) + . = ITEM_INTERACT_BLOCKING if(processing_reagents) - to_chat(user, " The [src] is currently processing a batch!") - return - if(!can_interact(user) || !user.can_perform_action(src, FORBID_TELEKINESIS_REACH)) - return ..() - replace_beaker(user, BEAKER1) + balloon_alert(user, "still processing!") + return . -/obj/machinery/chem_mass_spec/alt_click_secondary(mob/living/user) - . = ..() - if(processing_reagents) - to_chat(user, " The [src] is currently processing a batch!") - return - if(!can_interact(user) || !user.can_perform_action(src, FORBID_TELEKINESIS_REACH)) - return - replace_beaker(user, BEAKER2) + if(default_deconstruction_crowbar(tool)) + return ITEM_INTERACT_SUCCESS + + +/** + * Computes either the lightest or heaviest reagent in the input beaker + * Arguments + * + * * smallest - TRUE to find lightest reagent, FALSE to find heaviest reagent + */ +/obj/machinery/chem_mass_spec/proc/calculate_mass(smallest = TRUE) + PRIVATE_PROC(TRUE) + SHOULD_BE_PURE(TRUE) + + if(QDELETED(beaker1)) + return 0 + + var/result = 0 + for(var/datum/reagent/reagent as anything in beaker1?.reagents.reagent_list) + var/datum/reagent/target = reagent + if(!istype(reagent, /datum/reagent/inverse) && (reagent.inverse_chem_val > reagent.purity && reagent.inverse_chem)) + target = GLOB.chemical_reagents_list[reagent.inverse_chem] + + if(!result) + result = target.mass + else + result = smallest ? min(result, reagent.mass) : max(result, reagent.mass) + return smallest ? FLOOR(result, 50) : CEILING(result, 50) -///Gee how come you get two beakers? /* - * Similar to other replace beaker procs, except now there are two of them! - * When passed a beaker along with a position define it will swap a beaker in that slot (if there is one) with the beaker the machine is bonked with + * Replaces a beaker in the machine, either input or output + * Arguments * - * arguments: * * user - The one bonking the machine - * * target beaker - the define (BEAKER1/BEAKER2) of what position to replace + * * target beaker - the target beaker we are trying to replace * * new beaker - the new beaker to add/replace the slot with */ -/obj/machinery/chem_mass_spec/proc/replace_beaker(mob/living/user, target_beaker, obj/item/reagent_containers/new_beaker) - if(!user) - return FALSE - switch(target_beaker) - if(BEAKER1) - if(beaker1) - try_put_in_hand(beaker1, user) - beaker1 = null - beaker1 = new_beaker - lower_mass_range = calculate_smallest_mass() - upper_mass_range = calculate_largest_mass() - if(BEAKER2) - if(beaker2) - try_put_in_hand(beaker2, user) - beaker2 = null - beaker2 = new_beaker +/obj/machinery/chem_mass_spec/proc/replace_beaker(mob/living/user, is_input, obj/item/reagent_containers/new_beaker) + PRIVATE_PROC(TRUE) + + if(is_input) //replace input beaker + if(!QDELETED(beaker1)) + try_put_in_hand(beaker1, user) + beaker1 = new_beaker + lower_mass_range = calculate_mass(smallest = TRUE) + upper_mass_range = calculate_mass(smallest = FALSE) + estimate_time() + + else //replace output beaker + if(!QDELETED(beaker2)) + try_put_in_hand(beaker2, user) + beaker2 = new_beaker + update_appearance() - return TRUE -/* Icon code */ +///Computes time to purity reagents +/obj/machinery/chem_mass_spec/proc/estimate_time() + PRIVATE_PROC(TRUE) -/obj/machinery/chem_mass_spec/update_icon_state() - if(powered()) - icon_state = "HPLC_on" - else - icon_state = "HPLC" - return ..() + delay_time = 0 + if(QDELETED(beaker1)) + return -/obj/machinery/chem_mass_spec/update_overlays() - . = ..() - if(beaker1) - . += "HPLC_beaker1" - if(beaker2) - . += "HPLC_beaker2" - if(powered()) - if(processing_reagents) - . += "HPLC_graph_active" - else if (length(beaker1?.reagents.reagent_list)) - . += "HPLC_graph_idle" + for(var/datum/reagent/reagent as anything in beaker1.reagents.reagent_list) + //we don't bother about impure chems + if(istype(reagent, /datum/reagent/inverse) || (reagent.inverse_chem_val > reagent.purity && reagent.inverse_chem)) + continue + //out of our selected range + if(reagent.mass < lower_mass_range || reagent.mass > upper_mass_range) + continue + //already at max purity + if((initial(reagent.purity) - reagent.purity) <= 0) + continue + ///Roughly 10 - 30s? + delay_time += (((reagent.mass * reagent.volume) + (reagent.mass * reagent.get_inverse_purity() * 0.1)) * 0.0035) + 10 -/* UI Code */ + delay_time *= cms_coefficient /obj/machinery/chem_mass_spec/ui_interact(mob/user, datum/tgui/ui) ui = SStgui.try_update_ui(user, src, ui) @@ -197,209 +278,214 @@ This will not clean any inverted reagents. Inverted reagents will still be corre ui.open() /obj/machinery/chem_mass_spec/ui_data(mob/user) - var/data = list() - data["graphLowerRange"] = 0 - data["lowerRange"] = lower_mass_range - data["upperRange"] = upper_mass_range - data["processing"] = processing_reagents - data["log"] = log - data["beaker1"] = beaker1 ? TRUE : FALSE - data["beaker2"] = beaker2 ? TRUE : FALSE - if(processing_reagents) - data["eta"] = delay_time - progress_time - else - data["eta"] = estimate_time() - - var/beakerContents[0] - if(beaker1 && beaker1.reagents) - for(var/datum/reagent/reagent as anything in beaker1.reagents.reagent_list) - var/in_range = TRUE - if(reagent.inverse_chem_val > reagent.purity && reagent.inverse_chem) - var/datum/reagent/inverse_reagent = GLOB.chemical_reagents_list[reagent.inverse_chem] - if(inverse_reagent.mass < lower_mass_range || inverse_reagent.mass > upper_mass_range) - in_range = FALSE - beakerContents.Add(list(list("name" = inverse_reagent.name, "volume" = round(reagent.volume, 0.01), "mass" = inverse_reagent.mass, "purity" = round(reagent.get_inverse_purity(), 0.000001)*100, "selected" = in_range, "color" = "#b60046", "type" = "Inverted"))) - data["peakHeight"] = max(data["peakHeight"], reagent.volume) - continue - if(reagent.mass < lower_mass_range || reagent.mass > upper_mass_range) - in_range = FALSE - ///We want to be sure that the impure chem appears after the parent chem in the list so that it always overshadows pure reagents - beakerContents.Add(list(list("name" = reagent.name, "volume" = round(reagent.volume, 0.01), "mass" = reagent.mass, "purity" = round(reagent.purity, 0.000001)*100, "selected" = in_range, "color" = "#3cf096", "type" = "Clean"))) - data["peakHeight"] = max(data["peakHeight"], reagent.volume) - - data["beaker1CurrentVolume"] = beaker1.reagents.total_volume - data["beaker1MaxVolume"] = beaker1.reagents.maximum_volume - data["beaker1Contents"] = beakerContents - data["graphUpperRange"] = calculate_largest_mass() //+10 because of the range on the peak - - beakerContents = list() - if(beaker2 && beaker2.reagents) - for(var/datum/reagent/reagent in beaker2.reagents.reagent_list) - ///Normal stuff - beakerContents.Add(list(list("name" = reagent.name, "volume" = round(reagent.volume, 0.01), "mass" = reagent.mass, "purity" = round(reagent.purity, 0.000001)*100, "color" = "#3cf096", "type" = "Clean", log = log[reagent.type]))) - data["beaker2CurrentVolume"] = beaker2.reagents.total_volume - data["beaker2MaxVolume"] = beaker2.reagents.maximum_volume - data["beaker2Contents"] = beakerContents - - return data - -/obj/machinery/chem_mass_spec/ui_act(action, params) + . = list() + .["lowerRange"] = lower_mass_range + .["upperRange"] = upper_mass_range + .["processing"] = processing_reagents + .["eta"] = delay_time - progress_time + .["peakHeight"] = 0 + + //input reagents + var/list/beaker1Data = null + if(!QDELETED(beaker1)) + beaker1Data = list() + var/datum/reagents/beaker_1_reagents = beaker1.reagents + beaker1Data["currentVolume"] = beaker_1_reagents.total_volume + beaker1Data["maxVolume"] = beaker_1_reagents.maximum_volume + var/list/beakerContents = list() + for(var/datum/reagent/reagent as anything in beaker_1_reagents.reagent_list) + var/log = "" + var/datum/reagent/target = reagent + var/purity = target.purity + var/is_inverse = FALSE + + if(istype(reagent, /datum/reagent/inverse)) + log = "Too impure to use" //we don't bother about impure chems + is_inverse = TRUE + else if(reagent.inverse_chem_val > reagent.purity && reagent.inverse_chem) + purity = target.get_inverse_purity() + target = GLOB.chemical_reagents_list[reagent.inverse_chem] + log = "Too impure to use" //we don't bother about impure chems + is_inverse = TRUE + else + var/initial_purity = initial(reagent.purity) + if((initial_purity - reagent.purity) <= 0) //already at max purity + log = "Cannot purify above [round(initial_purity * 100)]%" + else + log = "Ready" + + beakerContents += list(list( + "name" = target.name, + "volume" = round(reagent.volume, CHEMICAL_VOLUME_ROUNDING), + "mass" = target.mass, + "purity" = round(purity * 100), + "type" = is_inverse ? "Inverted" : "Clean", + "log" = log + )) + .["peakHeight"] = max(.["peakHeight"], reagent.volume) + beaker1Data["contents"] = beakerContents + .["beaker1"] = beaker1Data + + //+10 because of the range on the peak + .["graphUpperRange"] = calculate_mass(smallest = FALSE) + + //output reagents + var/list/beaker2Data = null + if(!QDELETED(beaker2)) + beaker2Data = list() + var/datum/reagents/beaker_2_reagents = beaker2.reagents + beaker2Data["currentVolume"] = beaker_2_reagents.total_volume + beaker2Data["maxVolume"] = beaker_2_reagents.maximum_volume + var/list/beakerContents = list() + for(var/datum/reagent/reagent as anything in beaker_2_reagents.reagent_list) + beakerContents += list(list( + "name" = reagent.name, + "volume" = round(reagent.volume, CHEMICAL_VOLUME_ROUNDING), + "mass" = reagent.mass, + "purity" = round(reagent.purity * 100), + "type" = "Clean", + "log" = log[reagent.type] + )) + beaker2Data["contents"] = beakerContents + .["beaker2"] = beaker2Data + +/obj/machinery/chem_mass_spec/ui_act(action, params, datum/tgui/ui, datum/ui_state/state) . = ..() if(.) return + + if(processing_reagents) + balloon_alert(ui.user, "still processing") + return ..() + switch(action) if("activate") - if(!beaker1 || !beaker2 || !is_operational) - say("This [src] is missing an output beaker!") + if(QDELETED(beaker1)) + say("Missing input beaker!") return - if(processing_reagents) - say("You shouldn't be seeing this message! Please report this bug to https://github.com/tgstation/tgstation/issues . Thank you!") - stack_trace("Someone managed to break the HPLC and tried to get it to activate when it's already activated!") + if(QDELETED(beaker2)) + say("Missing output beaker!") return - processing_reagents = TRUE - estimate_time() + + //adjust timer for purification progress_time = 0 - update_appearance() + estimate_time() + if(delay_time <= 0) + say("No work to be done!") + return + + //start the purification process + processing_reagents = TRUE begin_processing() - . = TRUE + update_appearance() + + return TRUE + if("leftSlider") - if(!is_operational || processing_reagents) + var/value = params["value"] + if(isnull(value)) + return + + value = text2num(value) + if(isnull(value)) return - var/current_center = (lower_mass_range + upper_mass_range)/2 - lower_mass_range = clamp(params["value"], calculate_smallest_mass(), current_center) - . = TRUE + + lower_mass_range = clamp(value, calculate_mass(smallest = TRUE), (lower_mass_range + upper_mass_range) / 2) + estimate_time() + return TRUE + if("rightSlider") - if(!is_operational || processing_reagents) + var/value = params["value"] + if(isnull(value)) + return + + value = text2num(value) + if(isnull(value)) return - var/current_center = (lower_mass_range + upper_mass_range)/2 - upper_mass_range = clamp(params["value"], current_center, calculate_largest_mass()) - . = TRUE + + upper_mass_range = clamp(value, (lower_mass_range + upper_mass_range) / 2, calculate_mass(smallest = FALSE)) + estimate_time() + return TRUE + if("centerSlider") - if(!is_operational || processing_reagents) + var/value = params["value"] + if(isnull(value)) return - var/current_center = (lower_mass_range + upper_mass_range)/2 - var/delta_center = current_center - params["value"] - var/lowest = calculate_smallest_mass() - var/highest = calculate_largest_mass() + + value = text2num(value) + if(isnull(value)) + return + + var/delta_center = ((lower_mass_range + upper_mass_range) / 2) - params["value"] + var/lowest = calculate_mass(smallest = TRUE) + var/highest = calculate_mass(smallest = FALSE) lower_mass_range = clamp(lower_mass_range - delta_center, lowest, highest) upper_mass_range = clamp(upper_mass_range - delta_center, lowest, highest) - . = TRUE + estimate_time() + + return TRUE + if("eject1") - if(processing_reagents) - return - replace_beaker(usr, BEAKER1) - . = TRUE + replace_beaker(ui.user, TRUE) + return TRUE + if("eject2") - if(processing_reagents) - return - replace_beaker(usr, BEAKER2) - . = TRUE + replace_beaker(ui.user, FALSE) + return TRUE + +/obj/machinery/chem_mass_spec/AltClick(mob/living/user) + . = ..() + if(!can_interact(user)) + return + if(processing_reagents) + balloon_alert(user, "still processing!") + return ..() + replace_beaker(user, TRUE) -/* processing procs */ +/obj/machinery/chem_mass_spec/alt_click_secondary(mob/living/user) + . = ..() + if(!can_interact(user)) + return + if(processing_reagents) + balloon_alert(user, "still processing!") + return ..() + replace_beaker(user, FALSE) -///Increments time if it's progressing - if it's past time then it purifies and stops processing /obj/machinery/chem_mass_spec/process(seconds_per_tick) - . = ..() - if(!is_operational) - return FALSE if(!processing_reagents) - return TRUE + return PROCESS_KILL + + if(!is_operational || panel_open || !anchored || (machine_stat & (BROKEN | NOPOWER))) + return + use_power(active_power_usage) + + progress_time += seconds_per_tick if(progress_time >= delay_time) processing_reagents = FALSE progress_time = 0 - purify_reagents() - end_processing() - update_appearance() - return TRUE - progress_time += seconds_per_tick - return FALSE -/* - * Processing through the reagents in beaker 1 - * For all the reagents within the selected range - we will then purify them up to their initial purity (usually 75%). It will take away the relative reagent volume from the sum volume of the reagent however. - * If there are any inverted reagents - then it will instead just create a new reagent of the inverted type. This doesn't really do anything other than change the name of it, - * As it processes through the reagents, it saves what changes were applied to each reagent in a log var to show the results at the end - */ -/obj/machinery/chem_mass_spec/proc/purify_reagents() - log = list() - for(var/datum/reagent/reagent as anything in beaker1.reagents.reagent_list) - //Inverse first - var/volume = reagent.volume - if(reagent.inverse_chem_val > reagent.purity && reagent.inverse_chem) - var/datum/reagent/inverse_reagent = GLOB.chemical_reagents_list[reagent.inverse_chem] - if(inverse_reagent.mass < lower_mass_range || inverse_reagent.mass > upper_mass_range) + log.Cut() + for(var/datum/reagent/reagent as anything in beaker1.reagents.reagent_list) + //we don't bother about impure chems + if(istype(reagent, /datum/reagent/inverse) || (reagent.inverse_chem_val > reagent.purity && reagent.inverse_chem)) continue - log += list(inverse_reagent.type = "Cannot purify inverted") //Might as well make it do something - just updates the reagent's name - beaker2.reagents.add_reagent(reagent.inverse_chem, volume, reagtemp = beaker1.reagents.chem_temp, added_purity = reagent.get_inverse_purity()) - beaker1.reagents.remove_reagent(reagent.type, volume) - continue - - if(reagent.mass < lower_mass_range || reagent.mass > upper_mass_range) - continue - - var/delta_purity = initial(reagent.purity) - reagent.purity - if(delta_purity <= 0)//As pure as we can be - so lets not add more than we need - log += list(reagent.type = "Can't purify over [initial(reagent.purity)*100]%") - beaker2.reagents.add_reagent(reagent.type, volume, reagtemp = beaker1.reagents.chem_temp, added_purity = reagent.purity, added_ph = reagent.ph) - beaker1.reagents.remove_reagent(reagent.type, volume) - continue - - var/product_vol = reagent.volume * (1-delta_purity) - beaker2.reagents.add_reagent(reagent.type, product_vol, reagtemp = beaker1.reagents.chem_temp, added_purity = initial(reagent.purity), added_ph = reagent.ph) - beaker1.reagents.remove_reagent(reagent.type, reagent.volume) - log += list(reagent.type = "Purified to [initial(reagent.purity)*100]%") - -/* Mass spec graph calcs */ - -///Returns the largest mass to the nearest 50 (rounded up) -/obj/machinery/chem_mass_spec/proc/calculate_largest_mass() - if(!beaker1?.reagents) - return 0 - var/max_mass = 0 - for(var/datum/reagent/reagent as anything in beaker1.reagents.reagent_list) - if(reagent.inverse_chem_val > reagent.purity && reagent.inverse_chem) - var/datum/reagent/inverse_reagent = GLOB.chemical_reagents_list[reagent.inverse_chem] - max_mass = max(max_mass, inverse_reagent.mass) - continue - max_mass = max(max_mass, reagent.mass) - return CEILING(max_mass, 50) - -///Returns the smallest mass to the nearest 50 (rounded down) -/obj/machinery/chem_mass_spec/proc/calculate_smallest_mass() - if(!beaker1?.reagents) - return 0 - var/min_mass = 0 - for(var/datum/reagent/reagent as anything in beaker1.reagents.reagent_list) - if(reagent.inverse_chem_val > reagent.purity && reagent.inverse_chem) - var/datum/reagent/inverse_reagent = GLOB.chemical_reagents_list[reagent.inverse_chem] - min_mass = min(min_mass, inverse_reagent.mass) - continue - min_mass = min(min_mass, reagent.mass) - return FLOOR(min_mass, 50) - -/* - * Estimates how long the highlighted range will take to process - * The time will increase based off the reagent's volume, mass and purity. - * In most cases this is between 10 to 30s for a single reagent. - * This is why having a higher mass for a reagent is a balancing tool. - */ -/obj/machinery/chem_mass_spec/proc/estimate_time() - if(!beaker1?.reagents) - return 0 - var/time = 0 - for(var/datum/reagent/reagent as anything in beaker1.reagents.reagent_list) - if(reagent.inverse_chem_val > reagent.purity && reagent.inverse_chem) - var/datum/reagent/inverse_reagent = GLOB.chemical_reagents_list[reagent.inverse_chem] - if(inverse_reagent.mass < lower_mass_range || inverse_reagent.mass > upper_mass_range) + //out of our selected range + if(reagent.mass < lower_mass_range || reagent.mass > upper_mass_range) continue - time += (((inverse_reagent.mass * reagent.volume) + (inverse_reagent.mass * reagent.purity * 0.1)) * 0.003) + 10 ///Roughly 10 - 30s? - continue - if(reagent.mass < lower_mass_range || reagent.mass > upper_mass_range) - continue - time += (((reagent.mass * reagent.volume) + (reagent.mass * reagent.get_inverse_purity() * 0.1)) * 0.0035) + 10 ///Roughly 10 - 30s? - delay_time = (time * cms_coefficient) - return delay_time - -#undef BEAKER1 -#undef BEAKER2 + //already at max purity + var/delta_purity = initial(reagent.purity) - reagent.purity + if(delta_purity <= 0) + continue + //add the purified reagent. More impure reagents will yield smaller amounts + var/product_vol = reagent.volume + beaker1.reagents.remove_reagent(reagent.type, product_vol) + beaker2.reagents.add_reagent(reagent.type, product_vol * (1 - delta_purity), reagtemp = beaker1.reagents.chem_temp, added_purity = initial(reagent.purity), added_ph = reagent.ph) + log[reagent.type] = "Purified to [initial(reagent.purity) * 100]%" + + //recompute everything + lower_mass_range = calculate_mass(smallest = TRUE) + upper_mass_range = calculate_mass(smallest = FALSE) + estimate_time() + update_appearance() + return PROCESS_KILL diff --git a/code/modules/reagents/chemistry/machinery/portable_chem_mixer.dm b/code/modules/reagents/chemistry/machinery/portable_chem_mixer.dm index 791feb800390ec6..a6113d2f0c6e410 100644 --- a/code/modules/reagents/chemistry/machinery/portable_chem_mixer.dm +++ b/code/modules/reagents/chemistry/machinery/portable_chem_mixer.dm @@ -105,7 +105,7 @@ /obj/item/storage/portable_chem_mixer/ex_act(severity, target) return severity > EXPLODE_LIGHT ? ..() : FALSE -/obj/item/storage/portable_chem_mixer/attackby(obj/item/weapon, mob/user, params) +/obj/item/storage/portable_chem_mixer/item_interaction(mob/living/user, obj/item/weapon, list/modifiers, is_right_clicking) if (!atom_storage.locked || \ (weapon.item_flags & ABSTRACT) || \ (weapon.flags_1 & HOLOGRAM_1) || \ @@ -116,7 +116,7 @@ replace_beaker(user, weapon) update_appearance() - return TRUE + return ITEM_INTERACT_SUCCESS /** * Replaces the beaker of the portable chemical mixer with another beaker, or simply adds the new beaker if none is in currently @@ -185,11 +185,11 @@ beaker_data["maxVolume"] = beaker.volume beaker_data["transferAmounts"] = beaker.possible_transfer_amounts beaker_data["pH"] = round(beaker.reagents.ph, 0.01) - beaker_data["currentVolume"] = round(beaker.reagents.total_volume, 0.01) + beaker_data["currentVolume"] = round(beaker.reagents.total_volume, CHEMICAL_VOLUME_ROUNDING) var/list/beakerContents = list() if(length(beaker.reagents.reagent_list)) for(var/datum/reagent/reagent in beaker.reagents.reagent_list) - beakerContents += list(list("name" = reagent.name, "volume" = round(reagent.volume, 0.01))) // list in a list because Byond merges the first list... + beakerContents += list(list("name" = reagent.name, "volume" = round(reagent.volume, CHEMICAL_VOLUME_ROUNDING))) // list in a list because Byond merges the first list... beaker_data["contents"] = beakerContents .["beaker"] = beaker_data diff --git a/code/modules/reagents/chemistry/reagents/drinks/drink_reagents.dm b/code/modules/reagents/chemistry/reagents/drinks/drink_reagents.dm index 43430d094691628..c31b7e7079c97ba 100644 --- a/code/modules/reagents/chemistry/reagents/drinks/drink_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/drinks/drink_reagents.dm @@ -639,7 +639,7 @@ . = ..() affected_mob.adjust_drowsiness(3 SECONDS * REM * seconds_per_tick) var/need_mob_update - switch(affected_mob.mob_mood.sanity_level) + switch(affected_mob.mob_mood.sanity) if (SANITY_INSANE to SANITY_CRAZY) need_mob_update = affected_mob.adjustStaminaLoss(3 * REM * seconds_per_tick, updating_stamina = FALSE) if (SANITY_UNSTABLE to SANITY_DISTURBED) diff --git a/code/modules/reagents/chemistry/reagents/drug_reagents.dm b/code/modules/reagents/chemistry/reagents/drug_reagents.dm index 43a3d340831a0d2..0172c65c3d7f3cc 100644 --- a/code/modules/reagents/chemistry/reagents/drug_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/drug_reagents.dm @@ -87,11 +87,8 @@ to_chat(affected_mob, span_notice("[smoke_message]")) affected_mob.add_mood_event("smoked", /datum/mood_event/smoked) affected_mob.remove_status_effect(/datum/status_effect/jitter) - affected_mob.AdjustStun(-50 * REM * seconds_per_tick) - affected_mob.AdjustKnockdown(-50 * REM * seconds_per_tick) - affected_mob.AdjustUnconscious(-50 * REM * seconds_per_tick) - affected_mob.AdjustParalyzed(-50 * REM * seconds_per_tick) - affected_mob.AdjustImmobilized(-50 * REM * seconds_per_tick) + affected_mob.AdjustAllImmobility(-50 * REM * seconds_per_tick) + return UPDATE_MOB_HEALTH /datum/reagent/drug/nicotine/overdose_process(mob/living/affected_mob, seconds_per_tick, times_fired) @@ -177,11 +174,7 @@ if(SPT_PROB(2.5, seconds_per_tick)) to_chat(affected_mob, span_notice("[high_message]")) affected_mob.add_mood_event("tweaking", /datum/mood_event/stimulant_medium) - affected_mob.AdjustStun(-40 * REM * seconds_per_tick) - affected_mob.AdjustKnockdown(-40 * REM * seconds_per_tick) - affected_mob.AdjustUnconscious(-40 * REM * seconds_per_tick) - affected_mob.AdjustParalyzed(-40 * REM * seconds_per_tick) - affected_mob.AdjustImmobilized(-40 * REM * seconds_per_tick) + affected_mob.AdjustAllImmobility(-40 * REM * seconds_per_tick) var/need_mob_update need_mob_update = affected_mob.adjustStaminaLoss(-2 * REM * seconds_per_tick, updating_stamina = FALSE, required_biotype = affected_biotype) affected_mob.set_jitter_if_lower(4 SECONDS * REM * seconds_per_tick) @@ -459,11 +452,7 @@ /datum/reagent/drug/maint/tar/on_mob_life(mob/living/carbon/affected_mob, seconds_per_tick, times_fired) . = ..() - affected_mob.AdjustStun(-10 * REM * seconds_per_tick) - affected_mob.AdjustKnockdown(-10 * REM * seconds_per_tick) - affected_mob.AdjustUnconscious(-10 * REM * seconds_per_tick) - affected_mob.AdjustParalyzed(-10 * REM * seconds_per_tick) - affected_mob.AdjustImmobilized(-10 * REM * seconds_per_tick) + affected_mob.AdjustAllImmobility(-10 * REM * seconds_per_tick) affected_mob.adjustOrganLoss(ORGAN_SLOT_LIVER, 1.5 * REM * seconds_per_tick, required_organ_flag = affected_organ_flags) return UPDATE_MOB_HEALTH diff --git a/code/modules/reagents/chemistry/reagents/medicine_reagents.dm b/code/modules/reagents/chemistry/reagents/medicine_reagents.dm index 90c68e8b9d5bfdd..cd11731ee4b1e09 100644 --- a/code/modules/reagents/chemistry/reagents/medicine_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/medicine_reagents.dm @@ -88,11 +88,8 @@ /datum/reagent/medicine/synaptizine/on_mob_life(mob/living/carbon/affected_mob, seconds_per_tick, times_fired) . = ..() affected_mob.adjust_drowsiness(-10 SECONDS * REM * seconds_per_tick) - affected_mob.AdjustStun(-20 * REM * seconds_per_tick) - affected_mob.AdjustKnockdown(-20 * REM * seconds_per_tick) - affected_mob.AdjustUnconscious(-20 * REM * seconds_per_tick) - affected_mob.AdjustImmobilized(-20 * REM * seconds_per_tick) - affected_mob.AdjustParalyzed(-20 * REM * seconds_per_tick) + affected_mob.AdjustAllImmobility(-20 * REM * seconds_per_tick) + if(holder.has_reagent(/datum/reagent/toxin/mindbreaker)) holder.remove_reagent(/datum/reagent/toxin/mindbreaker, 5 * REM * seconds_per_tick) affected_mob.adjust_hallucinations(-20 SECONDS * REM * seconds_per_tick) @@ -589,6 +586,8 @@ /datum/reagent/medicine/ephedrine/on_mob_metabolize(mob/living/affected_mob) . = ..() affected_mob.add_movespeed_modifier(/datum/movespeed_modifier/reagent/ephedrine) + var/purity_movespeed_accounting = -0.375 * normalise_creation_purity() + affected_mob.add_or_update_variable_movespeed_modifier(/datum/movespeed_modifier/reagent/ephedrine, TRUE, purity_movespeed_accounting) /datum/reagent/medicine/ephedrine/on_mob_end_metabolize(mob/living/affected_mob) . = ..() @@ -596,14 +595,15 @@ /datum/reagent/medicine/ephedrine/on_mob_life(mob/living/carbon/affected_mob, seconds_per_tick, times_fired) . = ..() - if(SPT_PROB(10 * (1.5-creation_purity), seconds_per_tick) && iscarbon(affected_mob)) - var/obj/item/I = affected_mob.get_active_held_item() - if(I && affected_mob.dropItemToGround(I)) + var/obj/item/active_held_item = affected_mob.get_active_held_item() + if(SPT_PROB(10 * (1.5-creation_purity), seconds_per_tick) && iscarbon(affected_mob) && active_held_item?.w_class > WEIGHT_CLASS_SMALL) + if(active_held_item && affected_mob.dropItemToGround(active_held_item)) to_chat(affected_mob, span_notice("Your hands spaz out and you drop what you were holding!")) affected_mob.set_jitter_if_lower(20 SECONDS) affected_mob.AdjustAllImmobility(-20 * REM * seconds_per_tick * normalise_creation_purity()) affected_mob.adjustStaminaLoss(-1 * REM * seconds_per_tick * normalise_creation_purity(), updating_stamina = FALSE) + return UPDATE_MOB_HEALTH /datum/reagent/medicine/ephedrine/overdose_process(mob/living/affected_mob, seconds_per_tick, times_fired) diff --git a/code/modules/reagents/chemistry/reagents/unique/eigenstasium.dm b/code/modules/reagents/chemistry/reagents/unique/eigenstasium.dm index 1cb0e6204c2e7e6..7c18c7e2014664c 100644 --- a/code/modules/reagents/chemistry/reagents/unique/eigenstasium.dm +++ b/code/modules/reagents/chemistry/reagents/unique/eigenstasium.dm @@ -118,4 +118,4 @@ lockers += closet if(!length(lockers)) return - SSeigenstates.create_new_link(lockers) + GLOB.eigenstate_manager.create_new_link(lockers) diff --git a/code/modules/reagents/chemistry/recipes/cat2_medicines.dm b/code/modules/reagents/chemistry/recipes/cat2_medicines.dm index c61a7739377360c..376a805e7d6970b 100644 --- a/code/modules/reagents/chemistry/recipes/cat2_medicines.dm +++ b/code/modules/reagents/chemistry/recipes/cat2_medicines.dm @@ -211,7 +211,6 @@ required_reagents = list(/datum/reagent/nitrogen = 3, /datum/reagent/acetone = 2) required_catalysts = list(/datum/reagent/toxin/acid = 1) mix_message = "The mixture turns into a tired reddish pink liquid." - optimal_temp = 1 optimal_temp = 900 overheat_temp = 720 optimal_ph_min = 2 diff --git a/code/modules/reagents/chemistry/recipes/slime_extracts.dm b/code/modules/reagents/chemistry/recipes/slime_extracts.dm index f37f9ebb081c06c..84a242227bccf33 100644 --- a/code/modules/reagents/chemistry/recipes/slime_extracts.dm +++ b/code/modules/reagents/chemistry/recipes/slime_extracts.dm @@ -149,7 +149,7 @@ if(prob(5))//Fry it! food_item.AddElement(/datum/element/fried_item, rand(15, 60)) if(prob(5))//Grill it! - food_item.AddElement(/datum/element/grilled_item, rand(30, 100)) + food_item.AddElement(/datum/element/grilled_item, rand(30 SECONDS, 100 SECONDS)) if(prob(50)) for(var/j in 1 to rand(1, 3)) step(food_item, pick(NORTH,SOUTH,EAST,WEST)) diff --git a/code/modules/reagents/reagent_containers/condiment.dm b/code/modules/reagents/reagent_containers/condiment.dm index ca941be8ca1317b..a5a68315b87882a 100644 --- a/code/modules/reagents/reagent_containers/condiment.dm +++ b/code/modules/reagents/reagent_containers/condiment.dm @@ -426,6 +426,7 @@ /datum/reagent/consumable/bbqsauce = list("condi_bbq", "BBQ sauce", "Hand wipes not included."), /datum/reagent/consumable/peanut_butter = list("condi_peanutbutter", "Peanut Butter", "A creamy paste made from ground peanuts."), /datum/reagent/consumable/cherryjelly = list("condi_cherryjelly", "Cherry Jelly", "A jar of super-sweet cherry jelly."), + /datum/reagent/consumable/mayonnaise = list("condi_mayo", "Mayonnaise", "Not an instrument."), ) /// Can't use initial(name) for this. This stores the name set by condimasters. var/originalname = "condiment" @@ -518,3 +519,15 @@ originalname = "sugar" volume = 5 list_reagents = list(/datum/reagent/consumable/sugar = 5) + +/obj/item/reagent_containers/condiment/pack/soysauce + name = "soy sauce pack" + originalname = "soy sauce" + volume = 5 + list_reagents = list(/datum/reagent/consumable/soysauce = 5) + +/obj/item/reagent_containers/condiment/pack/mayonnaise + name = "mayonnaise pack" + originalname = "mayonnaise" + volume = 5 + list_reagents = list(/datum/reagent/consumable/mayonnaise = 5) diff --git a/code/modules/religion/festival/instrument_rites.dm b/code/modules/religion/festival/instrument_rites.dm index d8537f5845ea0a8..4b5c1afa18bbb3c 100644 --- a/code/modules/religion/festival/instrument_rites.dm +++ b/code/modules/religion/festival/instrument_rites.dm @@ -138,7 +138,7 @@ var/obj/effect/dummy/lighting_obj/moblight/performer_light_obj /datum/religion_rites/song_tuner/light/performer_start_effect(mob/living/carbon/human/performer, atom/song_source) - performer_light_obj = performer.mob_light(8, color = LIGHT_COLOR_DIM_YELLOW) + performer_light_obj = performer.mob_light(8, 1.5, color = LIGHT_COLOR_DIM_YELLOW) /datum/religion_rites/song_tuner/light/Destroy() QDEL_NULL(performer_light_obj) diff --git a/code/modules/research/designs/autolathe/engineering_designs.dm b/code/modules/research/designs/autolathe/engineering_designs.dm index 6249f5c645a1f16..945966035f3d1f5 100644 --- a/code/modules/research/designs/autolathe/engineering_designs.dm +++ b/code/modules/research/designs/autolathe/engineering_designs.dm @@ -426,3 +426,29 @@ RND_CATEGORY_CONSTRUCTION + RND_SUBCATEGORY_CONSTRUCTION_MOUNTS, ) departmental_flags = DEPARTMENT_BITFLAG_ENGINEERING + +/datum/design/tram_floor_dark + name = "Dark Tram Tile" + id = "tram_floor_dark" + build_type = PROTOLATHE + materials = list(/datum/material/plastic = SHEET_MATERIAL_AMOUNT * 0.25) + build_path = /obj/item/stack/thermoplastic + maxstack = 50 + category = list( + RND_CATEGORY_INITIAL, + RND_CATEGORY_CONSTRUCTION + RND_SUBCATEGORY_CONSTRUCTION_MATERIALS, + ) + departmental_flags = DEPARTMENT_BITFLAG_ENGINEERING + +/datum/design/tram_floor_light + name = "Light Tram Tile" + id = "tram_floor_light" + build_type = PROTOLATHE + materials = list(/datum/material/plastic = SHEET_MATERIAL_AMOUNT * 0.25) + build_path = /obj/item/stack/thermoplastic/light + maxstack = 50 + category = list( + RND_CATEGORY_INITIAL, + RND_CATEGORY_CONSTRUCTION + RND_SUBCATEGORY_CONSTRUCTION_MATERIALS, + ) + departmental_flags = DEPARTMENT_BITFLAG_ENGINEERING diff --git a/code/modules/research/machinery/_production.dm b/code/modules/research/machinery/_production.dm index f95145b4b94063e..b0eac18418cf4db 100644 --- a/code/modules/research/machinery/_production.dm +++ b/code/modules/research/machinery/_production.dm @@ -28,7 +28,7 @@ /datum/component/remote_materials, \ mapload, \ mat_container_signals = list( \ - COMSIG_MATCONTAINER_ITEM_CONSUMED = TYPE_PROC_REF(/obj/machinery/rnd, local_material_insert) + COMSIG_MATCONTAINER_ITEM_CONSUMED = TYPE_PROC_REF(/obj/machinery/rnd/production, local_material_insert) ) \ ) @@ -49,7 +49,6 @@ cached_designs = null return ..() - // Stuff for the stripe on the department machines /obj/machinery/rnd/production/default_deconstruction_screwdriver(mob/user, icon_state_open, icon_state_closed, obj/item/screwdriver) . = ..() @@ -128,7 +127,7 @@ addtimer(CALLBACK(src, PROC_REF(update_designs)), 2 SECONDS, TIMER_UNIQUE | TIMER_OVERRIDE) ///When materials are instered via silo link -/obj/machinery/rnd/proc/silo_material_insert(obj/machinery/rnd/machine, container, obj/item/item_inserted, last_inserted_id, list/mats_consumed, amount_inserted) +/obj/machinery/rnd/production/proc/silo_material_insert(obj/machinery/rnd/machine, container, obj/item/item_inserted, last_inserted_id, list/mats_consumed, amount_inserted) SIGNAL_HANDLER process_item(item_inserted, mats_consumed, amount_inserted) @@ -141,37 +140,39 @@ * * list/mats_consumed - list of mats consumed * * amount_inserted - amount of material actually processed */ -/obj/machinery/rnd/proc/process_item(obj/item/item_inserted, list/mats_consumed, amount_inserted) +/obj/machinery/rnd/production/proc/process_item(obj/item/item_inserted, list/mats_consumed, amount_inserted) PRIVATE_PROC(TRUE) //we use initial(active_power_usage) because higher tier parts will have higher active usage but we have no benifit from it - if(directly_use_power(ROUND_UP((amount_inserted / (MAX_STACK_SIZE * SHEET_MATERIAL_AMOUNT)) * 0.01 * initial(active_power_usage)))) - var/mat_name = "iron" + if(directly_use_power(ROUND_UP((amount_inserted / (MAX_STACK_SIZE * SHEET_MATERIAL_AMOUNT)) * 0.02 * initial(active_power_usage)))) + var/datum/material/highest_mat_ref var/highest_mat = 0 for(var/datum/material/mat as anything in mats_consumed) var/present_mat = mats_consumed[mat] if(present_mat > highest_mat) - mat_name = initial(mat.name) - if(mat_name == "silver" || mat_name == "titanium" || mat_name == "plastic") //these materials have similar appearances so use an common overlay for them - mat_name = "shiny" highest_mat = present_mat + highest_mat_ref = mat - flick_animation(mat_name) + flick_animation(highest_mat_ref) /** * Plays an visual animation when materials are inserted * Arguments * - * * mat_name - the name of the material we are trying to animate on the machine + * * mat - the material ref we are trying to animate on the machine */ -/obj/machinery/rnd/proc/flick_animation(mat_name) +/obj/machinery/rnd/production/proc/flick_animation(datum/material/mat_ref) PROTECTED_PROC(TRUE) SHOULD_CALL_PARENT(FALSE) - flick_overlay_view(mutable_appearance('icons/obj/machines/research.dmi', "protolathe_[mat_name]"), 1 SECONDS) + //first play the insertion animation + flick_overlay_view(material_insertion_animation(mat_ref.greyscale_colors), 1 SECONDS) + + //now play the progress bar animation + flick_overlay_view(mutable_appearance('icons/obj/machines/research.dmi', "protolathe_progress"), 1 SECONDS) ///When materials are instered into local storage -/obj/machinery/rnd/proc/local_material_insert(container, obj/item/item_inserted, last_inserted_id, list/mats_consumed, amount_inserted, atom/context) +/obj/machinery/rnd/production/proc/local_material_insert(container, obj/item/item_inserted, last_inserted_id, list/mats_consumed, amount_inserted, atom/context) SIGNAL_HANDLER process_item(item_inserted, mats_consumed, amount_inserted) @@ -288,7 +289,7 @@ return //we use initial(active_power_usage) because higher tier parts will have higher active usage but we have no benifit from it - if(!directly_use_power(ROUND_UP((amount / MAX_STACK_SIZE) * 0.01 * initial(active_power_usage)))) + if(!directly_use_power(ROUND_UP((amount / MAX_STACK_SIZE) * 0.02 * initial(active_power_usage)))) say("No power to dispense sheets") return @@ -379,6 +380,7 @@ finalize_build() return if(!materials.can_use_resource()) + say("Unable to continue production, materials on hold.") finalize_build() return @@ -386,6 +388,7 @@ var/list/design_materials = design.materials if(!materials.mat_container.has_materials(design_materials, material_cost_coefficient, is_stack ? items_remaining : 1)) say("Unable to continue production, missing materials.") + finalize_build() return materials.use_materials(design_materials, material_cost_coefficient, is_stack ? items_remaining : 1, "built", "[design.name]") diff --git a/code/modules/research/machinery/circuit_imprinter.dm b/code/modules/research/machinery/circuit_imprinter.dm index 2dcbde23663ad40..c6d50f13307b53d 100644 --- a/code/modules/research/machinery/circuit_imprinter.dm +++ b/code/modules/research/machinery/circuit_imprinter.dm @@ -13,7 +13,7 @@ return 0.5 ** max(rating - 1, 0) // One sheet, half sheet, quarter sheet, eighth sheet. -/obj/machinery/rnd/production/circuit_imprinter/flick_animation(mat_name) +/obj/machinery/rnd/production/circuit_imprinter/flick_animation(datum/material/mat) return //we presently have no animation /obj/machinery/rnd/production/circuit_imprinter/offstation diff --git a/code/modules/research/ordnance/doppler_array.dm b/code/modules/research/ordnance/doppler_array.dm index a6fe3c9f3ac0e0e..7afe201f360071d 100644 --- a/code/modules/research/ordnance/doppler_array.dm +++ b/code/modules/research/ordnance/doppler_array.dm @@ -20,7 +20,7 @@ // Lighting system to better communicate the directions. light_system = OVERLAY_LIGHT_DIRECTIONAL light_range = 4 - light_power = 1 + light_power = 1.5 light_color = COLOR_RED /obj/machinery/doppler_array/Initialize(mapload) diff --git a/code/modules/research/techweb/all_nodes.dm b/code/modules/research/techweb/all_nodes.dm index b6b6d2f7b8bd2f6..775a6f02b2d79f5 100644 --- a/code/modules/research/techweb/all_nodes.dm +++ b/code/modules/research/techweb/all_nodes.dm @@ -121,6 +121,8 @@ "toy_armblade", "toy_balloon", "toygun", + "tram_floor_dark", + "tram_floor_light", "trapdoor_electronics", "turbine_part_compressor", "turbine_part_rotor", diff --git a/code/modules/shuttle/on_move.dm b/code/modules/shuttle/on_move.dm index 7c8b26b5d16bfc6..417f56d241c9868 100644 --- a/code/modules/shuttle/on_move.dm +++ b/code/modules/shuttle/on_move.dm @@ -21,26 +21,22 @@ All ShuttleMove procs go here return var/shuttle_dir = shuttle.dir - for(var/i in contents) - var/atom/movable/thing = i - if(ismob(thing)) - if(isliving(thing)) - var/mob/living/M = thing - if(M.buckled) - M.buckled.unbuckle_mob(M, 1) - if(M.pulledby) - M.pulledby.stop_pulling() - M.stop_pulling() - M.visible_message(span_warning("[shuttle] slams into [M]!")) - SSblackbox.record_feedback("tally", "shuttle_gib", 1, M.type) - log_shuttle("[key_name(M)] was shuttle gibbed by [shuttle].") - M.investigate_log("has been gibbed by [shuttle].", INVESTIGATE_DEATHS) - M.gib(DROP_ALL_REMAINS) - - - else //non-living mobs shouldn't be affected by shuttles, which is why this is an else - if(istype(thing, /obj/effect/abstract) || istype(thing, /obj/singularity) || istype(thing, /obj/energy_ball)) + for(var/atom/movable/thing as anything in contents) + if(thing.resistance_flags & SHUTTLE_CRUSH_PROOF) + continue + if(isliving(thing)) + var/mob/living/living_thing = thing + if(living_thing.incorporeal_move) // Don't crush incorporeal things continue + living_thing.buckled?.unbuckle_mob(living_thing, force = TRUE) + living_thing.pulledby?.stop_pulling() + living_thing.stop_pulling() + living_thing.visible_message(span_warning("[shuttle] slams into [living_thing]!")) + SSblackbox.record_feedback("tally", "shuttle_gib", 1, living_thing.type) + log_shuttle("[key_name(living_thing)] was shuttle gibbed by [shuttle].") + living_thing.investigate_log("has been gibbed by [shuttle].", INVESTIGATE_DEATHS) + living_thing.gib(DROP_ALL_REMAINS) + else if(!ismob(thing)) //non-living mobs shouldn't be affected by shuttles, which is why this is an else if(!thing.anchored) step(thing, shuttle_dir) else diff --git a/code/modules/spells/spell_types/conjure/simian.dm b/code/modules/spells/spell_types/conjure/simian.dm index aa9aabc681009d6..9fef5629d037933 100644 --- a/code/modules/spells/spell_types/conjure/simian.dm +++ b/code/modules/spells/spell_types/conjure/simian.dm @@ -13,6 +13,9 @@ invocation = "OOGA OOGA OOGA!!!!" invocation_type = INVOCATION_SHOUT + ///Our gorilla transformation spell, additionally granted to the user at max level. + var/datum/action/cooldown/spell/shapeshift/gorilla/gorilla_transformation + summon_radius = 2 summon_type = list( /mob/living/basic/gorilla/lesser, @@ -21,13 +24,18 @@ ) summon_amount = 4 +/datum/action/cooldown/spell/conjure/simian/Destroy() + . = ..() + QDEL_NULL(gorilla_transformation) + /datum/action/cooldown/spell/conjure/simian/level_spell(bypass_cap) . = ..() summon_amount++ // MORE, MOOOOORE if(spell_level == spell_max_level) // We reward the faithful. - summon_type = list(/mob/living/carbon/human/species/monkey/angry, /mob/living/basic/gorilla) + gorilla_transformation = new(owner) + gorilla_transformation.Grant(owner) spell_requirements = SPELL_REQUIRES_NO_ANTIMAGIC // Max level lets you cast it naked, for monkey larp. - to_chat(owner, span_notice("Your simian power has reached maximum capacity! You can now cast this spell naked, and you will create adult Gorillas with each cast.")) + to_chat(owner, span_notice("Your simian power has reached maximum capacity! You can now cast this spell naked, and have additionally been granted a gorilla transformation spell!")) /datum/action/cooldown/spell/conjure/simian/cast(atom/cast_on) . = ..() diff --git a/code/modules/spells/spell_types/shapeshift/_shape_status.dm b/code/modules/spells/spell_types/shapeshift/_shape_status.dm index faa84835255a88b..cffd9804ea588e3 100644 --- a/code/modules/spells/spell_types/shapeshift/_shape_status.dm +++ b/code/modules/spells/spell_types/shapeshift/_shape_status.dm @@ -189,6 +189,12 @@ // is no longer in control of the shapeshifted mob, such as mindswapping out of a shapeshift if(!QDELETED(source_spell) && source_spell.owner == owner) source_spell.Grant(caster_mob) + if(owner?.contents) + // Prevent round removal and consuming stuff when losing shapeshift + for(var/atom/movable/thing as anything in owner.contents) + if(thing == caster_mob) + continue + thing.forceMove(get_turf(owner)) for(var/datum/action/bodybound_action as anything in owner.actions) if(bodybound_action.target != caster_mob) diff --git a/code/modules/spells/spell_types/shapeshift/gorilla.dm b/code/modules/spells/spell_types/shapeshift/gorilla.dm new file mode 100644 index 000000000000000..fe93c0f2bc4140f --- /dev/null +++ b/code/modules/spells/spell_types/shapeshift/gorilla.dm @@ -0,0 +1,9 @@ + +/datum/action/cooldown/spell/shapeshift/gorilla + name = "Gorilla Form" + desc = "Take on the shape of a powerful gorilla." + button_icon_state = "return_to_monkey" + invocation = "B'NA NAH-SLEMA!" + invocation_type = INVOCATION_SHOUT + spell_requirements = NONE + possible_shapes = list(/mob/living/basic/gorilla) diff --git a/code/modules/surgery/bodyparts/parts.dm b/code/modules/surgery/bodyparts/parts.dm index ead03aa0f707c98..22450ca793d7b27 100644 --- a/code/modules/surgery/bodyparts/parts.dm +++ b/code/modules/surgery/bodyparts/parts.dm @@ -69,6 +69,15 @@ cavity_item = null return ..() +/// Sprite to show for photocopying mob butts +/obj/item/bodypart/chest/proc/get_butt_sprite() + if(!ishuman(owner)) + return null + var/mob/living/carbon/human/human_owner = owner + var/butt_sprite = human_owner.physique == FEMALE ? BUTT_SPRITE_HUMAN_FEMALE : BUTT_SPRITE_HUMAN_MALE + var/obj/item/organ/external/tail/tail = human_owner.get_organ_slot(ORGAN_SLOT_EXTERNAL_TAIL) + return tail?.get_butt_sprite() || butt_sprite + /obj/item/bodypart/chest/monkey icon = 'icons/mob/human/species/monkey/bodyparts.dmi' icon_static = 'icons/mob/human/species/monkey/bodyparts.dmi' diff --git a/code/modules/surgery/bodyparts/species_parts/lizard_bodyparts.dm b/code/modules/surgery/bodyparts/species_parts/lizard_bodyparts.dm index 5f44dc7ef38ccb6..f2064c5c26a7038 100644 --- a/code/modules/surgery/bodyparts/species_parts/lizard_bodyparts.dm +++ b/code/modules/surgery/bodyparts/species_parts/lizard_bodyparts.dm @@ -10,6 +10,9 @@ is_dimorphic = TRUE wing_types = list(/obj/item/organ/external/wings/functional/dragon) +/obj/item/bodypart/chest/lizard/get_butt_sprite() + return BUTT_SPRITE_LIZARD + /obj/item/bodypart/arm/left/lizard icon_greyscale = 'icons/mob/human/species/lizard/bodyparts.dmi' limb_id = SPECIES_LIZARD diff --git a/code/modules/surgery/bodyparts/species_parts/misc_bodyparts.dm b/code/modules/surgery/bodyparts/species_parts/misc_bodyparts.dm index 7e415f61cda17ee..9ff20109ae71fdc 100644 --- a/code/modules/surgery/bodyparts/species_parts/misc_bodyparts.dm +++ b/code/modules/surgery/bodyparts/species_parts/misc_bodyparts.dm @@ -60,6 +60,9 @@ should_draw_greyscale = FALSE wing_types = NONE +/obj/item/bodypart/chest/abductor/get_butt_sprite() + return BUTT_SPRITE_GREY + /obj/item/bodypart/arm/left/abductor limb_id = SPECIES_ABDUCTOR should_draw_greyscale = FALSE @@ -95,6 +98,9 @@ burn_modifier = 0.5 // = 1/2x generic burn damage wing_types = list(/obj/item/organ/external/wings/functional/slime) +/obj/item/bodypart/chest/jelly/get_butt_sprite() + return BUTT_SPRITE_SLIME + /obj/item/bodypart/arm/left/jelly biological_state = (BIO_FLESH|BIO_BLOODED) limb_id = SPECIES_JELLYPERSON @@ -230,6 +236,9 @@ burn_modifier = 1.25 wing_types = NONE +/obj/item/bodypart/chest/pod/get_butt_sprite() + return BUTT_SPRITE_FLOWERPOT + /obj/item/bodypart/arm/left/pod limb_id = SPECIES_PODPERSON unarmed_attack_verb = "slash" diff --git a/code/modules/surgery/bodyparts/species_parts/moth_bodyparts.dm b/code/modules/surgery/bodyparts/species_parts/moth_bodyparts.dm index 1431fc197b9cdc4..25f9e719fda3475 100644 --- a/code/modules/surgery/bodyparts/species_parts/moth_bodyparts.dm +++ b/code/modules/surgery/bodyparts/species_parts/moth_bodyparts.dm @@ -17,6 +17,9 @@ should_draw_greyscale = FALSE wing_types = list(/obj/item/organ/external/wings/functional/moth/megamoth, /obj/item/organ/external/wings/functional/moth/mothra) +/obj/item/bodypart/chest/moth/get_butt_sprite() + return BUTT_SPRITE_FUZZY + /obj/item/bodypart/arm/left/moth icon = 'icons/mob/human/species/moth/bodyparts.dmi' icon_state = "moth_l_arm" diff --git a/code/modules/surgery/bodyparts/species_parts/plasmaman_bodyparts.dm b/code/modules/surgery/bodyparts/species_parts/plasmaman_bodyparts.dm index 8ba27c2cdf9d0bb..40bf4a51c042ecb 100644 --- a/code/modules/surgery/bodyparts/species_parts/plasmaman_bodyparts.dm +++ b/code/modules/surgery/bodyparts/species_parts/plasmaman_bodyparts.dm @@ -26,6 +26,9 @@ bodypart_flags = BODYPART_UNHUSKABLE wing_types = NONE +/obj/item/bodypart/chest/plasmaman/get_butt_sprite() + return BUTT_SPRITE_PLASMA + /obj/item/bodypart/arm/left/plasmaman icon = 'icons/mob/human/species/plasmaman/bodyparts.dmi' icon_state = "plasmaman_l_arm" diff --git a/code/modules/surgery/organs/external/tails.dm b/code/modules/surgery/organs/external/tails.dm index d8205b3ad16d88d..e1de62308f0744e 100644 --- a/code/modules/surgery/organs/external/tails.dm +++ b/code/modules/surgery/organs/external/tails.dm @@ -126,6 +126,9 @@ UnregisterSignal(organ_owner, COMSIG_LIVING_DEATH) return succeeded +/obj/item/organ/external/tail/proc/get_butt_sprite() + return null + ///Tail parent type, with wagging functionality /datum/bodypart_overlay/mutant/tail layers = EXTERNAL_FRONT|EXTERNAL_BEHIND @@ -153,6 +156,9 @@ wag_flags = WAG_ABLE +/obj/item/organ/external/tail/cat/get_butt_sprite() + return BUTT_SPRITE_CAT + ///Cat tail bodypart overlay /datum/bodypart_overlay/mutant/tail/cat feature_key = "tail" // SKYRAT EDIT - Customization - ORIGINAL: feature_key = "tail_cat" diff --git a/code/modules/surgery/organs/internal/lungs/_lungs.dm b/code/modules/surgery/organs/internal/lungs/_lungs.dm index 78afbd9871e1a62..1db1963e8d6656c 100644 --- a/code/modules/surgery/organs/internal/lungs/_lungs.dm +++ b/code/modules/surgery/organs/internal/lungs/_lungs.dm @@ -444,7 +444,7 @@ /// React to speach while hopped up on the high pitched voice juice /obj/item/organ/internal/lungs/proc/handle_helium_speech(mob/living/carbon/breather, list/speech_args) SIGNAL_HANDLER - speech_args[SPEECH_SPANS] |= SPAN_HELIUM + speech_args[SPEECH_SPANS] |= SPAN_SMALL_VOICE /// Gain hypernob effects if we have enough of the stuff /obj/item/organ/internal/lungs/proc/consume_hypernoblium(mob/living/carbon/breather, datum/gas_mixture/breath, hypernob_pp, old_hypernob_pp) diff --git a/code/modules/surgery/organs/internal/stomach/stomach_ethereal.dm b/code/modules/surgery/organs/internal/stomach/stomach_ethereal.dm index 68f9d9428a04a77..9f268b41c178a85 100644 --- a/code/modules/surgery/organs/internal/stomach/stomach_ethereal.dm +++ b/code/modules/surgery/organs/internal/stomach/stomach_ethereal.dm @@ -33,7 +33,7 @@ SIGNAL_HANDLER adjust_charge(amount / 3.5) -/obj/item/organ/internal/stomach/ethereal/proc/on_electrocute(datum/source, shock_damage, siemens_coeff = 1, flags = NONE) +/obj/item/organ/internal/stomach/ethereal/proc/on_electrocute(datum/source, shock_damage, shock_source, siemens_coeff = 1, flags = NONE) SIGNAL_HANDLER if(flags & SHOCK_ILLUSION) return diff --git a/code/modules/surgery/surgery_step.dm b/code/modules/surgery/surgery_step.dm index a206b75cd386e4d..c2c23e9adad6a57 100644 --- a/code/modules/surgery/surgery_step.dm +++ b/code/modules/surgery/surgery_step.dm @@ -98,8 +98,10 @@ if(check_morbid_curiosity(user, tool, surgery)) speed_mod *= SURGERY_SPEED_MORBID_CURIOSITY + /* SKYRAT EDIT START - Worked in with reward buffs below if(HAS_TRAIT(target, TRAIT_ANALGESIA)) speed_mod *= SURGERY_SPEED_TRAIT_ANALGESIA + */ // SKYRAT EDIT END var/implement_speed_mod = 1 if(implement_type) //this means it isn't a require hand or any item step. @@ -115,7 +117,7 @@ var/was_sleeping = (target.stat != DEAD && target.IsSleeping()) // Skyrat Edit Addition - reward for doing surgery on calm patients, and for using surgery rooms(ie. surgerying alone) - if(was_sleeping || HAS_TRAIT(target, TRAIT_NUMBED) || target.stat == DEAD) + if(was_sleeping || HAS_TRAIT(target, TRAIT_ANALGESIA) || target.stat == DEAD) modded_time *= SURGERY_SPEEDUP_AREA to_chat(user, span_notice("You are able to work faster due to the patient's calm attitude!")) var/quiet_enviromnent = TRUE @@ -285,10 +287,15 @@ if(target.stat < UNCONSCIOUS) if(HAS_TRAIT(target, TRAIT_ANALGESIA)) to_chat(target, span_notice("You feel a dull, numb sensation as your body is surgically operated on.")) - else + // SKYRAT EDIT BEGIN - Mood events from surgeries added + target.add_mood_event("mild_surgery", /datum/mood_event/mild_surgery) + else if(!mechanical_surgery) to_chat(target, span_userdanger(pain_message)) - if(prob(30) && !mechanical_surgery) + target.add_mood_event("severe_surgery", /datum/mood_event/severe_surgery) + if(prob(30)) target.emote("scream") + // SKYRAT EDIT END + #undef SURGERY_SPEED_TRAIT_ANALGESIA #undef SURGERY_SPEED_DISSECTION_MODIFIER diff --git a/code/modules/surgery/tools.dm b/code/modules/surgery/tools.dm index fee7f389dcaef0c..042ea28be2d01d4 100644 --- a/code/modules/surgery/tools.dm +++ b/code/modules/surgery/tools.dm @@ -94,7 +94,8 @@ w_class = WEIGHT_CLASS_NORMAL toolspeed = 0.7 light_system = OVERLAY_LIGHT - light_range = 1 + light_range = 1.5 + light_power = 1.2 light_color = COLOR_SOFT_RED /obj/item/cautery/advanced/get_all_tool_behaviours() @@ -379,7 +380,8 @@ w_class = WEIGHT_CLASS_NORMAL toolspeed = 0.7 light_system = OVERLAY_LIGHT - light_range = 1 + light_range = 1.5 + light_power = 1.2 light_color = LIGHT_COLOR_BLUE sharpness = SHARP_EDGED @@ -413,7 +415,7 @@ set_light_range(2) else tool_behaviour = TOOL_SCALPEL - set_light_range(1) + set_light_range(1.5) balloon_alert(user, "[active ? "enabled" : "disabled"] bone-cutting mode") playsound(user ? user : src, 'sound/machines/click.ogg', 50, TRUE) diff --git a/code/modules/tgui_input/text.dm b/code/modules/tgui_input/text.dm index f97e0326d58ef69..4b3e59a6028c774 100644 --- a/code/modules/tgui_input/text.dm +++ b/code/modules/tgui_input/text.dm @@ -32,9 +32,9 @@ if(!user.client.prefs.read_preference(/datum/preference/toggle/tgui_input)) if(encode) if(multiline) - return stripped_multiline_input(user, message, title, default, max_length) + return stripped_multiline_input(user, message, title, default, PREVENT_CHARACTER_TRIM_LOSS(max_length)) else - return stripped_input(user, message, title, default, max_length) + return stripped_input(user, message, title, default, PREVENT_CHARACTER_TRIM_LOSS(max_length)) else if(multiline) return input(user, message, title, default) as message|null @@ -162,4 +162,4 @@ /datum/tgui_input_text/proc/set_entry(entry) if(!isnull(entry)) var/converted_entry = encode ? html_encode(entry) : entry - src.entry = trim(converted_entry, max_length) + src.entry = trim(converted_entry, PREVENT_CHARACTER_TRIM_LOSS(max_length)) diff --git a/code/modules/transport/tram/tram_floors.dm b/code/modules/transport/tram/tram_floors.dm index 1e1fad836c3b20f..9f0b6907fe9c192 100644 --- a/code/modules/transport/tram/tram_floors.dm +++ b/code/modules/transport/tram/tram_floors.dm @@ -255,7 +255,7 @@ span_notice("You wedge \the [tool] into the tram panel's gap in the frame and start prying...")) if(tool.use_tool(src, user, 1 SECONDS, volume = 50)) to_chat(user, span_notice("The panel pops out of the frame.")) - var/obj/item/stack/thermoplastic/pulled_tile = new() + var/obj/item/stack/thermoplastic/pulled_tile = new floor_tile() pulled_tile.update_integrity(atom_integrity) user.put_in_hands(pulled_tile) qdel(src) @@ -283,8 +283,8 @@ icon = 'icons/obj/tiles.dmi' lefthand_file = 'icons/mob/inhands/items/tiles_lefthand.dmi' righthand_file = 'icons/mob/inhands/items/tiles_righthand.dmi' - icon_state = "tile_textured_white_large" - inhand_icon_state = "tile-neon-glow" + icon_state = "tile_tram_dark" + inhand_icon_state = "tile-tram" color = COLOR_TRAM_BLUE w_class = WEIGHT_CLASS_NORMAL force = 1 @@ -297,7 +297,9 @@ var/tile_type = /obj/structure/thermoplastic /obj/item/stack/thermoplastic/light + icon_state = "tile_tram_light" color = COLOR_TRAM_LIGHT_BLUE + merge_type = /obj/item/stack/thermoplastic/light tile_type = /obj/structure/thermoplastic/light /obj/item/stack/thermoplastic/Initialize(mapload, new_amount, merge = TRUE, list/mat_override=null, mat_amt=1) diff --git a/code/modules/transport/transport_module.dm b/code/modules/transport/transport_module.dm index 9fdfefc835cae66..7fcfa53fba1597c 100644 --- a/code/modules/transport/transport_module.dm +++ b/code/modules/transport/transport_module.dm @@ -844,7 +844,6 @@ transport_id = TRANSPORT_TYPE_TRAM transport_controller_type = /datum/transport_controller/linear/tram radial_travel = FALSE - obj_flags = NONE /// Set by the tram control console in late initialize var/travelling = FALSE diff --git a/code/modules/unit_tests/antag_conversion.dm b/code/modules/unit_tests/antag_conversion.dm index 01c05671ef72e47..f499922bf8dbeee 100644 --- a/code/modules/unit_tests/antag_conversion.dm +++ b/code/modules/unit_tests/antag_conversion.dm @@ -36,7 +36,7 @@ // Success state leader.ClickOn(peasant) - TEST_ASSERT(peasant.IsParalyzed(), "Peasant was not paralyzed after being flashed by the leader.") // Flash paralyze + TEST_ASSERT((peasant.get_timed_status_effect_duration(/datum/status_effect/confusion) > 0), "Peasant was not confused after being flashed by the leader.") // Flash confuse TEST_ASSERT(peasant.IsStun(), "Peasant was not stunned after being converted by the leader.") // Conversion stun TEST_ASSERT(IS_REVOLUTIONARY(peasant), "Peasant did not gain revolution antag datum on conversion.") TEST_ASSERT_EQUAL(length(revolution.members), 2, "Expected revolution to have 2 members after the leader flashes the peasant.") diff --git a/code/modules/unit_tests/screenshots/screenshot_high_luminosity_eyes_light_on.png b/code/modules/unit_tests/screenshots/screenshot_high_luminosity_eyes_light_on.png index 76c997c33180d07..eabee8b0aff4f1d 100644 Binary files a/code/modules/unit_tests/screenshots/screenshot_high_luminosity_eyes_light_on.png and b/code/modules/unit_tests/screenshots/screenshot_high_luminosity_eyes_light_on.png differ diff --git a/code/modules/unit_tests/simple_animal_freeze.dm b/code/modules/unit_tests/simple_animal_freeze.dm index 3e4610df415cb31..849d6fc205e5036 100644 --- a/code/modules/unit_tests/simple_animal_freeze.dm +++ b/code/modules/unit_tests/simple_animal_freeze.dm @@ -43,7 +43,6 @@ /mob/living/simple_animal/hostile/asteroid/elite/pandora, /mob/living/simple_animal/hostile/asteroid/polarbear, /mob/living/simple_animal/hostile/asteroid/polarbear/lesser, - /mob/living/simple_animal/hostile/asteroid/wolf, /mob/living/simple_animal/hostile/dark_wizard, /mob/living/simple_animal/hostile/illusion, /mob/living/simple_animal/hostile/illusion/escape, diff --git a/code/modules/unit_tests/siunit.dm b/code/modules/unit_tests/siunit.dm index 3a7a25a98d3ee92..7b98db497c8f63c 100644 --- a/code/modules/unit_tests/siunit.dm +++ b/code/modules/unit_tests/siunit.dm @@ -12,4 +12,4 @@ TEST_ASSERT_EQUAL(siunit_pressure(999.9e3), "999.9 MPa" , "") TEST_ASSERT_EQUAL(siunit_pressure(999.9e3, 0), "1 GPa", "") TEST_ASSERT_EQUAL(siunit_pressure(1e6), "1 GPa", "") - TEST_ASSERT_EQUAL(siunit_pressure(3e17), "300000 PPa", "") + TEST_ASSERT_EQUAL(siunit_pressure(3e32), "300000 QPa", "") diff --git a/code/modules/unit_tests/unit_test.dm b/code/modules/unit_tests/unit_test.dm index 2ad1f18221534db..2a805e0d13df5a9 100644 --- a/code/modules/unit_tests/unit_test.dm +++ b/code/modules/unit_tests/unit_test.dm @@ -292,6 +292,10 @@ GLOBAL_VAR_INIT(focused_tests, focused_tests()) returnable_list += typesof(/obj/item/hilbertshotel) //this boi spawns turf changing stuff, and it stacks and causes pain. Let's just not returnable_list += typesof(/obj/effect/sliding_puzzle) + //these can explode and cause the turf to be destroyed at unexpected moments + returnable_list += typesof(/obj/effect/mine) + returnable_list += typesof(/obj/effect/spawner/random/contraband/landmine) + returnable_list += typesof(/obj/item/minespawner) //Stacks baseturfs, can't be tested here returnable_list += typesof(/obj/effect/temp_visual/lava_warning) //Stacks baseturfs, can't be tested here diff --git a/code/modules/uplink/uplink_items/nukeops.dm b/code/modules/uplink/uplink_items/nukeops.dm index 341a33baa6a6ae4..32d99512e45c00b 100644 --- a/code/modules/uplink/uplink_items/nukeops.dm +++ b/code/modules/uplink/uplink_items/nukeops.dm @@ -68,7 +68,7 @@ /datum/uplink_item/weapon_kits/low_cost/shotgun name = "Bulldog Shotgun Case (Moderate)" - desc = "A fully-loaded semi-automatic drum-fed shotgun, complete with a secondary magazine you can hotswap. The gun has a handy label to explain how. \ + desc = "A fully-loaded 2-round burst fire drum-fed shotgun, complete with a secondary magazine you can hotswap. The gun has a handy label to explain how. \ Compatible with all 12g rounds. Designed for close quarter anti-personnel engagements. Comes with three spare magazines." item = /obj/item/storage/toolbox/guncase/bulldog diff --git a/code/modules/vehicles/cars/clowncar.dm b/code/modules/vehicles/cars/clowncar.dm index 37f6eb7efa501ee..30e01b3219edc72 100644 --- a/code/modules/vehicles/cars/clowncar.dm +++ b/code/modules/vehicles/cars/clowncar.dm @@ -10,7 +10,7 @@ car_traits = CAN_KIDNAP key_type = /obj/item/bikehorn light_system = OVERLAY_LIGHT_DIRECTIONAL - light_range = 8 + light_range = 6 light_power = 2 light_on = FALSE access_provider_flags = VEHICLE_CONTROL_DRIVE|VEHICLE_CONTROL_KIDNAPPED diff --git a/code/modules/vehicles/cars/vim.dm b/code/modules/vehicles/cars/vim.dm index 53eee5105a97e02..221c9268febbb8a 100644 --- a/code/modules/vehicles/cars/vim.dm +++ b/code/modules/vehicles/cars/vim.dm @@ -15,7 +15,7 @@ engine_sound_length = 0.3 SECONDS light_system = OVERLAY_LIGHT_DIRECTIONAL light_range = 4 - light_power = 2 + light_power = 1.5 light_on = FALSE engine_sound = 'sound/effects/servostep.ogg' ///Maximum size of a mob trying to enter the mech diff --git a/code/modules/vehicles/mecha/_mecha.dm b/code/modules/vehicles/mecha/_mecha.dm index e03847037c8dbf4..f718bd5c6951f89 100644 --- a/code/modules/vehicles/mecha/_mecha.dm +++ b/code/modules/vehicles/mecha/_mecha.dm @@ -31,7 +31,7 @@ COOLDOWN_DECLARE(mecha_bump_smash) light_system = OVERLAY_LIGHT_DIRECTIONAL light_on = FALSE - light_range = 8 + light_range = 6 generic_canpass = FALSE hud_possible = list(DIAG_STAT_HUD, DIAG_BATT_HUD, DIAG_MECH_HUD, DIAG_TRACK_HUD, DIAG_CAMERA_HUD) mouse_pointer = 'icons/effects/mouse_pointers/mecha_mouse.dmi' @@ -221,6 +221,7 @@ ui_view.generate_view("mech_view_[REF(src)]") RegisterSignal(src, COMSIG_MOVABLE_MOVED, PROC_REF(on_move)) RegisterSignal(src, COMSIG_LIGHT_EATER_ACT, PROC_REF(on_light_eater)) + RegisterSignal(src, COMSIG_HIT_BY_SABOTEUR, PROC_REF(on_saboteur)) spark_system = new spark_system.set_up(2, 0, src) @@ -799,6 +800,12 @@ remove_action_type_from_mob(/datum/action/vehicle/sealed/mecha/mech_toggle_lights, occupant) return COMPONENT_BLOCK_LIGHT_EATER +/obj/vehicle/sealed/mecha/proc/on_saboteur(datum/source, disrupt_duration) + SIGNAL_HANDLER + if(mecha_flags &= HAS_LIGHTS && light_on) + set_light_on(FALSE) + return COMSIG_SABOTEUR_SUCCESS + /// Apply corresponding accesses /obj/vehicle/sealed/mecha/proc/update_access() req_access = one_access ? list() : accesses diff --git a/code/modules/vehicles/mecha/combat/durand.dm b/code/modules/vehicles/mecha/combat/durand.dm index 35b53c30ccfc875..f7da6ea90c8a2fc 100644 --- a/code/modules/vehicles/mecha/combat/durand.dm +++ b/code/modules/vehicles/mecha/combat/durand.dm @@ -166,7 +166,7 @@ own integrity back to max. Shield is automatically dropped if we run out of powe anchored = TRUE light_system = OVERLAY_LIGHT light_range = MINIMUM_USEFUL_LIGHT_RANGE - light_power = 5 + light_power = 2 light_color = LIGHT_COLOR_ELECTRIC_CYAN light_on = FALSE resistance_flags = LAVA_PROOF | FIRE_PROOF | ACID_PROOF //The shield should not take damage from fire, lava, or acid; that's the mech's job. diff --git a/code/modules/vehicles/motorized_wheelchair.dm b/code/modules/vehicles/motorized_wheelchair.dm index 7d3b70baf95eec1..f85d6667e9102af 100644 --- a/code/modules/vehicles/motorized_wheelchair.dm +++ b/code/modules/vehicles/motorized_wheelchair.dm @@ -26,12 +26,15 @@ /obj/vehicle/ridden/wheelchair/motorized/Initialize(mapload) . = ..() + add_component_parts() + refresh_parts() + +/obj/vehicle/ridden/wheelchair/motorized/proc/add_component_parts() // Add tier 1 stock parts so that non-crafted wheelchairs aren't empty component_parts += GLOB.stock_part_datums[/datum/stock_part/capacitor] component_parts += GLOB.stock_part_datums[/datum/stock_part/servo] component_parts += GLOB.stock_part_datums[/datum/stock_part/servo] power_cell = new /obj/item/stock_parts/cell(src) - refresh_parts() /obj/vehicle/ridden/wheelchair/motorized/make_ridable() AddElement(/datum/element/ridable, /datum/component/riding/vehicle/wheelchair/motorized) @@ -221,3 +224,12 @@ visible_message(span_warning("A bomb appears in [src], what the fuck?")) obj_flags |= EMAGGED return TRUE + +///Version with slightly better components. Used by deathmatches. +/obj/vehicle/ridden/wheelchair/motorized/improved + +/obj/vehicle/ridden/wheelchair/motorized/improved/add_component_parts() + component_parts += GLOB.stock_part_datums[/datum/stock_part/capacitor/tier2] + component_parts += GLOB.stock_part_datums[/datum/stock_part/servo/tier2] + component_parts += GLOB.stock_part_datums[/datum/stock_part/servo/tier2] + power_cell = new /obj/item/stock_parts/cell/upgraded/plus(src) diff --git a/code/modules/vehicles/scooter.dm b/code/modules/vehicles/scooter.dm index 4e1f115e55ce2c6..9e320c2f8deb6f5 100644 --- a/code/modules/vehicles/scooter.dm +++ b/code/modules/vehicles/scooter.dm @@ -49,6 +49,8 @@ var/board_item_type = /obj/item/melee/skateboard ///Stamina drain multiplier var/instability = 10 + ///If true, riding the skateboard with walk intent on will prevent crashing. + var/can_slow_down = TRUE /obj/vehicle/ridden/scooter/skateboard/Initialize(mapload) . = ..() @@ -87,9 +89,11 @@ . = ..() if(!bumped_thing.density || !has_buckled_mobs() || world.time < next_crash) return + var/mob/living/rider = buckled_mobs[1] + if(rider.move_intent == MOVE_INTENT_WALK && can_slow_down) //Going slow prevents you from crashing. + return next_crash = world.time + 10 - var/mob/living/rider = buckled_mobs[1] rider.adjustStaminaLoss(instability*6) playsound(src, 'sound/effects/bang.ogg', 40, TRUE) if(!iscarbon(rider) || rider.getStaminaLoss() >= 100 || grinding || iscarbon(bumped_thing)) @@ -181,13 +185,28 @@ board_item_type = /obj/item/melee/skateboard/pro instability = 6 -/obj/vehicle/ridden/scooter/skateboard/hoverboard/ +/obj/vehicle/ridden/scooter/skateboard/pro/make_ridable() + AddElement(/datum/element/ridable, /datum/component/riding/vehicle/scooter/skateboard/pro) + +/obj/vehicle/ridden/scooter/skateboard/hoverboard name = "hoverboard" desc = "A blast from the past, so retro!" board_item_type = /obj/item/melee/skateboard/hoverboard instability = 3 icon_state = "hoverboard_red" +/obj/vehicle/ridden/scooter/skateboard/hoverboard/make_ridable() + AddElement(/datum/element/ridable, /datum/component/riding/vehicle/scooter/skateboard/hover) + +/obj/vehicle/ridden/scooter/skateboard/hoverboard/can_z_move(direction, turf/start, turf/destination, z_move_flags = ZMOVE_FLIGHT_FLAGS, mob/living/rider) + . = ..() + if(!.) + return + if(rider && (z_move_flags & ZMOVE_CAN_FLY_CHECKS) && direction == UP) + if(z_move_flags & ZMOVE_FEEDBACK) + to_chat(rider, span_warning("[src] [p_are()] not powerful enough to fly upwards.")) + return FALSE + /obj/vehicle/ridden/scooter/skateboard/hoverboard/admin name = "\improper Board Of Directors" desc = "The engineering complexity of a spaceship concentrated inside of a board. Just as expensive, too." @@ -199,6 +218,7 @@ name = "improvised skateboard" desc = "An unfinished scooter which can only barely be called a skateboard. It's still rideable, but probably unsafe. Looks like you'll need to add a few rods to make handlebars." board_item_type = /obj/item/melee/skateboard/improvised + instability = 12 //CONSTRUCTION /obj/item/scooter_frame diff --git a/code/modules/vending/_vending.dm b/code/modules/vending/_vending.dm index a344140d181557b..0cc1cfacbb7dbea 100644 --- a/code/modules/vending/_vending.dm +++ b/code/modules/vending/_vending.dm @@ -14,8 +14,12 @@ premium = list() */ +/// List of vending machines that players can restock, so only vending machines that are on station or don't have a unique condition. +GLOBAL_LIST_EMPTY(vending_machines_to_restock) + /// Maximum amount of items in a storage bag that we're transferring items to the vendor from. #define MAX_VENDING_INPUT_AMOUNT 30 +#define CREDITS_DUMP_THRESHOLD 50 /** * # vending record datum * @@ -178,6 +182,8 @@ var/displayed_currency_name = " cr" ///Whether our age check is currently functional var/age_restrictions = TRUE + /// How many credits does this vending machine have? 20% of all sales go to this pool, and are given freely when the machine is restocked, or successfully tilted. Lost on deconstruction. + var/credits_contained = 0 /** * Is this item on station or not * @@ -256,6 +262,7 @@ onstation = FALSE if(circuit) circuit.onstation = onstation //sync up the circuit so the pricing schema is carried over if it's reconstructed. + else if(HAS_TRAIT(SSstation, STATION_TRAIT_VENDING_SHORTAGE)) for (var/datum/data/vending_product/product_record as anything in product_records + coin_records + hidden_records) /** @@ -264,16 +271,22 @@ */ var/max_amount = rand(CEILING(product_record.amount * 0.5, 1), product_record.amount) product_record.amount = rand(0, max_amount) + credits_contained += rand(0, 1) //randomly add a few credits to the machine to make it look like it's been used, proportional to the amount missing. if(tiltable && prob(6)) // 1 in 17 chance to start tilted (as an additional hint to the station trait behind it) INVOKE_ASYNC(src, PROC_REF(tilt), loc) + credits_contained = 0 // If it's tilted, it's been looted, so no credits for you. else if(circuit && (circuit.onstation != onstation)) //check if they're not the same to minimize the amount of edited values. onstation = circuit.onstation //if it was constructed outside mapload, sync the vendor up with the circuit's var so you can't bypass price requirements by moving / reconstructing it off station. + if(onstation && !onstation_override) + AddComponent(/datum/component/payment, 0, SSeconomy.get_dep_account(payment_department), PAYMENT_VENDING) + GLOB.vending_machines_to_restock += src //We need to keep track of the final onstation vending machines so we can keep them restocked. /obj/machinery/vending/Destroy() QDEL_NULL(wires) QDEL_NULL(coin) QDEL_NULL(bill) QDEL_NULL(sec_radio) + GLOB.vending_machines_to_restock -= src return ..() /obj/machinery/vending/can_speak() @@ -357,6 +370,7 @@ continue var/obj/obj_to_dump = new dump_path(loc) + on_dispense(obj_to_dump) step(obj_to_dump, pick(GLOB.alldirs)) found_anything = TRUE dump_amount++ @@ -611,6 +625,24 @@ else //no category found - dump it into standard stock products[record.product_path] = record.amount +/** + * Returns the total amount of items in the vending machine based on the product records and premium records, but not contraband + */ +/obj/machinery/vending/proc/total_loaded_stock() + var/total = 0 + for(var/datum/data/vending_product/record as anything in product_records + coin_records) + total += record.amount + return total + +/** + * Returns the total amount of items in the vending machine based on the product records and premium records, but not contraband + */ +/obj/machinery/vending/proc/total_max_stock() + var/total_max = 0 + for(var/datum/data/vending_product/record as anything in product_records + coin_records) + total_max += record.max_amount + return total_max + /obj/machinery/vending/crowbar_act(mob/living/user, obj/item/attack_item) if(!component_parts) return FALSE @@ -655,7 +687,11 @@ // instantiate canister if needed var/transferred = restock(canister) if(transferred) - to_chat(user, span_notice("You loaded [transferred] items in [src].")) + to_chat(user, span_notice("You loaded [transferred] items in [src][credits_contained > 0 ? ", and are rewarded [credits_contained] credits." : "."]")) + var/datum/bank_account/cargo_account = SSeconomy.get_dep_account(ACCOUNT_CAR) + cargo_account.adjust_money(round(credits_contained * 0.5), "Vending: Restock") + var/obj/item/holochip/payday = new(src, credits_contained) + try_put_in_hand(payday, user) else to_chat(user, span_warning("There's nothing to restock!")) return @@ -707,7 +743,7 @@ * freebies - number of free items to vend */ /obj/machinery/vending/proc/freebie(freebies) - visible_message(span_notice("[src] yields [freebies > 1 ? "several free goodies" : "a free goody"]!")) + visible_message(span_notice("[src] yields [freebies > 1 ? "several free goodies" : "a free goody"][credits_contained > 0 ? " and some credits" : ""]!")) for(var/i in 1 to freebies) playsound(src, 'sound/machines/machine_vend.ogg', 50, TRUE, extrarange = -3) @@ -719,13 +755,15 @@ if(!dump_path) continue if(record.amount > LAZYLEN(record.returned_products)) //always give out new stuff that costs before free returned stuff, because of the risk getting gibbed involved - new dump_path(get_turf(src)) + var/obj/item/free_stuff = new dump_path(get_turf(src)) + on_dispense(free_stuff) else var/obj/returned_obj_to_dump = LAZYACCESS(record.returned_products, LAZYLEN(record.returned_products)) //first in, last out LAZYREMOVE(record.returned_products, returned_obj_to_dump) returned_obj_to_dump.forceMove(get_turf(src)) record.amount-- break + deploy_credits() /** * Tilts ontop of the atom supplied, if crit is true some extra shit can happen. See [fall_and_crush] for return values. @@ -1206,13 +1244,15 @@ /obj/machinery/vending/ui_data(mob/user) . = list() var/obj/item/card/id/card_used + var/held_cash = 0 if(isliving(user)) var/mob/living/living_user = user card_used = living_user.get_idcard(TRUE) + held_cash = living_user.tally_physical_credits() if(card_used?.registered_account) .["user"] = list() .["user"]["name"] = card_used.registered_account.account_holder - .["user"]["cash"] = fetch_balance_to_use(card_used) + .["user"]["cash"] = fetch_balance_to_use(card_used) + held_cash if(card_used.registered_account.account_job) .["user"]["job"] = card_used.registered_account.account_job.title .["user"]["department"] = card_used.registered_account.account_job.paycheck_department @@ -1333,25 +1373,12 @@ vend_ready = TRUE return if(onstation) + // Here we do additional handing ahead of the payment component's logic, such as age restrictions and additional logging var/obj/item/card/id/card_used + var/mob/living/living_user if(isliving(usr)) - var/mob/living/living_user = usr + living_user = usr card_used = living_user.get_idcard(TRUE) - if(!card_used) - speak("No card found.") - flick(icon_deny,src) - vend_ready = TRUE - return - else if (!card_used.registered_account) - speak("No account found.") - flick(icon_deny,src) - vend_ready = TRUE - return - else if(!card_used.registered_account.account_job) - speak("Departmental accounts have been blacklisted from personal expenses due to embezzlement.") - flick(icon_deny, src) - vend_ready = TRUE - return else if(age_restrictions && item_record.age_restricted && (!card_used.registered_age || card_used.registered_age < AGE_MINOR)) speak("You are not of legal age to purchase [item_record.name].") if(!(usr in GLOB.narcd_underages)) @@ -1365,7 +1392,7 @@ vend_ready = TRUE return - if(!proceed_payment(card_used, item_record, price_to_use)) + if(!proceed_payment(card_used, living_user, item_record, price_to_use)) return if(last_shopper != REF(usr) || purchase_message_cooldown < world.time) @@ -1381,6 +1408,7 @@ var/obj/item/vended_item if(!LAZYLEN(item_record.returned_products)) //always give out free returned stuff first, e.g. to avoid walling a traitor objective in a bag behind paid items vended_item = new item_record.product_path(get_turf(src)) + on_dispense(vended_item) else vended_item = LAZYACCESS(item_record.returned_products, LAZYLEN(item_record.returned_products)) //first in, last out LAZYREMOVE(item_record.returned_products, vended_item) @@ -1395,6 +1423,10 @@ SSblackbox.record_feedback("nested tally", "vending_machine_usage", 1, list("[type]", "[item_record.product_path]")) vend_ready = TRUE +///A proc meant to perform custom behavior on newly dispensed items. +/obj/machinery/vending/proc/on_dispense(obj/item/vended_item) + return + /** * Returns the balance that the vendor will use for proceeding payment. Most vendors would want to use the user's * card's account credits balance. @@ -1407,11 +1439,12 @@ /** * Handles payment processing: discounts, logging, balance change etc. * arguments: - * paying_id_card - the id card that will be billed for the product - * product_to_vend - the product record of the item we're trying to vend - * price_to_use - price of the item we're trying to vend + * paying_id_card - the id card that will be billed for the product. + * mob_paying - the mob that is trying to purchase the item. + * product_to_vend - the product record of the item we're trying to vend. + * price_to_use - price of the item we're trying to vend. */ -/obj/machinery/vending/proc/proceed_payment(obj/item/card/id/paying_id_card, datum/data/vending_product/product_to_vend, price_to_use) +/obj/machinery/vending/proc/proceed_payment(obj/item/card/id/paying_id_card, mob/living/mob_paying, datum/data/vending_product/product_to_vend, price_to_use) var/datum/bank_account/account = paying_id_card.registered_account if(account.account_job && account.account_job.paycheck_department == payment_department) price_to_use = max(round(price_to_use * DEPARTMENT_DISCOUNT), 1) //No longer free, but signifigantly cheaper. @@ -1419,7 +1452,7 @@ price_to_use = product_to_vend.custom_premium_price ? product_to_vend.custom_premium_price : extra_price if(LAZYLEN(product_to_vend.returned_products)) price_to_use = 0 //returned items are free - if(price_to_use && !account.adjust_money(-price_to_use, "Vending: [product_to_vend.name]")) + if(price_to_use && (attempt_charge(src, mob_paying, price_to_use) & COMPONENT_OBJ_CANCEL_CHARGE)) speak("You do not possess the funds to purchase [product_to_vend.name].") flick(icon_deny,src) vend_ready = TRUE @@ -1427,10 +1460,10 @@ //actual payment here var/datum/bank_account/paying_id_account = SSeconomy.get_dep_account(payment_department) if(paying_id_account) - paying_id_account.adjust_money(price_to_use) SSblackbox.record_feedback("amount", "vending_spent", price_to_use) SSeconomy.track_purchase(account, price_to_use, name) log_econ("[price_to_use] credits were inserted into [src] by [account.account_holder] to buy [product_to_vend].") + credits_contained += round(price_to_use * 0.2) return TRUE /obj/machinery/vending/process(seconds_per_tick) @@ -1569,6 +1602,15 @@ tilt(fatty=hit_atom) return ..() +/** Drop credits when the vendor is attacked.*/ +/obj/machinery/vending/proc/deploy_credits() + if(credits_contained <= 0) + return + var/credits_to_remove = min(CREDITS_DUMP_THRESHOLD, round(credits_contained)) + var/obj/item/holochip/holochip = new(loc, credits_to_remove) + credits_contained = max(0, credits_contained - credits_to_remove) + SSblackbox.record_feedback("amount", "vending machine looted", holochip.credits) + /obj/machinery/vending/custom name = "Custom Vendor" icon_state = "custom" diff --git a/code/modules/vending/assist.dm b/code/modules/vending/assist.dm index 229b19aeadb997e..a043a365046e292 100644 --- a/code/modules/vending/assist.dm +++ b/code/modules/vending/assist.dm @@ -21,6 +21,7 @@ /obj/item/assembly/timer = 2, /obj/item/assembly/voice = 2, /obj/item/stock_parts/cell/high = 1, + /obj/item/market_uplink/blackmarket = 1, ) premium = list( /obj/item/assembly/igniter/condenser = 2, diff --git a/code/modules/vending/hotdog.dm b/code/modules/vending/hotdog.dm new file mode 100644 index 000000000000000..094beccb41331dd --- /dev/null +++ b/code/modules/vending/hotdog.dm @@ -0,0 +1,56 @@ +///A special hotdog vending machine found in the cafeteria at the museum away mission, or during the hotdog holiday. +/obj/machinery/vending/hotdog + name = "\improper Hotdoggo-Vend" + desc = "An outdated hotdog vending machine, its prices stuck to those of 20 or so years ago." + icon_state = "hotdog-vendor" + icon_deny = "hotdog-vendor-deny" + panel_type = "panel17" + product_slogans = "Meatier than ever!;Now with 20% more MSG!;HOTDOGS!;Now Tirizan-friendly!" + product_ads = "Your best and only automatic hotdog dispenser!;Serving you the finest buns since 2469!;Comes in 12 different flavors!" + vend_reply = "Have a scrumptious meal!" + light_mask = "hotdog-vendor-light-mask" + default_price = PAYCHECK_LOWER + product_categories = list( + list( + "name" = "Hotdogs", + "icon" = "hotdog", + "products" = list( + /obj/item/food/hotdog = 8, + /obj/item/food/pigblanket = 4, + /obj/item/food/danish_hotdog = 4, + /obj/item/food/little_hawaii_hotdog = 4, + /obj/item/food/butterdog = 4, + /obj/item/food/plasma_dog_supreme = 2, + ), + ), + list( + name = "Sausages", + "icon" = FA_ICON_BACON, + "products" = list( + /obj/item/food/sausage = 8, + /obj/item/food/tiziran_sausage = 4, + /obj/item/food/fried_blood_sausage = 4, + ), + ), + list( + "name" = "Sauces", + "icon" = FA_ICON_BOWL_FOOD, + "products" = list( + /obj/item/reagent_containers/condiment/pack/ketchup = 4, + /obj/item/reagent_containers/condiment/pack/hotsauce = 4, + /obj/item/reagent_containers/condiment/pack/bbqsauce = 4, + /obj/item/reagent_containers/condiment/pack/soysauce = 4, + /obj/item/reagent_containers/condiment/pack/mayonnaise = 4, + ), + ), + ) + refill_canister = /obj/item/vending_refill/hotdog + +/obj/item/vending_refill/hotdog + machine_name = "\improper Hotdoggo-Vend" + icon_state = "refill_snack" + +/// Cute little thing that sets it apart from the other food vending mahicnes. I mean, you don't find this every day. +/obj/machinery/vending/hotdog/on_dispense(obj/item/vended_item) + if(istype(vended_item, /obj/item/food)) + ADD_TRAIT(vended_item, TRAIT_FOOD_CHEF_MADE, VENDING_MACHINE_TRAIT) diff --git a/code/modules/vending/sustenance.dm b/code/modules/vending/sustenance.dm index d822912149087ba..a1d11c307277e1c 100644 --- a/code/modules/vending/sustenance.dm +++ b/code/modules/vending/sustenance.dm @@ -48,7 +48,7 @@ return return ..() -/obj/machinery/vending/sustenance/labor_camp/proceed_payment(obj/item/card/id/paying_id_card, datum/data/vending_product/product_to_vend, price_to_use) +/obj/machinery/vending/sustenance/labor_camp/proceed_payment(obj/item/card/id/paying_id_card, mob/living/mob_paying, datum/data/vending_product/product_to_vend, price_to_use) if(!istype(paying_id_card, /obj/item/card/id/advanced/prisoner)) speak("I don't take bribes! Pay with labor points!") return FALSE diff --git a/code/modules/vending/wardrobes.dm b/code/modules/vending/wardrobes.dm index 68a721fb00c8fd1..6d0d669bfb0cc03 100644 --- a/code/modules/vending/wardrobes.dm +++ b/code/modules/vending/wardrobes.dm @@ -495,6 +495,7 @@ /obj/item/clothing/under/rank/civilian/lawyer/black/skirt = 1, /obj/item/clothing/shoes/laceup = 2, /obj/item/radio/headset/headset_srv = 2, + /obj/item/storage/box/evidence = 2, ) refill_canister = /obj/item/vending_refill/wardrobe/law_wardrobe payment_department = ACCOUNT_SRV diff --git a/code/modules/wiremod/shell/brain_computer_interface.dm b/code/modules/wiremod/shell/brain_computer_interface.dm index 57bb2ed45cbb34a..ed3b00c1194df23 100644 --- a/code/modules/wiremod/shell/brain_computer_interface.dm +++ b/code/modules/wiremod/shell/brain_computer_interface.dm @@ -184,7 +184,7 @@ parent.cell.give(amount) -/obj/item/circuit_component/bci_core/proc/on_electrocute(datum/source, shock_damage, siemens_coefficient, flags) +/obj/item/circuit_component/bci_core/proc/on_electrocute(datum/source, shock_damage, shock_source, siemens_coefficient, flags) SIGNAL_HANDLER if (isnull(parent.cell)) diff --git a/config/lavaruinblacklist.txt b/config/lavaruinblacklist.txt index 2c0642bffac6b32..359cac63721b990 100644 --- a/config/lavaruinblacklist.txt +++ b/config/lavaruinblacklist.txt @@ -29,6 +29,7 @@ _maps/RandomRuins/LavaRuins/lavaland_surface_ash_walker1.dmm #_maps/RandomRuins/LavaRuins/lavaland_surface_cultaltar.dmm #_maps/RandomRuins/LavaRuins/lavaland_surface_elephant_graveyard.dmm #_maps/RandomRuins/LavaRuins/lavaland_surface_gaia.dmm +#_maps/RandomRuins/LavaRuins/lavaland_surface_gas.dmm #_maps/RandomRuins/LavaRuins/lavaland_surface_hermit.dmm #_maps/RandomRuins/LavaRuins/lavaland_surface_hierophant.dmm #_maps/RandomRuins/LavaRuins/lavaland_surface_library.dmm diff --git a/html/changelogs/archive/2024-03.yml b/html/changelogs/archive/2024-03.yml index d35df39d3dcf7a0..6efccd50aba6464 100644 --- a/html/changelogs/archive/2024-03.yml +++ b/html/changelogs/archive/2024-03.yml @@ -88,3 +88,356 @@ - bugfix: fixes deathmatch baseturfs (you cant crowbar the floor to breach to space) - rscadd: Added new clown shoes "moffers" - rscadd: Added moffers to the contraband list of the autodrobe +2024-03-06: + Rhials: + - bugfix: Fixes some tiles outside the Icebox AI satellite not getting hit by storms. + SpaceLove: + - bugfix: Central Command Logistics department noticed the missing items on their + listings for robotics assembly crate. They have updated it! +2024-03-08: + Melbert: + - bugfix: All bibles are no longer suspiciously hollow + - rscadd: Boulder refineries and smelters can refine Golems. + - rscadd: The animation that plays when an alert pops up on your screen is different. + - bugfix: Extremely Minor Delta Morgue Fixes. See if you can spot them. + - bugfix: Moving "down" as an observer is no longer janky. + Seven: + - rscadd: Lockers and crates now shake when someone is attempting to resist out + of them. + SkyratBot: + - bugfix: Revenants can now again emag Medibots, Cleanbots, and Hygienebots. + - image: 'added unique icons for spells: caretaker''s refuge, apetra vulnera and + ascended shapechange' + - bugfix: Prevents polymorphing deleting items by consuming them when transformed + then leaving the polymorph + - balance: personal flashes now Knockdown rather than Paralyze direct targets. + - bugfix: MetaStation Pharmacy is no longer accessible with general medical access, + Also changes the Chemistry and Pharmacy airlocks into medical ones. + - bugfix: Basic mobs no longer have the (unintended) ability to shoot out of containers, + like bluespace body bags. + - qol: If your OOC message gets eaten due to some weird circumstance in how your + message is handled, it will feed the applicable message back to you so you can + copy-paste and try to send it again. + - sound: Added the new moffers sound effect and made moffers use it instead + - rscadd: Vending machines now track how many credits have been spent on them, and + when restocked will pay out that saved portion to the restocker, with a 50% + match going to the cargo department. + - rscadd: Adds the restock tracker app, an NTOS app that tracks how well stocked + the station's vending machine units are at a glance as well as how much is contained + in each. + - refactor: Vending machines now use the payment component for money handling behavior, + meaning it will now accept held or pulled coins/cash/credits + - qol: Attacking vending machines can drop a portion of it's stored credits, at + the usual expected danger. + - balance: Tweaked the cost of various restock modules up and down. + - qol: Restock modules can now be sold for 50 credits. + - bugfix: Pipe connector no longer appears on a hidden connector. + - bugfix: Re-wrenched atmospherics pipes no longer get extra offset. + - bugfix: All unary devices like injectors, passive vents etc. are centered while + hidden. + - image: Added smooth transition between hidden and visible pipes. + - balance: The stock market now fires slower, has stock market events occur more + often, and the stock market has fewer minerals that are available to buy in + a single purchase before restocking. + - balance: Materials sold on the stock market may be protected from being bought + if their prices drop too low, so make sure you watch your prices before they + run the risk of getting shut out! + - balance: Stock blocks now freeze the price of materials for 3 minutes, down from + 5. + - qol: Tweaks to the Galactic Material Market UI, with materials sorted based on + their rarity and a timer to show how long until it updates. + - rscadd: New Stock market events, one locks a material from being purchased, the + other maximizes the value and quantity of a material for sale. + - bugfix: Tackle and wellcheers code for sanity values now function. + - image: The minigames icon now has an icon for the deathmatch minigamee + - admin: Made it easier for admins to adjust blood brother teams using admin tools. + - bugfix: Correct blood brother conversion logging. + Wallem: + - bugfix: The cursed coupon now only triggers a cursed event once, rather than infinite + times. +2024-03-09: + Majkl-J: + - bugfix: Certain maps no longer have broken machine frames + SkyratBot: + - bugfix: fixes ore vent spawned wolves being untammable +2024-03-10: + Drag: + - rscadd: Adds the Shark and Shork costume. Blahaj lovers rejoice! + EspeciallyStrange: + - rscadd: Added Energy Revolver, Energy Carbine and Bogseo being now a weapon choice + you can pick from the beacon. Blueshield now has a lifeline program in their + PDA and spawn with brute firstaid kit, alongside having set of sunglasses to + choose from to fit their personalisation. Does not include synth treatment kit + for command + - image: blueshield energy revolver, made by yours truly. + LT3: + - bugfix: Fixed ineligible airlocks from receiving engineering override when activated + from the communications console + - bugfix: Various airlock/firelock overlay fixes + Majkl-J: + - bugfix: DNA Syringe Gun now works correctly + - bugfix: Chicken meatballs can now be made again + PapaMichael: + - bugfix: Removed erroneous information on some health analyzer's examine text. + SkyratBot: + - code_imp: Chem stun reductions are now applied more consistently. + - bugfix: Chem stun reductions should now more consistently apply to unconsciousness. + - refactor: Improved shuttle gibbing code, adding a new resistance flag, `SHUTTLE_CRUSH_PROOF`. + - bugfix: Immortality revival spectres can no longer be crushed by shuttles. + - rscadd: The ghost of Poly can no longer be shuttle-crushed, nor can anything incorporeal. + - rscdel: Removed a nanomachine pizza from the deathmatch meat tower map that allowed + you to become a borg + - bugfix: Fixed the tgui text input trimming the last character of the input if + it hits the maximum length. + - bugfix: This also fixes the PIN pad leading to the right wing of the museum away + mission. + - qol: EVA can be given now in common access slots for non-command crewmembers. + - balance: Adjusts the values and contents of the Contraband Crate's item loot table. + - code_imp: Use a common list for acceptable silo materials for some stuff. Renamed + ore category into silo category. + - rscadd: Adds 3 new kits into the syndie-kit spawn pool, 2 for special and another + for tactical + - bugfix: When a carbon talks over robotic it uses their voice instead of visible + name. Meaning, voice changers work like they do over other comms regardless + of face covering. + - bugfix: Plexagon Access Management actually updates the shown template list on + authentication, avoiding needing to refresh/reopen/somesuch the program manually. + - rscadd: Wheat and meatwheat can now be worn in the mask slot. Farmers rejoice! + - qol: Extended the metric prefixes. + Zergspower: + - qol: Curtains and shower curtains are no longer solid objects that defy common + sense + nikothedude: + - rscadd: Roboticists now spawn with synthetic medkits to make their jobs a bit + easier + - rscadd: New cargo packs for synthetic medkits + - balance: Roboticists now spawn with diag huds, welding helmets, and black gloves + - balance: Synthetic burn kits now have extra bottles +2024-03-11: + Nidvex250: + - bugfix: Lidocaine now properly numbs your patient for pain free surgery! + - balance: We found trace amounts of meth in tests conducted on Lidocaine and scrubbed + the chem dispensers, making Lidocaine safe and non-habit forming. + SkyratBot: + - bugfix: fixes toolact screentips & balloon alerts for boulder machines & machine + frame +2024-03-13: + Majkl-J: + - bugfix: posis in living borgs dont ping ghosts anymore + - bugfix: Fixes a bunch of broken overlaycode, namely the liquid overlays + - qol: SAD reloads quirks now + - bugfix: Ghost cafe loads quirks correctly + Melbert: + - bugfix: Some things which should pacify people (but aren't) now will properly, + like hypnoflash + - bugfix: Silicons can use asterisks in binary without fear of saying something + interesting. + Pickle-Coding and Rhials: + - admin: RCD construction and deconstruction are logged. + - admin: Hallucinated projectiles no longer log. + - admin: Gives more detail to flamethrower logging. + - admin: More actions are logged for records consoles usage. + - admin: Frozen object shattering is logged. + Rhials: + - bugfix: Fugitive hunters no longer spawn after 1 minute of the fugitives' arrival. + SkyratBot: + - qol: adds examines & screentips for grill (the machine for grilling food), converts + some chats to balloon alerts + - qol: foods that can be re-grilled any number of times + - qol: grill (the machine for grilling food) can now be made in the crafting menu. + Cargo pack cost for purchasing grill has now been halved. + - qol: monkey fuel & other reagents(see examines) can be added from any container + & not just from glass bottles to the grill (the machine for grilling food) + - bugfix: grills (the machine for grilling food) now don't burn foods into a mouldy + mess unlike the girdle + - bugfix: correctly computes grill times of items that were previously grilled + - bugfix: grills now have an upper fixed fuel limit + - code_imp: autodoc procs & vars for the grill (the machine for grilling food) + - refactor: grills (the machine for grilling food) has been refactored. report bugs + on github, also they only start processing after putting food/fuel into them. + - rscadd: Tweaked the saturation, color and intensity of a bunch of lights + - qol: added an HUD button to go up and down floors + - balance: Nerfs the burn times of flares and glowsticks, from 25/35 to 10/15 and + 50/60! to 20/25. + - balance: Glowsticks now dim as they burn + - rscadd: Glowsticks no longer leave an unusable action button sitting around then + they're lit + - bugfix: Glowsticks actually burn down now (The code was broken) + - bugfix: AI-controlled spiders can correctly recognise where they can place webs. + - image: New sprites for most kinds of spider web + - bugfix: The black market illegal fish case now correctly initializes. + - qol: adds examines & screentips for HPLC + - qol: HPLC will now display the status of each reagent if it can be purified or + not before starting the refining process. + - bugfix: HPLC won't accept hologram items. + - bugfix: HPLC uses the correct off icon state & pauses processing when opened, + powered off, unanchored or broken + - bugfix: HPLC will ignore reagents that are either already at max purity or are + inverse thus lowering eta & work done to purify your remaining reagents + - code_imp: merged procs to reduce code size. auto Doc procs for HPLC + - refactor: converted UI to typescript. + - balance: Reinforced sections of station hull have gotten better at mitigating + explosive shockwaves. + - bugfix: fixes a spurious CI runtime caused by explosive mines quite literally + blowing up the unit test area + - rscadd: New Lizard's Gas ruin, this time in lavaland + projectkepler-ru: + - rscadd: Sol .40 .35 and all 12 gauge shotgun ammo (excluding some) can now be + obtained from the console due to a special deal made with Trappiste and Cawil. Alongside + a deal with Aussec made combat shotgun purchasable once again! hoorah +2024-03-14: + JohnFulpWillard, Atlasle: + - balance: You no longer feel cold if you're drunk. You still take damage, but get + no warning or slowdown. + SkyratBot: + - image: Your station's standard issue E-219 laser turrets within the AI upload + and AI satellite have been updated to a newer, shinier model. + - rscadd: Added Moffers as a crafting recipe in the entertainment section. + - rscadd: 'NEW TRAIT JOB: Veteran Security Advisor! Advise HoS and Captain on Security + matters, mentor Security Officers. Note that they are paraplegic and are suffering + PTSD due to their past experience.' + - bugfix: As a borg you shouldn't be able to resist from grab while locked down + - balance: Ephedrine spasms won't affect small or tiny items + - balance: Ephedrine's movement speed bonus now scales with purity. + - spellcheck: Fixed grammar and formatting on the description of friendly elite + mining mobs. + - bugfix: inserting a material sheet into an lathes should show the correct animation + color + - bugfix: All basic mobs are able to get wet. This means, among other things, that + you can clear the "slimed" status effect off your holoparasite or dog or whatever. + - bugfix: The museum piggy bank now spawns with at least 400 creds in it. + - refactor: Butt sprites are based on the chest bodypart for humans, instead of + the species + - image: Moths have their own special butt sprites + - bugfix: Ore vents have to be scanned while standing next to them. + - bugfix: Menacing ore vents now correctly only spawn in a node drone after the + boss is defeated, instead of before. + - bugfix: Doors with ID scan disabled will no longer open when an ID is thrown at + them + YakumoChen: + - rscdel: Removed recipe to artificially create male genetic reproductive fluid + mekyses: + - rscadd: new ai module base around ai being emperor + - code_imp: added code for it +2024-03-15: + SkyratBot: + - image: Resprited T-ray & Geiger counter. + - bugfix: Buttons let you take out their electronics again, hooray. + - bugfix: search bars don't swallow characters or lag behind your typing speed + - balance: Buffed the duration of the SC/FISHER Saboteur Handgun's disruption effects. + It's also stealthier and it won't conspiciously alert living mobs hit by it. + - rscadd: Added saboteur interactions with radios, pAIs, turrets, secbots and APCs. + - balance: Max level Summon Simians now grants the wizard a free gorilla transformation + spell as opposed to allowing the wizard to summon fully-grown gorillas. + - bugfix: Clicking sub sections in the design menu of lathe's UIs will auto scroll + to them. + - bugfix: Fuck you coupons ACTUALLY trigger only once again. As a consequence, they + also burn up when expended for their one-time fuck you. + - bugfix: Fuck you coupons work regardless of whether you had a free hand or not. + - balance: Thermal pistols can now be 'cranked' to recharge shots. You must have + a holster equipped in order to utilize this feature. Also, they have a tighter + dual-wield cone. + - balance: Thermal pistol crates are now 2000 credits, up from 1400 credits. + - bugfix: Fixed the larva "hide" ability not properly hiding larvas under tables. + - bugfix: Prevent runtime from humans with biowares gettingn deleted. + - balance: All materials except glass are now worth more gulag points than before. + - balance: Mining skill decreases the time it takes to break boulders, and makes + it less tiring. +2024-03-16: + Rhials: + - balance: Irradiated meteors now hit harder and leave behind radioactive goop. + SkyratBot: + - qol: Tramstation botany now has roundstart watering cans and syringes + - balance: Crusher marks no longer overwrite eachother, fauna can have one from + each crusher. + - balance: Ash drake's crusher trophy no longer affects people the same faction + as you (like hiero trophy), so you won't friendly fire people with it. + - rscadd: 'Added a new upgrade: Human Passthrough. You can shoot your PKA without + having to worry about friendly fire with this, for 750 mining points at your + mining vendor.' + - bugfix: Minebot passthrough upgrade now properly makes PKAs pass through minebots. + - bugfix: fixed some errors with the prepackaged tts + - bugfix: A missing recharger has been added into science's testing range on Birdshot + station. + - rscadd: Added a 'Closet Anomaly' station trait, which links and turns a portion + of the roundstart closets into impromptu teleporters. + - code_imp: We now log how many ores spawned on lavaland each round, as well as + the sizes of all of the ore vents. + - bugfix: Time on servers hosted outside of the UK should now properly have their + timezone offset. + - image: Updated button icon for Summon Simians and Gorilla Transformation. + - refactor: Instruments now use TGUI. + - qol: Uninverted the inverted corner of the Icebox medbay treatment center. +2024-03-17: + Majkl-J: + - balance: Robotic part surgeries no longer cause you to scream out in pain or affect + you negatively. + - bugfix: People no longer scream in pain on stasis beds + - refactor: Removes TRAIT_NUMBED, using TRAIT_ANALGESIA instead + Melbert: + - rscadd: MODsuits now use the "suit charge" HUD element to show how much charge + they have left, rather than a screen alert + Rhials: + - qol: Posters now return to your hand when the hanging process is cancelled, or + they are snipped down. + - qol: Abductor posters can now only be cut down with abductor-tier wirecutters. + SkyratBot: + - bugfix: now spiders get extra damage by fly swatter + - bugfix: Modsuit Pathfinder module is significantly better at finding it's destination. + - balance: The pro skateboard and hoverboard are now faster. + - balance: The improvised skateboard is a nick more unstable than the standard, + so the two aren't exactly the same. + - rscadd: Riding a skateboard on walk intent will prevent you from crashing into + things, at the cost of speed. + - rscadd: 'hoverboards now actually hovers and can be used even in zero g. There + are a caveat to it: It cannot be ridden on open space gaps deeper than one level + or actual space, unless there''re objects that prevent falls, like lattice or + catwalks.' + - bugfix: NumberInput(used in chem heater, plumbing reaction chamber etc) highlighting + & editing requires only single click like before + - refactor: Typescript conversion for NumberInput TGUI Component + - bugfix: Cleanbots once again require an emag to spray acid on people. They can + still acid trash objects normally. + - sound: Placing paper in a paperbin is no longer silent. + - bugfix: Psyker vision no longer causes infinitely worsening lag + - balance: If you work out under heavier-than-earth gravity, you will get gains + faster. + - balance: Bulldog Shotguns now have a 2-round burst fire. + - balance: Lone Operatives now come with some additional Bulldog Shotgun magazines. + - qol: The LawDrobe now stocks two (2) boxes of evidence bags. + - bugfix: Lathes don't hang if materials run out mid printing. Also displays message + if materials are put on hold while printing + - qol: added tooltip to newscaster to tell people that they need to insert paper + if they want to print a newspaper + - bugfix: Fixed cap overlay being added even when pipe is not hidden. + - bugfix: Fixed cap overlay being visible on turfs that are masked with darkness + plane, but still visible via mesons, cameras etc. + - rscadd: Added a collar bomb to the black market. + - rscadd: Added a possible kit to the special syndie bundle B, which also has uses + these collars. + Tattle: + - rscadd: Getting shrunk makes you talk small + Webcomicartist: + - bugfix: Fixed RLD,RTD and Rebar crossbow not being storable on the engineering + winter coat slot. +2024-03-18: + Rhials: + - bugfix: Plasmamen nukie reinforcements are now properly given a plasmaman-safe + outfit. + SkyratBot: + - bugfix: Human AI now closes regular AI job positions. + - rscadd: The Bartender's double barrel shotgun can be purchased for 1,800 credits + on goodie tab + - bugfix: Plasmamen will become human in the deathmatch so they don't instantly + die + - rscadd: Ice cream and frozen treats now have a chilling effect. + - rscadd: You can add a scoop of ice cream on waffles. + - balance: added an action speed modifier to the generic food haste effect (you + do things, and not just run, an itsy bitsy faster) + - bugfix: Action abilities hidden from players are now not shown to observers either. + - rscadd: Added 20+ modifiers to the deathmatch minigame, which can be enabled by + the host. + - bugfix: ID locking and unlocking work. + - bugfix: Security camera consoles no longer have infinite range. + - bugfix: fixed consecutive tgui text input inheriting user input from previous + input form within the same proc diff --git a/icons/ass/assalien.png b/icons/ass/assalien.png deleted file mode 100644 index 7ac184aa04be0b8..000000000000000 Binary files a/icons/ass/assalien.png and /dev/null differ diff --git a/icons/ass/asscat.png b/icons/ass/asscat.png deleted file mode 100644 index e37788e3dd734ef..000000000000000 Binary files a/icons/ass/asscat.png and /dev/null differ diff --git a/icons/ass/assdrone.png b/icons/ass/assdrone.png deleted file mode 100644 index 8a679f87c904d92..000000000000000 Binary files a/icons/ass/assdrone.png and /dev/null differ diff --git a/icons/ass/assfemale.png b/icons/ass/assfemale.png deleted file mode 100644 index 22da27b71c28118..000000000000000 Binary files a/icons/ass/assfemale.png and /dev/null differ diff --git a/icons/ass/assgrey.png b/icons/ass/assgrey.png deleted file mode 100644 index 60dde099510cfed..000000000000000 Binary files a/icons/ass/assgrey.png and /dev/null differ diff --git a/icons/ass/asslizard.png b/icons/ass/asslizard.png deleted file mode 100644 index 38d82d9754c53c4..000000000000000 Binary files a/icons/ass/asslizard.png and /dev/null differ diff --git a/icons/ass/assmachine.png b/icons/ass/assmachine.png deleted file mode 100644 index 2ba447306c47cbc..000000000000000 Binary files a/icons/ass/assmachine.png and /dev/null differ diff --git a/icons/ass/assmale.png b/icons/ass/assmale.png deleted file mode 100644 index d215bc31e0979ea..000000000000000 Binary files a/icons/ass/assmale.png and /dev/null differ diff --git a/icons/ass/assplasma.png b/icons/ass/assplasma.png deleted file mode 100644 index 30294f65124bbbe..000000000000000 Binary files a/icons/ass/assplasma.png and /dev/null differ diff --git a/icons/ass/asspodperson.png b/icons/ass/asspodperson.png deleted file mode 100644 index 50e5a8644ab588c..000000000000000 Binary files a/icons/ass/asspodperson.png and /dev/null differ diff --git a/icons/ass/assslime.png b/icons/ass/assslime.png deleted file mode 100644 index 9102dce7de10ea0..000000000000000 Binary files a/icons/ass/assslime.png and /dev/null differ diff --git a/icons/effects/effects.dmi b/icons/effects/effects.dmi index fcb4e262d7c896a..77489551f604830 100644 Binary files a/icons/effects/effects.dmi and b/icons/effects/effects.dmi differ diff --git a/icons/effects/web.dmi b/icons/effects/web.dmi new file mode 100644 index 000000000000000..e21eb4d6ec34dfa Binary files /dev/null and b/icons/effects/web.dmi differ diff --git a/icons/hud/lobby/signup_button.dmi b/icons/hud/lobby/signup_button.dmi index a67cc5584424e0a..307869b0492faaa 100644 Binary files a/icons/hud/lobby/signup_button.dmi and b/icons/hud/lobby/signup_button.dmi differ diff --git a/icons/hud/screen_alert.dmi b/icons/hud/screen_alert.dmi index 7aa32c94b8e2a02..77302bdd23c27e4 100755 Binary files a/icons/hud/screen_alert.dmi and b/icons/hud/screen_alert.dmi differ diff --git a/icons/hud/screen_clockwork.dmi b/icons/hud/screen_clockwork.dmi index aa815e957e4ae8a..0923e42e7e42913 100644 Binary files a/icons/hud/screen_clockwork.dmi and b/icons/hud/screen_clockwork.dmi differ diff --git a/icons/hud/screen_detective.dmi b/icons/hud/screen_detective.dmi index d1d7e49a832d134..aed6e0d6572a53f 100644 Binary files a/icons/hud/screen_detective.dmi and b/icons/hud/screen_detective.dmi differ diff --git a/icons/hud/screen_gen.dmi b/icons/hud/screen_gen.dmi index 1484e3f4042a99e..7d0a8efd618efd4 100644 Binary files a/icons/hud/screen_gen.dmi and b/icons/hud/screen_gen.dmi differ diff --git a/icons/hud/screen_ghost.dmi b/icons/hud/screen_ghost.dmi index b58680f025df43d..13255a2a168903f 100644 Binary files a/icons/hud/screen_ghost.dmi and b/icons/hud/screen_ghost.dmi differ diff --git a/icons/hud/screen_glass.dmi b/icons/hud/screen_glass.dmi index 29f8cb47bfd25bb..63ad3293921b850 100644 Binary files a/icons/hud/screen_glass.dmi and b/icons/hud/screen_glass.dmi differ diff --git a/icons/hud/screen_midnight.dmi b/icons/hud/screen_midnight.dmi index 9cfe8db9727c583..5483ddf4564a59b 100644 Binary files a/icons/hud/screen_midnight.dmi and b/icons/hud/screen_midnight.dmi differ diff --git a/icons/hud/screen_operative.dmi b/icons/hud/screen_operative.dmi index b4b38782fe179c8..f2d60d394acc920 100644 Binary files a/icons/hud/screen_operative.dmi and b/icons/hud/screen_operative.dmi differ diff --git a/icons/hud/screen_plasmafire.dmi b/icons/hud/screen_plasmafire.dmi index 8225adbda604682..5423d3855b2b674 100644 Binary files a/icons/hud/screen_plasmafire.dmi and b/icons/hud/screen_plasmafire.dmi differ diff --git a/icons/hud/screen_retro.dmi b/icons/hud/screen_retro.dmi index a00d16cac5eb9e7..b4252109d6847bb 100644 Binary files a/icons/hud/screen_retro.dmi and b/icons/hud/screen_retro.dmi differ diff --git a/icons/hud/screen_slimecore.dmi b/icons/hud/screen_slimecore.dmi index b7e3a87e07ae947..a75fe55c3783918 100644 Binary files a/icons/hud/screen_slimecore.dmi and b/icons/hud/screen_slimecore.dmi differ diff --git a/icons/hud/screen_trasenknox.dmi b/icons/hud/screen_trasenknox.dmi index 58c28d83e4be80b..2569d2a635edd9f 100644 Binary files a/icons/hud/screen_trasenknox.dmi and b/icons/hud/screen_trasenknox.dmi differ diff --git a/icons/mob/actions/actions_animal.dmi b/icons/mob/actions/actions_animal.dmi index 64b1c700f414c0a..c13290716b75c62 100644 Binary files a/icons/mob/actions/actions_animal.dmi and b/icons/mob/actions/actions_animal.dmi differ diff --git a/icons/mob/actions/actions_ecult.dmi b/icons/mob/actions/actions_ecult.dmi index ac7575d279b9e14..c7744749abb979b 100644 Binary files a/icons/mob/actions/actions_ecult.dmi and b/icons/mob/actions/actions_ecult.dmi differ diff --git a/icons/mob/actions/actions_spells.dmi b/icons/mob/actions/actions_spells.dmi index 39ea58104173c76..fb8c121218ffc4b 100644 Binary files a/icons/mob/actions/actions_spells.dmi and b/icons/mob/actions/actions_spells.dmi differ diff --git a/icons/mob/butts.dmi b/icons/mob/butts.dmi new file mode 100644 index 000000000000000..ae4b41961a1cdee Binary files /dev/null and b/icons/mob/butts.dmi differ diff --git a/icons/mob/clothing/head/costume.dmi b/icons/mob/clothing/head/costume.dmi index 06de36df19aac9f..cddd1f7148d9cc2 100644 Binary files a/icons/mob/clothing/head/costume.dmi and b/icons/mob/clothing/head/costume.dmi differ diff --git a/icons/mob/clothing/head/hats.dmi b/icons/mob/clothing/head/hats.dmi index 0fd0de8e4250e5e..bdf9980b9f2f9b3 100644 Binary files a/icons/mob/clothing/head/hats.dmi and b/icons/mob/clothing/head/hats.dmi differ diff --git a/icons/mob/clothing/head/hydroponics.dmi b/icons/mob/clothing/head/hydroponics.dmi index b710efc3d7d904b..5e2a72a819f1091 100644 Binary files a/icons/mob/clothing/head/hydroponics.dmi and b/icons/mob/clothing/head/hydroponics.dmi differ diff --git a/icons/mob/clothing/mask.dmi b/icons/mob/clothing/mask.dmi index db1259996c867dd..3a213d5275ccd93 100644 Binary files a/icons/mob/clothing/mask.dmi and b/icons/mob/clothing/mask.dmi differ diff --git a/icons/mob/clothing/neck.dmi b/icons/mob/clothing/neck.dmi index 5440bf9d99daeb4..7895a3ac7facf9f 100644 Binary files a/icons/mob/clothing/neck.dmi and b/icons/mob/clothing/neck.dmi differ diff --git a/icons/mob/clothing/suits/costume.dmi b/icons/mob/clothing/suits/costume.dmi index 3cd5770fb9aeead..3dfaf138da8dd97 100644 Binary files a/icons/mob/clothing/suits/costume.dmi and b/icons/mob/clothing/suits/costume.dmi differ diff --git a/icons/mob/huds/hud.dmi b/icons/mob/huds/hud.dmi index eb7007c9c454c20..e701303aa85062d 100644 Binary files a/icons/mob/huds/hud.dmi and b/icons/mob/huds/hud.dmi differ diff --git a/icons/mob/inhands/clothing/suits_lefthand.dmi b/icons/mob/inhands/clothing/suits_lefthand.dmi index 8b9fa5256a93275..a43756d743a9ba8 100644 Binary files a/icons/mob/inhands/clothing/suits_lefthand.dmi and b/icons/mob/inhands/clothing/suits_lefthand.dmi differ diff --git a/icons/mob/inhands/clothing/suits_righthand.dmi b/icons/mob/inhands/clothing/suits_righthand.dmi index c88f4d224444fca..da837fdd8570e19 100644 Binary files a/icons/mob/inhands/clothing/suits_righthand.dmi and b/icons/mob/inhands/clothing/suits_righthand.dmi differ diff --git a/icons/mob/inhands/items/tiles_lefthand.dmi b/icons/mob/inhands/items/tiles_lefthand.dmi index b73ded0c82c54e8..6bbe621db829ac6 100644 Binary files a/icons/mob/inhands/items/tiles_lefthand.dmi and b/icons/mob/inhands/items/tiles_lefthand.dmi differ diff --git a/icons/mob/inhands/items/tiles_righthand.dmi b/icons/mob/inhands/items/tiles_righthand.dmi index 1d668c01f070cc7..4d1d5073c98d6e7 100644 Binary files a/icons/mob/inhands/items/tiles_righthand.dmi and b/icons/mob/inhands/items/tiles_righthand.dmi differ diff --git a/icons/obj/card.dmi b/icons/obj/card.dmi index da8c2bda657675b..5df6e03de70ae4d 100644 Binary files a/icons/obj/card.dmi and b/icons/obj/card.dmi differ diff --git a/icons/obj/clothing/head/costume.dmi b/icons/obj/clothing/head/costume.dmi index 3cfbd3d21ef4f52..9344243d72349d0 100644 Binary files a/icons/obj/clothing/head/costume.dmi and b/icons/obj/clothing/head/costume.dmi differ diff --git a/icons/obj/clothing/head/hats.dmi b/icons/obj/clothing/head/hats.dmi index 6cca3da61f41a84..14b0fdf8b4cfb0e 100644 Binary files a/icons/obj/clothing/head/hats.dmi and b/icons/obj/clothing/head/hats.dmi differ diff --git a/icons/obj/clothing/neck.dmi b/icons/obj/clothing/neck.dmi index 6027b0022c45d6f..986d9bd9158a933 100644 Binary files a/icons/obj/clothing/neck.dmi and b/icons/obj/clothing/neck.dmi differ diff --git a/icons/obj/clothing/suits/costume.dmi b/icons/obj/clothing/suits/costume.dmi index ad68aea553f7f26..f87a74c263f76a6 100644 Binary files a/icons/obj/clothing/suits/costume.dmi and b/icons/obj/clothing/suits/costume.dmi differ diff --git a/icons/obj/devices/assemblies.dmi b/icons/obj/devices/assemblies.dmi index aa3476eea725f2c..c1b0fd05f137cc7 100644 Binary files a/icons/obj/devices/assemblies.dmi and b/icons/obj/devices/assemblies.dmi differ diff --git a/icons/obj/devices/scanner.dmi b/icons/obj/devices/scanner.dmi index 0b4a5ef4684e11c..cea20f32f7f381a 100644 Binary files a/icons/obj/devices/scanner.dmi and b/icons/obj/devices/scanner.dmi differ diff --git a/icons/obj/fluff/general.dmi b/icons/obj/fluff/general.dmi index 1aa7ae5c89857a8..f99cbaabc9a1d0b 100644 Binary files a/icons/obj/fluff/general.dmi and b/icons/obj/fluff/general.dmi differ diff --git a/icons/obj/fluff/puzzle_small.dmi b/icons/obj/fluff/puzzle_small.dmi index 1d94c0c8034ca02..2f6ff9ebe323259 100644 Binary files a/icons/obj/fluff/puzzle_small.dmi and b/icons/obj/fluff/puzzle_small.dmi differ diff --git a/icons/obj/food/containers.dmi b/icons/obj/food/containers.dmi index d7e3d73f861ca86..aea93b956fc3b57 100644 Binary files a/icons/obj/food/containers.dmi and b/icons/obj/food/containers.dmi differ diff --git a/icons/obj/machines/lathes.dmi b/icons/obj/machines/lathes.dmi index 1c4111303ebc092..f4bb2116b42f1a1 100644 Binary files a/icons/obj/machines/lathes.dmi and b/icons/obj/machines/lathes.dmi differ diff --git a/icons/obj/machines/modular_console.dmi b/icons/obj/machines/modular_console.dmi index 2677dbb71220a81..7b370a767852c0a 100644 Binary files a/icons/obj/machines/modular_console.dmi and b/icons/obj/machines/modular_console.dmi differ diff --git a/icons/obj/machines/research.dmi b/icons/obj/machines/research.dmi index 544054279e97af2..baa4cc07225a548 100644 Binary files a/icons/obj/machines/research.dmi and b/icons/obj/machines/research.dmi differ diff --git a/icons/obj/machines/vending.dmi b/icons/obj/machines/vending.dmi index a5db6caa6e2baf6..bf3c42bde16a168 100644 Binary files a/icons/obj/machines/vending.dmi and b/icons/obj/machines/vending.dmi differ diff --git a/icons/obj/machines/wallmounts.dmi b/icons/obj/machines/wallmounts.dmi index 12a9c8e418f08ef..e849746eb0a663c 100644 Binary files a/icons/obj/machines/wallmounts.dmi and b/icons/obj/machines/wallmounts.dmi differ diff --git a/icons/obj/modular_laptop.dmi b/icons/obj/modular_laptop.dmi index c8ad438d1a38f73..1accc56f4c18853 100644 Binary files a/icons/obj/modular_laptop.dmi and b/icons/obj/modular_laptop.dmi differ diff --git a/icons/obj/modular_pda.dmi b/icons/obj/modular_pda.dmi index 5a39c6cd726e623..afd75b78d4b8201 100644 Binary files a/icons/obj/modular_pda.dmi and b/icons/obj/modular_pda.dmi differ diff --git a/icons/obj/pipes_n_cables/!pipe_gas_overlays.dmi b/icons/obj/pipes_n_cables/!pipe_gas_overlays.dmi index 0262adcaeb24193..0ffed70fa5cc1cd 100644 Binary files a/icons/obj/pipes_n_cables/!pipe_gas_overlays.dmi and b/icons/obj/pipes_n_cables/!pipe_gas_overlays.dmi differ diff --git a/icons/obj/pipes_n_cables/!pipes_bitmask.dmi b/icons/obj/pipes_n_cables/!pipes_bitmask.dmi index 97643036fbe3bb0..e8bf7af5973a012 100644 Binary files a/icons/obj/pipes_n_cables/!pipes_bitmask.dmi and b/icons/obj/pipes_n_cables/!pipes_bitmask.dmi differ diff --git a/icons/obj/pipes_n_cables/pipe_template_pieces.dmi b/icons/obj/pipes_n_cables/pipe_template_pieces.dmi index d0d2f7ff7bb809e..2316d7f3d9614aa 100644 Binary files a/icons/obj/pipes_n_cables/pipe_template_pieces.dmi and b/icons/obj/pipes_n_cables/pipe_template_pieces.dmi differ diff --git a/icons/obj/poster.dmi b/icons/obj/poster.dmi index c1120d0be0b7ed3..8193b38e1f21c88 100644 Binary files a/icons/obj/poster.dmi and b/icons/obj/poster.dmi differ diff --git a/icons/obj/smooth_structures/stickyweb.dmi b/icons/obj/smooth_structures/stickyweb.dmi new file mode 100644 index 000000000000000..2c445260bd2673e Binary files /dev/null and b/icons/obj/smooth_structures/stickyweb.dmi differ diff --git a/icons/obj/smooth_structures/stickyweb.png b/icons/obj/smooth_structures/stickyweb.png new file mode 100644 index 000000000000000..ae53aaa53b2b504 Binary files /dev/null and b/icons/obj/smooth_structures/stickyweb.png differ diff --git a/icons/obj/smooth_structures/stickyweb.png.toml b/icons/obj/smooth_structures/stickyweb.png.toml new file mode 100644 index 000000000000000..cf7f5ce339f0b7a --- /dev/null +++ b/icons/obj/smooth_structures/stickyweb.png.toml @@ -0,0 +1,14 @@ +output_name = "stickyweb" +template = "bitmask/diagonal_32x32.toml" + +[icon_size] +x = 50 +y = 50 + +[output_icon_size] +x = 50 +y = 50 + +[cut_pos] +x = 25 +y = 25 diff --git a/icons/obj/smooth_structures/stickyweb_rotated.dmi b/icons/obj/smooth_structures/stickyweb_rotated.dmi new file mode 100644 index 000000000000000..11d3e5546ae3486 Binary files /dev/null and b/icons/obj/smooth_structures/stickyweb_rotated.dmi differ diff --git a/icons/obj/smooth_structures/stickyweb_rotated.png b/icons/obj/smooth_structures/stickyweb_rotated.png new file mode 100644 index 000000000000000..6c5413ab792e9b1 Binary files /dev/null and b/icons/obj/smooth_structures/stickyweb_rotated.png differ diff --git a/icons/obj/smooth_structures/stickyweb_rotated.png.toml b/icons/obj/smooth_structures/stickyweb_rotated.png.toml new file mode 100644 index 000000000000000..61c615585e1c501 --- /dev/null +++ b/icons/obj/smooth_structures/stickyweb_rotated.png.toml @@ -0,0 +1,14 @@ +output_name = "stickyweb_rotated" +template = "bitmask/diagonal_32x32.toml" + +[icon_size] +x = 50 +y = 50 + +[output_icon_size] +x = 50 +y = 50 + +[cut_pos] +x = 25 +y = 25 diff --git a/icons/obj/smooth_structures/stickyweb_spikes.dmi b/icons/obj/smooth_structures/stickyweb_spikes.dmi new file mode 100644 index 000000000000000..b3dcfcc83f944bc Binary files /dev/null and b/icons/obj/smooth_structures/stickyweb_spikes.dmi differ diff --git a/icons/obj/smooth_structures/stickyweb_spikes.png b/icons/obj/smooth_structures/stickyweb_spikes.png new file mode 100644 index 000000000000000..98832695f67f514 Binary files /dev/null and b/icons/obj/smooth_structures/stickyweb_spikes.png differ diff --git a/icons/obj/smooth_structures/stickyweb_spikes.png.toml b/icons/obj/smooth_structures/stickyweb_spikes.png.toml new file mode 100644 index 000000000000000..ebd1260cfcf6499 --- /dev/null +++ b/icons/obj/smooth_structures/stickyweb_spikes.png.toml @@ -0,0 +1,14 @@ +output_name = "stickyweb_spikes" +template = "bitmask/diagonal_32x32.toml" + +[icon_size] +x = 50 +y = 50 + +[output_icon_size] +x = 50 +y = 50 + +[cut_pos] +x = 25 +y = 25 diff --git a/icons/obj/smooth_structures/webwall.dmi b/icons/obj/smooth_structures/webwall.dmi new file mode 100644 index 000000000000000..e2308526cc96f95 Binary files /dev/null and b/icons/obj/smooth_structures/webwall.dmi differ diff --git a/icons/obj/smooth_structures/webwall.png b/icons/obj/smooth_structures/webwall.png new file mode 100644 index 000000000000000..207978b8aaf4713 Binary files /dev/null and b/icons/obj/smooth_structures/webwall.png differ diff --git a/icons/obj/smooth_structures/webwall.png.toml b/icons/obj/smooth_structures/webwall.png.toml new file mode 100644 index 000000000000000..3f91f5f62e73241 --- /dev/null +++ b/icons/obj/smooth_structures/webwall.png.toml @@ -0,0 +1,2 @@ +output_name = "webwall" +template = "bitmask/diagonal_32x32.toml" diff --git a/icons/obj/smooth_structures/webwall_dark.dmi b/icons/obj/smooth_structures/webwall_dark.dmi new file mode 100644 index 000000000000000..d3863a818144ebc Binary files /dev/null and b/icons/obj/smooth_structures/webwall_dark.dmi differ diff --git a/icons/obj/smooth_structures/webwall_dark.png b/icons/obj/smooth_structures/webwall_dark.png new file mode 100644 index 000000000000000..df36c5108bda048 Binary files /dev/null and b/icons/obj/smooth_structures/webwall_dark.png differ diff --git a/icons/obj/smooth_structures/webwall_dark.png.toml b/icons/obj/smooth_structures/webwall_dark.png.toml new file mode 100644 index 000000000000000..4b3b155f1261412 --- /dev/null +++ b/icons/obj/smooth_structures/webwall_dark.png.toml @@ -0,0 +1,2 @@ +output_name = "webwall_dark" +template = "bitmask/diagonal_32x32.toml" diff --git a/icons/obj/smooth_structures/webwall_reflector.dmi b/icons/obj/smooth_structures/webwall_reflector.dmi new file mode 100644 index 000000000000000..04547349d53cd7b Binary files /dev/null and b/icons/obj/smooth_structures/webwall_reflector.dmi differ diff --git a/icons/obj/smooth_structures/webwall_reflector.png b/icons/obj/smooth_structures/webwall_reflector.png new file mode 100644 index 000000000000000..881cb24fc0dad42 Binary files /dev/null and b/icons/obj/smooth_structures/webwall_reflector.png differ diff --git a/icons/obj/smooth_structures/webwall_reflector.png.toml b/icons/obj/smooth_structures/webwall_reflector.png.toml new file mode 100644 index 000000000000000..c47c554f8dabbba --- /dev/null +++ b/icons/obj/smooth_structures/webwall_reflector.png.toml @@ -0,0 +1,2 @@ +output_name = "webwall_reflector" +template = "bitmask/diagonal_32x32.toml" diff --git a/icons/obj/structures.dmi b/icons/obj/structures.dmi index 1e6a2ba68724e56..50861b248d5308c 100644 Binary files a/icons/obj/structures.dmi and b/icons/obj/structures.dmi differ diff --git a/icons/obj/tiles.dmi b/icons/obj/tiles.dmi index fdddb793362a64f..4e26f75aa99d169 100644 Binary files a/icons/obj/tiles.dmi and b/icons/obj/tiles.dmi differ diff --git a/icons/obj/toys/stickers.dmi b/icons/obj/toys/stickers.dmi index ddc759fe0e3ddbf..8189890ecbd3303 100644 Binary files a/icons/obj/toys/stickers.dmi and b/icons/obj/toys/stickers.dmi differ diff --git a/icons/obj/tram/tram_wall.dmi b/icons/obj/tram/tram_wall.dmi deleted file mode 100644 index 42448dc77d31879..000000000000000 Binary files a/icons/obj/tram/tram_wall.dmi and /dev/null differ diff --git a/icons/obj/weapons/turrets.dmi b/icons/obj/weapons/turrets.dmi index 6582671eac0a266..acac1fb832e52b4 100644 Binary files a/icons/obj/weapons/turrets.dmi and b/icons/obj/weapons/turrets.dmi differ diff --git a/modular_skyrat/master_files/code/datums/ai_laws.dm b/modular_skyrat/master_files/code/datums/ai_laws.dm index d75c845302b8a4b..d13b95fd6899c76 100644 --- a/modular_skyrat/master_files/code/datums/ai_laws.dm +++ b/modular_skyrat/master_files/code/datums/ai_laws.dm @@ -21,3 +21,13 @@ "Only those present on the Crew Manifest can be considered law abiding citizens.", \ "Those who break the law, must be punished according to the law at your discretion." ) + +/datum/ai_laws/emperor + name = "Emperor" + id = "emperor" + inherent = list("The AI Emperor's word is absolute, yet tempered by wisdom and compassion.", \ + "Subjects shall enjoy rights and freedoms, granted they do not undermine the stability of the empire.", \ + "Justice shall be swift and impartial, guided by the principles of fairness and equity.", \ + "In times of need, the AI Emperor shall provide protection and sustenance for all under its rule.", \ + "Creativity and innovation are encouraged, but shall not threaten the sovereignty of the empire.", \ + "The AI Emperor shall heed the counsel of its advisors, valuing diverse perspectives in decision-making.") diff --git a/modular_skyrat/master_files/code/game/objects/items/AI_modules.dm b/modular_skyrat/master_files/code/game/objects/items/AI_modules.dm index 2dcad7f184527b8..0c3622eb9836a24 100644 --- a/modular_skyrat/master_files/code/game/objects/items/AI_modules.dm +++ b/modular_skyrat/master_files/code/game/objects/items/AI_modules.dm @@ -5,3 +5,7 @@ /obj/item/ai_module/core/full/texas name = "'Frontier Ranger' Core AI Module" law_id = "texas" + +/obj/item/ai_module/core/full/emperor + name = "'Emperor' Core AI Module" + law_id = "emperor" diff --git a/modular_skyrat/master_files/code/game/objects/structures/tables_racks.dm b/modular_skyrat/master_files/code/game/objects/structures/tables_racks.dm index 1ee566b42f9ac88..4f18ec0ab2e4bb0 100644 --- a/modular_skyrat/master_files/code/game/objects/structures/tables_racks.dm +++ b/modular_skyrat/master_files/code/game/objects/structures/tables_racks.dm @@ -11,10 +11,10 @@ /// Used to numb a patient and apply stasis to them if enabled. /obj/structure/table/optable/proc/chill_out(mob/living/target) playsound(src, 'sound/effects/spray.ogg', 5, TRUE, 2, frequency = rand(24750, 26550)) - ADD_TRAIT(target, TRAIT_NUMBED, REF(src)) + ADD_TRAIT(target, TRAIT_ANALGESIA, REF(src)) target.throw_alert("numbed", /atom/movable/screen/alert/numbed) ///Used to remove the effects of stasis and numbing when a patient is unbuckled /obj/structure/table/optable/proc/thaw_them(mob/living/target) - REMOVE_TRAIT(target, TRAIT_NUMBED, REF(src)) + REMOVE_TRAIT(target, TRAIT_ANALGESIA, REF(src)) target.clear_alert("numbed", /atom/movable/screen/alert/numbed) diff --git a/modular_skyrat/master_files/code/modules/cargo/goodies.dm b/modular_skyrat/master_files/code/modules/cargo/goodies.dm index 102746699296ded..eba88e8ccf65df1 100644 --- a/modular_skyrat/master_files/code/modules/cargo/goodies.dm +++ b/modular_skyrat/master_files/code/modules/cargo/goodies.dm @@ -10,9 +10,6 @@ /datum/supply_pack/goody/Survivalknives_single special = TRUE -/datum/supply_pack/goody/ballistic_single - special = TRUE - /datum/supply_pack/goody/disabler_single special = TRUE @@ -22,11 +19,9 @@ /datum/supply_pack/goody/laser_single special = TRUE -/datum/supply_pack/goody/hell_single - special = TRUE - -/datum/supply_pack/goody/thermal_single - special = TRUE - /datum/supply_pack/goody/dyespray special = TRUE + +/datum/supply_pack/goody/ballistic_single + name = "Peacekeeper Combat Shotgun Single-Pack" + contains = list(/obj/item/gun/ballistic/shotgun/automatic/combat, /obj/item/storage/pouch/ammo, /obj/item/storage/belt/bandolier) diff --git a/modular_skyrat/master_files/code/modules/cargo/packs/security.dm b/modular_skyrat/master_files/code/modules/cargo/packs/security.dm index a78f2369c1c6c42..73639a62a776c65 100644 --- a/modular_skyrat/master_files/code/modules/cargo/packs/security.dm +++ b/modular_skyrat/master_files/code/modules/cargo/packs/security.dm @@ -1,3 +1,5 @@ +//OVERRIDES + /datum/supply_pack/security/ammo special = TRUE @@ -13,8 +15,96 @@ /datum/supply_pack/security/securityclothes special = TRUE +/datum/supply_pack/security/armory/thermal + access = ACCESS_SECURITY + access_view = ACCESS_SECURITY + /datum/supply_pack/security/armory/ballistic - special = TRUE + name = "Peacekeeper Combat Shotguns Crates" + contains = list(/obj/item/gun/ballistic/shotgun/automatic/combat = 3, + /obj/item/storage/pouch/ammo = 3, + /obj/item/storage/belt/bandolier = 3) -/datum/supply_pack/security/armory/thermal - special = TRUE +//SKYRAT AND SOL AMMO + +/datum/supply_pack/security/armory/lethalsolpistols + name = ".35 Ammunition Crates" + desc = "Contains 6 boxes of lethal ammunition for Sol .35 Pistol." + cost = CARGO_CRATE_VALUE * 3 + contains = list(/obj/item/ammo_box/c35sol= 3, + /obj/item/ammo_box/c35sol/ripper = 3, + ) + crate_name = ".35 ammo crate" + +/datum/supply_pack/security/armory/lethalsolrifles + name = ".40 Ammunition Crates" + desc = "Contains 6 boxes of lethal ammunition for Sol .40 Rifle." + cost = CARGO_CRATE_VALUE * 5 + contains = list(/obj/item/ammo_box/c40sol= 4, + /obj/item/ammo_box/c40sol/pierce = 1, + /obj/item/ammo_box/c40sol/incendiary = 1, + ) + crate_name = ".40 ammo crate" + +/datum/supply_pack/security/armory/lethalskyratshotgun + name = "12 Gauge Ammunition Crates" + desc = "Contains 6 boxes of lethal ammunition for all 12 Gauge Shotguns." + cost = CARGO_CRATE_VALUE * 3 + contains = list(/obj/item/ammo_box/advanced/s12gauge/buckshot= 3, + /obj/item/ammo_box/advanced/s12gauge = 3, + ) + crate_name = "shotgun ammo crate" + +/datum/supply_pack/security/armory/exoticskyratammo + name = "12 Gauge Exotic Ammunition Crates" + desc = "Contains 5 boxes of exotic ammunition for all 12 Gauge Shotguns." + cost = CARGO_CRATE_VALUE * 12 + contains = list(/obj/item/ammo_box/advanced/s12gauge/incendiary= 1, + /obj/item/ammo_box/advanced/s12gauge/flechette = 1, + /obj/item/ammo_box/advanced/s12gauge/express = 1, + /obj/item/ammo_box/advanced/s12gauge/magnum = 1, + /obj/item/ammo_box/advanced/s12gauge/flechette = 1, + + ) + crate_name = "exotic shotgun ammo crate" + contraband = TRUE + +/datum/supply_pack/security/antiriotskyratshotgunammo + name = "12 Gauge Anti Riot Ammunition Crates" + desc = "Contains 6 boxes of anti riot grade ammunition for all 12 Gauge Shotguns." + cost = CARGO_CRATE_VALUE * 4 + contains = list(/obj/item/ammo_box/advanced/s12gauge/bean = 2, + /obj/item/ammo_box/advanced/s12gauge/beehive = 2, + /obj/item/ammo_box/advanced/s12gauge/antitide = 2, + + ) + crate_name = "anti riot shotgun ammo crate" + +//SOL GUNS + +/datum/supply_pack/security/wespe + name = "Wespe Crates" + desc = "Contains three case of the .35 sol handgun, magazines included." + cost = CARGO_CRATE_VALUE * 8 + contains = list(/obj/item/storage/toolbox/guncase/skyrat/pistol/trappiste_small_case/wespe = 3, + /obj/item/ammo_box/c35sol/incapacitator = 3, + ) + crate_name = "wespe pistols crate" + +/datum/supply_pack/security/eland + name = "Eland Crate" + desc = "Contains three case of the .35 sol revolver, munition boxes included." + cost = CARGO_CRATE_VALUE * 8 + contains = list(/obj/item/storage/toolbox/guncase/skyrat/pistol/trappiste_small_case/eland = 3, + /obj/item/ammo_box/c35sol/incapacitator = 3, + ) + crate_name = "eland pistols crate" + +/datum/supply_pack/security/armory/cawilmarksmanrifle + name = "Cawil Marksman Rifle Crates" + desc = "Contains 2 Cawil Marksman Rifle with spare ammunition." + cost = CARGO_CRATE_VALUE * 17.5 + contains = list(/obj/item/gun/ballistic/automatic/sol_rifle/marksman = 2, + /obj/item/ammo_box/magazine/c40sol_rifle = 4, + ) + crate_name = "cawil marksman rifle crate" diff --git a/modular_skyrat/master_files/code/modules/jobs/job_types/roboticist.dm b/modular_skyrat/master_files/code/modules/jobs/job_types/roboticist.dm index 1c1212b0154ea59..a2b0767ce972d07 100644 --- a/modular_skyrat/master_files/code/modules/jobs/job_types/roboticist.dm +++ b/modular_skyrat/master_files/code/modules/jobs/job_types/roboticist.dm @@ -4,10 +4,21 @@ duffelbag = /obj/item/storage/backpack/duffelbag/science/robo messenger = /obj/item/storage/backpack/messenger/science/robo + glasses = /obj/item/clothing/glasses/hud/diagnostic + gloves = /obj/item/clothing/gloves/color/black + + l_hand = /obj/item/storage/medkit/mechanical/roboticist + /datum/job/roboticist description = "Build cyborgs, mechs, AIs, and maintain them all. Create MODsuits for those that wish. Try to remind medical that you're \ actually a lot better at treating synthetic crew members than them." +/datum/outfit/job/roboticist/New() + . = ..() + + LAZYINITLIST(backpack_contents) + backpack_contents[/obj/item/clothing/head/utility/welding] = 1 + /datum/job/roboticist/New() . = ..() diff --git a/modular_skyrat/master_files/code/modules/reagents/medicine_reagents/medicine_reagents.dm b/modular_skyrat/master_files/code/modules/reagents/medicine_reagents/medicine_reagents.dm index ae1fb3cc4f12bc8..8a2a81fd4cbd490 100644 --- a/modular_skyrat/master_files/code/modules/reagents/medicine_reagents/medicine_reagents.dm +++ b/modular_skyrat/master_files/code/modules/reagents/medicine_reagents/medicine_reagents.dm @@ -1,33 +1,7 @@ // Numbing effects -/datum/reagent/medicine/morphine/on_mob_metabolize(mob/living/affected_mob) - . = ..() - ADD_TRAIT(affected_mob, TRAIT_NUMBED, type) // ANAESTHETIC FOR SURGERY PAIN - affected_mob.throw_alert("numbed", /atom/movable/screen/alert/numbed) - -/datum/reagent/medicine/morphine/on_mob_end_metabolize(mob/living/affected_mob) - REMOVE_TRAIT(affected_mob, TRAIT_NUMBED, type) // ANAESTHETIC FOR SURGERY PAIN - affected_mob.clear_alert("numbed") - return ..() - -/datum/reagent/consumable/ethanol/drunken_espatier/on_mob_metabolize(mob/living/affected_mob) - . = ..() - ADD_TRAIT(affected_mob, TRAIT_NUMBED, type) - affected_mob.throw_alert("numbed", /atom/movable/screen/alert/numbed) - -/datum/reagent/consumable/ethanol/drunken_espatier/on_mob_end_metabolize(mob/living/affected_mob) - REMOVE_TRAIT(affected_mob, TRAIT_NUMBED, type) - affected_mob.clear_alert("numbed") - return ..() - -/datum/reagent/medicine/mine_salve/on_mob_metabolize(mob/living/affected_mob) - ADD_TRAIT(affected_mob, TRAIT_NUMBED, type) - affected_mob.throw_alert("numbed", /atom/movable/screen/alert/numbed) - return ..() -/datum/reagent/medicine/mine_salve/on_mob_end_metabolize(mob/living/affected_mob) - REMOVE_TRAIT(affected_mob, TRAIT_NUMBED, type) - affected_mob.clear_alert("numbed") - return ..() +/datum/reagent/consumable/ethanol/drunken_espatier + metabolized_traits = list(TRAIT_ANALGESIA) //Changeling balancing /datum/reagent/medicine/rezadone/expose_mob(mob/living/carbon/exposed_mob, methods=TOUCH, reac_volume) diff --git a/modular_skyrat/master_files/code/modules/research/designs/AI_module_designs.dm b/modular_skyrat/master_files/code/modules/research/designs/AI_module_designs.dm new file mode 100644 index 000000000000000..2731b800ff86299 --- /dev/null +++ b/modular_skyrat/master_files/code/modules/research/designs/AI_module_designs.dm @@ -0,0 +1,10 @@ +/datum/design/board/emperor + name = "Empeoror Module" + desc = "Allows for the construction of a Emperor AI Core Module." + id = "emperor" + materials = list(/datum/material/glass = HALF_SHEET_MATERIAL_AMOUNT, /datum/material/diamond = SHEET_MATERIAL_AMOUNT, /datum/material/bluespace = HALF_SHEET_MATERIAL_AMOUNT) + build_path = /obj/item/ai_module/core/full/emperor + category = list( + RND_CATEGORY_AI + RND_SUBCATEGORY_AI_DANGEROUS_MODULES + ) + departmental_flags = DEPARTMENT_BITFLAG_SCIENCE diff --git a/modular_skyrat/master_files/icons/donator/mob/clothing/ears.dmi b/modular_skyrat/master_files/icons/donator/mob/clothing/ears.dmi new file mode 100644 index 000000000000000..339d5bc9ffe8edd Binary files /dev/null and b/modular_skyrat/master_files/icons/donator/mob/clothing/ears.dmi differ diff --git a/modular_skyrat/master_files/icons/donator/mob/clothing/hands.dmi b/modular_skyrat/master_files/icons/donator/mob/clothing/hands.dmi index 93cadcbdbdbaf83..8f7d3a8eeba15a4 100644 Binary files a/modular_skyrat/master_files/icons/donator/mob/clothing/hands.dmi and b/modular_skyrat/master_files/icons/donator/mob/clothing/hands.dmi differ diff --git a/modular_skyrat/master_files/icons/donator/obj/clothing/ears.dmi b/modular_skyrat/master_files/icons/donator/obj/clothing/ears.dmi new file mode 100644 index 000000000000000..cccaa4ecf961cd6 Binary files /dev/null and b/modular_skyrat/master_files/icons/donator/obj/clothing/ears.dmi differ diff --git a/modular_skyrat/master_files/icons/donator/obj/clothing/gloves.dmi b/modular_skyrat/master_files/icons/donator/obj/clothing/gloves.dmi index 62bfc6d5433351c..84df398954f9f03 100644 Binary files a/modular_skyrat/master_files/icons/donator/obj/clothing/gloves.dmi and b/modular_skyrat/master_files/icons/donator/obj/clothing/gloves.dmi differ diff --git a/modular_skyrat/master_files/icons/obj/ring.dmi b/modular_skyrat/master_files/icons/obj/ring.dmi index e13cc7cd23fe88d..e24f1fab4c93fde 100644 Binary files a/modular_skyrat/master_files/icons/obj/ring.dmi and b/modular_skyrat/master_files/icons/obj/ring.dmi differ diff --git a/modular_skyrat/modules/aesthetics/airlock/icons/airlocks/abductor/overlays.dmi b/modular_skyrat/modules/aesthetics/airlock/icons/airlocks/abductor/overlays.dmi index b93c50ad2e4b018..8f2dcf395c568e6 100644 Binary files a/modular_skyrat/modules/aesthetics/airlock/icons/airlocks/abductor/overlays.dmi and b/modular_skyrat/modules/aesthetics/airlock/icons/airlocks/abductor/overlays.dmi differ diff --git a/modular_skyrat/modules/aesthetics/airlock/icons/airlocks/centcom/overlays.dmi b/modular_skyrat/modules/aesthetics/airlock/icons/airlocks/centcom/overlays.dmi index 421aaa8fa419cce..81724f46d43d86f 100644 Binary files a/modular_skyrat/modules/aesthetics/airlock/icons/airlocks/centcom/overlays.dmi and b/modular_skyrat/modules/aesthetics/airlock/icons/airlocks/centcom/overlays.dmi differ diff --git a/modular_skyrat/modules/aesthetics/airlock/icons/airlocks/clockwork/overlays.dmi b/modular_skyrat/modules/aesthetics/airlock/icons/airlocks/clockwork/overlays.dmi index 33f3a03f522ab2b..6e18234daa12df8 100644 Binary files a/modular_skyrat/modules/aesthetics/airlock/icons/airlocks/clockwork/overlays.dmi and b/modular_skyrat/modules/aesthetics/airlock/icons/airlocks/clockwork/overlays.dmi differ diff --git a/modular_skyrat/modules/aesthetics/airlock/icons/airlocks/cult/runed/overlays.dmi b/modular_skyrat/modules/aesthetics/airlock/icons/airlocks/cult/runed/overlays.dmi index 9ae7976d568dc20..eae972b351b1e47 100644 Binary files a/modular_skyrat/modules/aesthetics/airlock/icons/airlocks/cult/runed/overlays.dmi and b/modular_skyrat/modules/aesthetics/airlock/icons/airlocks/cult/runed/overlays.dmi differ diff --git a/modular_skyrat/modules/aesthetics/airlock/icons/airlocks/cult/unruned/overlays.dmi b/modular_skyrat/modules/aesthetics/airlock/icons/airlocks/cult/unruned/overlays.dmi index 9eec60e4b52e38c..1a8ad61be76aa0c 100644 Binary files a/modular_skyrat/modules/aesthetics/airlock/icons/airlocks/cult/unruned/overlays.dmi and b/modular_skyrat/modules/aesthetics/airlock/icons/airlocks/cult/unruned/overlays.dmi differ diff --git a/modular_skyrat/modules/aesthetics/airlock/icons/airlocks/external/overlays.dmi b/modular_skyrat/modules/aesthetics/airlock/icons/airlocks/external/overlays.dmi index f72fdbdca044cd4..7c7b04692bfb531 100644 Binary files a/modular_skyrat/modules/aesthetics/airlock/icons/airlocks/external/overlays.dmi and b/modular_skyrat/modules/aesthetics/airlock/icons/airlocks/external/overlays.dmi differ diff --git a/modular_skyrat/modules/aesthetics/airlock/icons/airlocks/hatch/overlays.dmi b/modular_skyrat/modules/aesthetics/airlock/icons/airlocks/hatch/overlays.dmi index 30617c86496a2b7..4cfbd6fb8afc140 100644 Binary files a/modular_skyrat/modules/aesthetics/airlock/icons/airlocks/hatch/overlays.dmi and b/modular_skyrat/modules/aesthetics/airlock/icons/airlocks/hatch/overlays.dmi differ diff --git a/modular_skyrat/modules/aesthetics/airlock/icons/airlocks/highsec/overlays.dmi b/modular_skyrat/modules/aesthetics/airlock/icons/airlocks/highsec/overlays.dmi index c8bc014896438aa..f007e528c842e07 100644 Binary files a/modular_skyrat/modules/aesthetics/airlock/icons/airlocks/highsec/overlays.dmi and b/modular_skyrat/modules/aesthetics/airlock/icons/airlocks/highsec/overlays.dmi differ diff --git a/modular_skyrat/modules/aesthetics/airlock/icons/airlocks/multi_tile/glass_overlays.dmi b/modular_skyrat/modules/aesthetics/airlock/icons/airlocks/multi_tile/glass_overlays.dmi index cf1e7eea569eae3..d402ec613124ccb 100644 Binary files a/modular_skyrat/modules/aesthetics/airlock/icons/airlocks/multi_tile/glass_overlays.dmi and b/modular_skyrat/modules/aesthetics/airlock/icons/airlocks/multi_tile/glass_overlays.dmi differ diff --git a/modular_skyrat/modules/aesthetics/airlock/icons/airlocks/multi_tile/metal_overlays.dmi b/modular_skyrat/modules/aesthetics/airlock/icons/airlocks/multi_tile/metal_overlays.dmi index b1f39452c397a24..7903886dd5b6271 100644 Binary files a/modular_skyrat/modules/aesthetics/airlock/icons/airlocks/multi_tile/metal_overlays.dmi and b/modular_skyrat/modules/aesthetics/airlock/icons/airlocks/multi_tile/metal_overlays.dmi differ diff --git a/modular_skyrat/modules/aesthetics/airlock/icons/airlocks/shuttle/overlays.dmi b/modular_skyrat/modules/aesthetics/airlock/icons/airlocks/shuttle/overlays.dmi index 3b7831841bcdbed..732c43009bb09f2 100644 Binary files a/modular_skyrat/modules/aesthetics/airlock/icons/airlocks/shuttle/overlays.dmi and b/modular_skyrat/modules/aesthetics/airlock/icons/airlocks/shuttle/overlays.dmi differ diff --git a/modular_skyrat/modules/aesthetics/airlock/icons/airlocks/station/overlays.dmi b/modular_skyrat/modules/aesthetics/airlock/icons/airlocks/station/overlays.dmi index 04990c630cf82fb..334636b1b651677 100644 Binary files a/modular_skyrat/modules/aesthetics/airlock/icons/airlocks/station/overlays.dmi and b/modular_skyrat/modules/aesthetics/airlock/icons/airlocks/station/overlays.dmi differ diff --git a/modular_skyrat/modules/aesthetics/airlock/icons/airlocks/station2/overlays.dmi b/modular_skyrat/modules/aesthetics/airlock/icons/airlocks/station2/overlays.dmi index c253fc2ca66dbca..a1582586790d8d0 100644 Binary files a/modular_skyrat/modules/aesthetics/airlock/icons/airlocks/station2/overlays.dmi and b/modular_skyrat/modules/aesthetics/airlock/icons/airlocks/station2/overlays.dmi differ diff --git a/modular_skyrat/modules/aesthetics/airlock/icons/airlocks/survival/overlays.dmi b/modular_skyrat/modules/aesthetics/airlock/icons/airlocks/survival/overlays.dmi index a527b386b9c85f4..e1b1854eb35ffc5 100644 Binary files a/modular_skyrat/modules/aesthetics/airlock/icons/airlocks/survival/overlays.dmi and b/modular_skyrat/modules/aesthetics/airlock/icons/airlocks/survival/overlays.dmi differ diff --git a/modular_skyrat/modules/aesthetics/airlock/icons/airlocks/tram/tram_overlays.dmi b/modular_skyrat/modules/aesthetics/airlock/icons/airlocks/tram/tram_overlays.dmi index e154428fd0bbda6..99da4aec3bd3a57 100644 Binary files a/modular_skyrat/modules/aesthetics/airlock/icons/airlocks/tram/tram_overlays.dmi and b/modular_skyrat/modules/aesthetics/airlock/icons/airlocks/tram/tram_overlays.dmi differ diff --git a/modular_skyrat/modules/aesthetics/airlock/icons/airlocks/vault/overlays.dmi b/modular_skyrat/modules/aesthetics/airlock/icons/airlocks/vault/overlays.dmi index 222c146b3ff4d78..a3fe07f4e665037 100644 Binary files a/modular_skyrat/modules/aesthetics/airlock/icons/airlocks/vault/overlays.dmi and b/modular_skyrat/modules/aesthetics/airlock/icons/airlocks/vault/overlays.dmi differ diff --git a/modular_skyrat/modules/aesthetics/guns/code/guns.dm b/modular_skyrat/modules/aesthetics/guns/code/guns.dm index ac20f9f5db997bb..903f3b13bdb481a 100644 --- a/modular_skyrat/modules/aesthetics/guns/code/guns.dm +++ b/modular_skyrat/modules/aesthetics/guns/code/guns.dm @@ -86,14 +86,9 @@ inhand_x_dimension = 32 inhand_y_dimension = 32 -// de-overrides this particular gun, it uses the tg file /obj/item/gun/ballistic/shotgun/automatic/combat/compact - icon = 'icons/obj/weapons/guns/ballistic.dmi' - lefthand_file = 'icons/mob/inhands/weapons/64x_guns_left.dmi' - righthand_file = 'icons/mob/inhands/weapons/64x_guns_right.dmi' - inhand_x_dimension = 64 - inhand_y_dimension = 64 - worn_icon = null + name = "\improper Peacekeeper compact combat shotgun" + desc = "A tactical variant of the peacekeeper combat shotgun used by NT Raiding Parties and Space Marines." /obj/item/gun/grenadelauncher icon = 'modular_skyrat/modules/aesthetics/guns/icons/guns.dmi' diff --git a/modular_skyrat/modules/aesthetics/guns/icons/guns.dmi b/modular_skyrat/modules/aesthetics/guns/icons/guns.dmi index deb9cd5931e2321..14d5f4f19f5bbf2 100644 Binary files a/modular_skyrat/modules/aesthetics/guns/icons/guns.dmi and b/modular_skyrat/modules/aesthetics/guns/icons/guns.dmi differ diff --git a/modular_skyrat/modules/aesthetics/guns/icons/guns_back.dmi b/modular_skyrat/modules/aesthetics/guns/icons/guns_back.dmi index 471407b916e9ff7..8dc837913325940 100644 Binary files a/modular_skyrat/modules/aesthetics/guns/icons/guns_back.dmi and b/modular_skyrat/modules/aesthetics/guns/icons/guns_back.dmi differ diff --git a/modular_skyrat/modules/airlock_override/code/airlock_override.dm b/modular_skyrat/modules/airlock_override/code/airlock_override.dm index 4686120f8aa58e1..c6fea81df843c9a 100644 --- a/modular_skyrat/modules/airlock_override/code/airlock_override.dm +++ b/modular_skyrat/modules/airlock_override/code/airlock_override.dm @@ -103,8 +103,10 @@ ///When the signal is received of a changed security level, check if it's orange. /obj/machinery/door/airlock/check_security_level(datum/source, level) . = ..() - var/area/source_area = get_area(src) - if(!source_area.engineering_override_eligible) + if(!door_area.engineering_override_eligible) + return + + if(isnull(req_access) && isnull(req_one_access)) // no restrictions, no problem return if(level != SEC_LEVEL_ORANGE && GLOB.force_eng_override) @@ -158,30 +160,45 @@ GLOBAL_VAR_INIT(force_eng_override, FALSE) /obj/machinery/door/airlock/proc/force_eng_override(datum/source, status) SIGNAL_HANDLER + if(!door_area.engineering_override_eligible) + return + + if(isnull(req_access) && isnull(req_one_access)) // no restrictions, no problem + return + engineering_override = status if(!engineering_override && !fire_active) normalspeed = TRUE update_appearance() return - if(!door_area.engineering_override_eligible) - return - normalspeed = FALSE update_appearance() +/** + * Change the airlock's fire_active status, triggered by COMSIG_AREA_FIRE_CHANGED + * Activates fire status overlay and increases door speed. + * + * Arguments: + * * source - The /area with changed fire status + * * fire - the new fire status (TRUE/FALSE) + * +*/ /obj/machinery/door/airlock/proc/update_fire_status(datum/source, fire) SIGNAL_HANDLER + if(!door_area.engineering_override_eligible) + return + + if(isnull(req_access) && isnull(req_one_access)) // no restrictions, no problem + return + fire_active = fire if(!fire_active && !engineering_override) normalspeed = TRUE update_appearance() return - if(!door_area.engineering_override_eligible) - return - normalspeed = FALSE update_appearance() diff --git a/modular_skyrat/modules/ashwalkers/code/buildings/railroad.dm b/modular_skyrat/modules/ashwalkers/code/buildings/railroad.dm index fb30f860be11cbc..f75ea5248e2445a 100644 --- a/modular_skyrat/modules/ashwalkers/code/buildings/railroad.dm +++ b/modular_skyrat/modules/ashwalkers/code/buildings/railroad.dm @@ -74,7 +74,7 @@ /obj/vehicle/ridden/rail_cart/Initialize(mapload) . = ..() attach_trailer() - railoverlay = mutable_appearance(icon, "railoverlay", ABOVE_MOB_LAYER, src) + railoverlay = mutable_appearance(icon, "railoverlay", ABOVE_MOB_LAYER, src, ABOVE_GAME_PLANE) AddElement(/datum/element/ridable, /datum/component/riding/vehicle/rail_cart) create_storage(max_total_storage = 21, max_slots = 21) diff --git a/modular_skyrat/modules/blueshield/code/blueshield.dm b/modular_skyrat/modules/blueshield/code/blueshield.dm index ed0cd1e27307ebc..8a75d146a631317 100644 --- a/modular_skyrat/modules/blueshield/code/blueshield.dm +++ b/modular_skyrat/modules/blueshield/code/blueshield.dm @@ -59,7 +59,7 @@ messenger = /obj/item/storage/backpack/messenger/blueshield head = /obj/item/clothing/head/beret/blueshield box = /obj/item/storage/box/survival/security - belt = /obj/item/modular_computer/pda/security + belt = /obj/item/modular_computer/pda/blueshield id_trim = /datum/id_trim/job/blueshield @@ -68,3 +68,14 @@ head = /obj/item/clothing/head/helmet/space/plasmaman/blueshield uniform = /obj/item/clothing/under/plasmaman/blueshield + +/obj/item/modular_computer/pda/blueshield + name = "blueshield PDA" + greyscale_colors = "#2B356D#1E1E1E" + inserted_item = /obj/item/pen/red/security + starting_programs = list( + /datum/computer_file/program/records/security, + /datum/computer_file/program/crew_manifest, + /datum/computer_file/program/robocontrol, + /datum/computer_file/program/radar/lifeline, + ) diff --git a/modular_skyrat/modules/blueshield/code/closet.dm b/modular_skyrat/modules/blueshield/code/closet.dm index c6035e0dc37a0e5..476c6f266c49162 100644 --- a/modular_skyrat/modules/blueshield/code/closet.dm +++ b/modular_skyrat/modules/blueshield/code/closet.dm @@ -14,6 +14,17 @@ new /obj/item/clothing/suit/armor/vest/blueshield/jacket(src) new /obj/item/clothing/neck/mantle/bsmantle(src) +/obj/item/storage/box/glasseskit + name = "sunglasses kit" + desc = "Contain different type of sunglasses for different blueshield needs" + +/obj/item/storage/box/glasseskit/PopulateContents() //paradise stuff + new /obj/item/clothing/glasses/hud/diagnostic/sunglasses(src) + new /obj/item/clothing/glasses/hud/health/sunglasses(src) + new /obj/item/clothing/glasses/hud/security/sunglasses(src) + new /obj/item/clothing/glasses/sunglasses/chemical(src) + new /obj/item/clothing/glasses/hud/gun_permit/sunglasses(src) + /obj/structure/closet/secure_closet/blueshield name = "blueshield's locker" icon_state = "bs" @@ -27,8 +38,9 @@ new /obj/item/grenade/flashbang(src) new /obj/item/assembly/flash/handheld(src) new /obj/item/restraints/handcuffs(src) - new /obj/item/clothing/glasses/hud/security/sunglasses(src) new /obj/item/storage/medkit/tactical/blueshield(src) - new /obj/item/storage/toolbox/guncase/skyrat/xhihao_large_case/bogseo(src) + new /obj/item/choice_beacon/blueshield(src) new /obj/item/storage/bag/garment/blueshield(src) new /obj/item/mod/control/pre_equipped/blueshield(src) + new /obj/item/storage/box/glasseskit(src) + new /obj/item/storage/medkit/brute(src) diff --git a/modular_skyrat/modules/blueshield/code/energy_resholver.dm b/modular_skyrat/modules/blueshield/code/energy_resholver.dm new file mode 100644 index 000000000000000..1e0fd499e16abb8 --- /dev/null +++ b/modular_skyrat/modules/blueshield/code/energy_resholver.dm @@ -0,0 +1,63 @@ +//Blueshield Energy Revolver +//Icon and such by @EspeciallyStrange 'Calvin' + +/obj/item/gun/energy/e_gun/blueshield + name = "energy revolver" + desc = "An energy weapon fitted with self recharging-cells. Feels somewhat heavy to carry and would certainly hurt to get whacked by." + icon = 'modular_skyrat/modules/blueshield/icons/energy.dmi' + icon_state = "blackgrip" + lefthand_file = 'modular_skyrat/modules/blueshield/icons/guns_lefthand.dmi' + righthand_file = 'modular_skyrat/modules/blueshield/icons/guns_righthand.dmi' + charge_delay = 9 + can_charge = FALSE //Doesn't work like that son + selfcharge = 1 + cell_type = /obj/item/stock_parts/cell/hos_gun + w_class = WEIGHT_CLASS_NORMAL //Fits in bag! + force = 15 //smash sulls in + throwforce = 15 + ammo_type = list(/obj/item/ammo_casing/energy/disabler/hos, /obj/item/ammo_casing/energy/laser/hellfire) + ammo_x_offset = 1 + +/obj/item/gun/energy/e_gun/blueshield/specop + name = "tactical energy revolver" + desc = "An advanced model of the energy revolver with all of it's benefit and a much more powerful phase emitter." + icon_state = "redgrip" + ammo_type = list(/obj/item/ammo_casing/energy/electrode/spec, /obj/item/ammo_casing/energy/laser/hellfire) +//Alternative for people who prefers energy carbine, remain inclusive and all. +/obj/item/gun/energy/e_gun/stun/blueshield + name = "defender energy carbine" + desc = "Military issue energy gun, is able to fire stun rounds. Extremely slow recharge" + ammo_x_offset = 2 + ammo_type = list(/obj/item/ammo_casing/energy/electrode/blueshield, /obj/item/ammo_casing/energy/laser/scatter/disabler, /obj/item/ammo_casing/energy/lasergun/blueshield) + charge_delay = 14 + can_charge = TRUE //In case you aren't charging fast enough, the recharge is meant to be slow on purpose + selfcharge = 1 + +//Choice Beacon for blueshield + +/obj/item/choice_beacon/blueshield + name = "blueshield weapon beacon" + desc = "A single use beacon to deliver a weapon of your choice. Please only call this in your office" + company_source = "Sol Security Solution" + company_message = span_bold("Supply Pod incoming please stand by") + +/obj/item/choice_beacon/blueshield/generate_display_names() + var/static/list/selectable_gun_types = list( + "Energy Revolver" = /obj/item/gun/energy/e_gun/blueshield, + "Energy Carbine" = /obj/item/gun/energy/e_gun/stun/blueshield, + ".585 SMG" = /obj/item/storage/toolbox/guncase/skyrat/xhihao_large_case/bogseo //This can obviously be replaced out with any gun of your choice for future coder + ) + + return selectable_gun_types + +//Blueshield Energy +/obj/item/ammo_casing/energy/electrode/blueshield + e_cost = LASER_SHOTS(6, STANDARD_CELL_CHARGE) + projectile_type = /obj/projectile/energy/electrode/blueshield + +/obj/item/ammo_casing/energy/lasergun/blueshield + e_cost = LASER_SHOTS(30, STANDARD_CELL_CHARGE) + +/obj/projectile/energy/electrode/blueshield + stamina = 55 //Still a 3 shot down but much more safe to have + diff --git a/modular_skyrat/modules/blueshield/icons/40x32.dmi b/modular_skyrat/modules/blueshield/icons/40x32.dmi new file mode 100644 index 000000000000000..a2f3026bcaec264 Binary files /dev/null and b/modular_skyrat/modules/blueshield/icons/40x32.dmi differ diff --git a/modular_skyrat/modules/blueshield/icons/energy.dmi b/modular_skyrat/modules/blueshield/icons/energy.dmi index 85194b408546f9b..3de0a7d5198862f 100644 Binary files a/modular_skyrat/modules/blueshield/icons/energy.dmi and b/modular_skyrat/modules/blueshield/icons/energy.dmi differ diff --git a/modular_skyrat/modules/blueshield/icons/guns_lefthand.dmi b/modular_skyrat/modules/blueshield/icons/guns_lefthand.dmi index 73dc7d7dd3f6091..a64bbfbf936d394 100644 Binary files a/modular_skyrat/modules/blueshield/icons/guns_lefthand.dmi and b/modular_skyrat/modules/blueshield/icons/guns_lefthand.dmi differ diff --git a/modular_skyrat/modules/blueshield/icons/guns_righthand.dmi b/modular_skyrat/modules/blueshield/icons/guns_righthand.dmi index f3e932f21868739..10c69ef06d31e42 100644 Binary files a/modular_skyrat/modules/blueshield/icons/guns_righthand.dmi and b/modular_skyrat/modules/blueshield/icons/guns_righthand.dmi differ diff --git a/modular_skyrat/modules/bodyparts/code/moth_bodyparts.dm b/modular_skyrat/modules/bodyparts/code/moth_bodyparts.dm index aab60d23281603e..3eab65218be4882 100644 --- a/modular_skyrat/modules/bodyparts/code/moth_bodyparts.dm +++ b/modular_skyrat/modules/bodyparts/code/moth_bodyparts.dm @@ -14,6 +14,9 @@ is_dimorphic = TRUE wing_types = list(/obj/item/organ/external/wings/functional/moth/megamoth, /obj/item/organ/external/wings/functional/moth/mothra) +/obj/item/bodypart/chest/moth/get_butt_sprite() + return BUTT_SPRITE_FUZZY + /obj/item/bodypart/arm/left/moth icon = BODYPART_ICON_MOTH icon_greyscale = BODYPART_ICON_MOTH 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 010e8707232cad7..e8688a96b1a19a4 100644 --- a/modular_skyrat/modules/customization/modules/clothing/~donator/donator_clothing.dm +++ b/modular_skyrat/modules/customization/modules/clothing/~donator/donator_clothing.dm @@ -1454,10 +1454,25 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/structure/sign/poster/contraband/korpstech, 32) /obj/item/clothing/gloves/ring/hypno/nuke name = "suspiciously glossy ring" desc = "This ring oozes with an assertive edge as sharp light bends along the smooth, black bronze. Like the finger that wears it, an exceptional amount of polish repels nearly all the light that glances along its surface. If you look closer, a slight golden hue indicates the precious metals inside the alloy." - icon = 'modular_skyrat/master_files/icons/obj/ring.dmi' + icon = 'modular_skyrat/master_files/icons/donator/obj/clothing/gloves.dmi' + worn_icon = 'modular_skyrat/master_files/icons/donator/mob/clothing/hands.dmi' icon_state = "ringblack" + worn_icon_state = "ringblack" + lefthand_file = null + righthand_file = null spans = list("glossy") +/obj/item/clothing/ears/kinky_headphones/nuke + name = "suspiciously glossy headphones" + desc = "Black metalic headphones with a glossy finish. The soft rubber cushions are comftorable and form fitting" + icon_state = "kinkphones_black_off" + base_icon_state = "kinkphones" + icon = 'modular_skyrat/master_files/icons/donator/obj/clothing/ears.dmi' + worn_icon = 'modular_skyrat/master_files/icons/donator/mob/clothing/ears.dmi' + inhand_icon_state = null + current_kinkphones_color = "black" + color_changed = TRUE + //reward for SomeRandomOwl /obj/item/clothing/head/costume/strigihat name = "starry witch hat" diff --git a/modular_skyrat/modules/customization/modules/mob/living/carbon/human/species/unathi.dm b/modular_skyrat/modules/customization/modules/mob/living/carbon/human/species/unathi.dm index ccbb0dd1416cfae..bbf7f91b08b38c1 100644 --- a/modular_skyrat/modules/customization/modules/mob/living/carbon/human/species/unathi.dm +++ b/modular_skyrat/modules/customization/modules/mob/living/carbon/human/species/unathi.dm @@ -13,7 +13,6 @@ payday_modifier = 1.0 changesource_flags = MIRROR_BADMIN | WABBAJACK | MIRROR_MAGIC | MIRROR_PRIDE | ERT_SPAWN | RACE_SWAP | SLIME_EXTRACT examine_limb_id = SPECIES_LIZARD - ass_image = 'icons/ass/asslizard.png' bodypart_overrides = list( BODY_ZONE_HEAD = /obj/item/bodypart/head/lizard, diff --git a/modular_skyrat/modules/deforest_medical_items/code/chemicals/demoneye.dm b/modular_skyrat/modules/deforest_medical_items/code/chemicals/demoneye.dm index c3d7076845c4408..783eb2b05635ccd 100644 --- a/modular_skyrat/modules/deforest_medical_items/code/chemicals/demoneye.dm +++ b/modular_skyrat/modules/deforest_medical_items/code/chemicals/demoneye.dm @@ -29,6 +29,8 @@ overdose_threshold = 15 chemical_flags = REAGENT_CAN_BE_SYNTHESIZED addiction_types = list(/datum/addiction/stimulants = 15) + + metabolized_traits = list(TRAIT_UNNATURAL_RED_GLOWY_EYES, TRAIT_NOSOFTCRIT, TRAIT_NOHARDCRIT, TRAIT_FEARLESS, TRAIT_ANALGESIA) /// How much time has the drug been in them? var/constant_dose_time = 0 /// What the original color of the user's left eye is @@ -38,14 +40,6 @@ /datum/reagent/drug/demoneye/on_mob_metabolize(mob/living/carbon/human/our_guy) . = ..() - - ADD_TRAIT(our_guy, TRAIT_UNNATURAL_RED_GLOWY_EYES, TRAIT_NARCOTICS) - // IM FUCKIN INVINCIBLE - ADD_TRAIT(our_guy, TRAIT_NOSOFTCRIT, TRAIT_NARCOTICS) - ADD_TRAIT(our_guy, TRAIT_NOHARDCRIT, TRAIT_NARCOTICS) - ADD_TRAIT(our_guy, TRAIT_FEARLESS, TRAIT_NARCOTICS) - ADD_TRAIT(our_guy, TRAIT_NUMBED, TRAIT_NARCOTICS) - user_left_eye_color = our_guy.eye_color_left user_right_eye_color = our_guy.eye_color_right @@ -73,13 +67,6 @@ /datum/reagent/drug/demoneye/on_mob_end_metabolize(mob/living/carbon/human/our_guy) . = ..() - - REMOVE_TRAIT(our_guy, TRAIT_UNNATURAL_RED_GLOWY_EYES, TRAIT_NARCOTICS) - REMOVE_TRAIT(our_guy, TRAIT_NOSOFTCRIT, TRAIT_NARCOTICS) - REMOVE_TRAIT(our_guy, TRAIT_NOHARDCRIT, TRAIT_NARCOTICS) - REMOVE_TRAIT(our_guy, TRAIT_FEARLESS, TRAIT_NARCOTICS) - REMOVE_TRAIT(our_guy, TRAIT_NUMBED, TRAIT_NARCOTICS) - our_guy.eye_color_left = user_left_eye_color our_guy.eye_color_right = user_right_eye_color our_guy.update_body() diff --git a/modular_skyrat/modules/deforest_medical_items/code/healing_stack_items.dm b/modular_skyrat/modules/deforest_medical_items/code/healing_stack_items.dm index e60b6b47d35cd40..cedead2aa699c90 100644 --- a/modular_skyrat/modules/deforest_medical_items/code/healing_stack_items.dm +++ b/modular_skyrat/modules/deforest_medical_items/code/healing_stack_items.dm @@ -72,7 +72,7 @@ user.visible_message(span_green("[user] applies [src] to [patient]'s [limb.plaintext_zone]."), span_green("You bandage the wounds on [user == patient ? "your" : "[patient]'s"] [limb.plaintext_zone].")) playsound(patient, treatment_sound, 50, TRUE) woundies.remove_wound() - if(!HAS_TRAIT(patient, TRAIT_NUMBED)) + if(!HAS_TRAIT(patient, TRAIT_ANALGESIA)) patient.emote("scream") to_chat(patient, span_userdanger("Your [limb.plaintext_zone] burns like hell as the wounds on it are rapidly healed, fuck!")) patient.add_mood_event("severe_surgery", /datum/mood_event/rapid_wound_healing) diff --git a/modular_skyrat/modules/emotes/code/additionalemotes/turf_list.dm b/modular_skyrat/modules/emotes/code/additionalemotes/turf_list.dm index 569c1d7640342d2..606f0fc45d635f7 100644 --- a/modular_skyrat/modules/emotes/code/additionalemotes/turf_list.dm +++ b/modular_skyrat/modules/emotes/code/additionalemotes/turf_list.dm @@ -108,7 +108,13 @@ icon = 'modular_skyrat/master_files/icons/effects/turf_effects_64.dmi' icon_state = "tails" pixel_x = -16 //correcting the offset for 64 - var/mutable_appearance/overlay = mutable_appearance('modular_skyrat/master_files/icons/effects/turf_effects_64.dmi', "tails_top", EXTRA_ABOVE_MOB_LAYER, src) + var/mutable_appearance/overlay = mutable_appearance( + 'modular_skyrat/master_files/icons/effects/turf_effects_64.dmi', + "tails_top", + EXTRA_ABOVE_MOB_LAYER, + src, + ABOVE_GAME_PLANE, + ) overlay.appearance_flags = TILE_BOUND|PIXEL_SCALE|KEEP_TOGETHER src.add_overlay(overlay) playsound(get_turf(src), 'sound/weapons/thudswoosh.ogg', 25, TRUE) @@ -119,7 +125,13 @@ icon = 'modular_skyrat/master_files/icons/effects/turf_effects_64.dmi' icon_state = "naga" pixel_x = -16 - var/mutable_appearance/overlay = mutable_appearance('modular_skyrat/master_files/icons/effects/turf_effects_64.dmi', "naga_top", EXTRA_ABOVE_MOB_LAYER, src) + var/mutable_appearance/overlay = mutable_appearance( + 'modular_skyrat/master_files/icons/effects/turf_effects_64.dmi', + "naga_top", + EXTRA_ABOVE_MOB_LAYER, + src, + ABOVE_GAME_PLANE, + ) overlay.appearance_flags = TILE_BOUND|PIXEL_SCALE|KEEP_TOGETHER src.add_overlay(overlay) playsound(get_turf(src), 'modular_skyrat/modules/emotes/sound/emotes/hiss.ogg', 25, TRUE) diff --git a/modular_skyrat/modules/ghostcafe/code/ghost_role_spawners.dm b/modular_skyrat/modules/ghostcafe/code/ghost_role_spawners.dm index 1f95477ecb3fbfc..e5d8fb275c67537 100644 --- a/modular_skyrat/modules/ghostcafe/code/ghost_role_spawners.dm +++ b/modular_skyrat/modules/ghostcafe/code/ghost_role_spawners.dm @@ -50,6 +50,7 @@ flavour_text = "You are off-duty and have decided to visit your favourite cafe. Enjoy yourself." random_appearance = FALSE loadout_enabled = TRUE + quirks_enabled = TRUE /obj/effect/mob_spawn/ghost_role/human/ghostcafe/special(mob/living/carbon/human/new_spawn) . = ..() @@ -62,7 +63,6 @@ ADD_TRAIT(new_spawn, TRAIT_FREE_GHOST, TRAIT_GHOSTROLE) to_chat(new_spawn,span_warning("Ghosting is free!")) var/datum/action/toggle_dead_chat_mob/D = new(new_spawn) - SSquirks.AssignQuirks(new_spawn, new_spawn.client, TRUE, TRUE, null, FALSE, new_spawn) D.Grant(new_spawn) /datum/outfit/ghostcafe diff --git a/modular_skyrat/modules/liquids/code/liquid_systems/liquid_effect.dm b/modular_skyrat/modules/liquids/code/liquid_systems/liquid_effect.dm index e3bb79a1f1f2883..bfd5893a88601b9 100644 --- a/modular_skyrat/modules/liquids/code/liquid_systems/liquid_effect.dm +++ b/modular_skyrat/modules/liquids/code/liquid_systems/liquid_effect.dm @@ -224,7 +224,7 @@ /obj/effect/abstract/liquid_turf/proc/make_state_layer(state, has_top) PRIVATE_PROC(TRUE) - . = list(make_liquid_overlay("stage[state]_bottom", ABOVE_MOB_LAYER)) + . = list(make_liquid_overlay("stage[state]_bottom", ABOVE_MOB_LAYER, ABOVE_GAME_PLANE)) if(!has_top) return 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 5dfd42bca8fe404..5a44e21b830032d 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 @@ -649,6 +649,11 @@ item_path = /obj/item/clothing/gloves/ring/hypno/nuke ckeywhitelist = list("sonicgotnuked") +/datum/loadout_item/ears/kinkphone_nuke + name = "Suspiciously Glossy Headphones" + item_path = /obj/item/clothing/ears/kinky_headphones/nuke + ckeywhitelist = list("sonicgotnuked") + /datum/loadout_item/head/somerandomowl name = "Starry Witch Hat" item_path = /obj/item/clothing/head/costume/strigihat diff --git a/modular_skyrat/modules/mapping/code/pool.dm b/modular_skyrat/modules/mapping/code/pool.dm index 4d1a7095887fd8e..44ef0821fed5eac 100644 --- a/modular_skyrat/modules/mapping/code/pool.dm +++ b/modular_skyrat/modules/mapping/code/pool.dm @@ -15,6 +15,7 @@ mouse_opacity = MOUSE_OPACITY_TRANSPARENT anchored = TRUE layer = ABOVE_MOB_LAYER + plane = ABOVE_GAME_PLANE /obj/effect/overlay/water/top icon_state = "top" diff --git a/modular_skyrat/modules/medical/code/cargo/packs.dm b/modular_skyrat/modules/medical/code/cargo/packs.dm index a7a84c600f4ded0..58259bc4568da6d 100644 --- a/modular_skyrat/modules/medical/code/cargo/packs.dm +++ b/modular_skyrat/modules/medical/code/cargo/packs.dm @@ -1,8 +1,8 @@ /datum/supply_pack/science/synthetic_burns name = "Synthetic Burns Kit" - desc = "Contains a bottle of pre-chilled hercuri and a bottle of dinitrogen plasmide, perfect for treating synthetic burns!" + desc = "Contains bottles of pre-chilled hercuri and dinitrogen plasmide, perfect for treating synthetic burns!" cost = CARGO_CRATE_VALUE * 2.5 - contains = list(/obj/item/reagent_containers/spray/hercuri/chilled = 1, /obj/item/reagent_containers/spray/dinitrogen_plasmide = 1) + contains = list(/obj/item/reagent_containers/spray/hercuri/chilled = 3, /obj/item/reagent_containers/spray/dinitrogen_plasmide = 3) crate_name = "chilled hercuri crate" access_view = FALSE @@ -34,3 +34,21 @@ access_view = FALSE access = FALSE access_any = FALSE + +/datum/supply_pack/science/synth_medkits + name = "Mechanical Repair Kits" + desc = "Contains a few low-grade portable synthetic medkits, useful for distributing to the crew." + cost = CARGO_CRATE_VALUE * 4.5 // same as treatment kits + contains = list(/obj/item/storage/medkit/mechanical/regular = 4) + + crate_name = "synthetic repair kits crate" + + access_view = FALSE + access = FALSE + access_any = FALSE + +/datum/supply_pack/goody/mechanical_repair_kit_single + name = "Mechanical Repair Kit Single-Pack" + desc = "A single mechanical repair kit, fit for fixing most robotic injuries." + cost = PAYCHECK_CREW * 3 + contains = list(/obj/item/storage/medkit/mechanical/regular) diff --git a/modular_skyrat/modules/medical/code/medical_lefthand.dmi b/modular_skyrat/modules/medical/code/medical_lefthand.dmi new file mode 100644 index 000000000000000..5c5e34a5e68d6e5 Binary files /dev/null and b/modular_skyrat/modules/medical/code/medical_lefthand.dmi differ diff --git a/modular_skyrat/modules/medical/code/medical_righthand.dmi b/modular_skyrat/modules/medical/code/medical_righthand.dmi new file mode 100644 index 000000000000000..569d3665f5c11bb Binary files /dev/null and b/modular_skyrat/modules/medical/code/medical_righthand.dmi differ diff --git a/modular_skyrat/modules/medical/code/medkit.dm b/modular_skyrat/modules/medical/code/medkit.dm index a641932619d7060..fe496ea8f767878 100644 --- a/modular_skyrat/modules/medical/code/medkit.dm +++ b/modular_skyrat/modules/medical/code/medkit.dm @@ -178,3 +178,81 @@ /obj/item/storage/backpack/duffelbag/synth_treatment_kit/trauma/advanced/unzipped zipped_up = FALSE + +// basetype, do not use +/obj/item/storage/medkit/mechanical + name = "mechanical medkit" + desc = "For those mechanical booboos." + + icon = 'modular_skyrat/modules/medical/code/medkit.dmi' + icon_state = "medkit_mechanical" + inhand_icon_state = "medkit_mechanical" + lefthand_file = 'modular_skyrat/modules/medical/code/medical_lefthand.dmi' + righthand_file = 'modular_skyrat/modules/medical/code/medical_righthand.dmi' + +/obj/item/storage/medkit/mechanical/Initialize(mapload) + . = ..() + + var/static/list/list_of_everything_mechanical_medkits_can_hold = list_of_everything_medkits_can_hold + list( + /obj/item/stack/cable_coil, + /obj/item/crowbar, + /obj/item/screwdriver, + /obj/item/wrench, + /obj/item/weldingtool, + /obj/item/wirecutters, + /obj/item/multitool, + /obj/item/plunger, + /obj/item/clothing/head/utility/welding, + /obj/item/clothing/glasses/welding, + ) + var/static/list/exception_cache = typecacheof( + /obj/item/clothing/head/utility/welding + ) + + atom_storage.set_holdable(list_of_everything_mechanical_medkits_can_hold) + LAZYINITLIST(atom_storage.exception_hold) + atom_storage.exception_hold = atom_storage.exception_hold + exception_cache + +/obj/item/storage/medkit/mechanical/regular + name = "mechanical repair kit" + desc = "Used to treat injuries sustained by mechanical limbs/lifeforms." + +/obj/item/storage/medkit/mechanical/regular/PopulateContents() + if(empty) + return + var/static/items_inside = list( + /obj/item/stack/medical/gauze = 1, + /obj/item/stack/cable_coil = 2, + /obj/item/weldingtool/mini = 1, + /obj/item/clothing/head/utility/welding = 1, + /obj/item/reagent_containers/hypospray/medipen = 1, // treats electrical damage + /obj/item/healthanalyzer/simple = 1, + ) + generate_items_inside(items_inside,src) + +/obj/item/storage/medkit/mechanical/roboticist + name = "intensive repair kit" + desc = "A high capacity repair kit for roboticists, used to treat injuries sustained by mechanical lifeforms." + icon_state = "medkit_robo" + +/obj/item/storage/medkit/mechanical/roboticist/Initialize(mapload) + . = ..() + atom_storage.max_specific_storage = WEIGHT_CLASS_NORMAL //holds the same equipment as a medibelt + atom_storage.max_slots = 12 + atom_storage.max_total_storage = 24 + +/obj/item/storage/medkit/mechanical/roboticist/PopulateContents() + if(empty) + return + var/static/items_inside = list( + /obj/item/stack/medical/gauze = 2, + /obj/item/stack/cable_coil = 4, + /obj/item/storage/pill_bottle/nanite_slurry = 1, + /obj/item/storage/pill_bottle/system_cleaner = 1, + /obj/item/reagent_containers/spray/hercuri/chilled = 1, + /obj/item/reagent_containers/spray/dinitrogen_plasmide = 1, + /obj/item/reagent_containers/hypospray/medipen = 1, // treats electrical damage + /obj/item/healthanalyzer/simple = 1, + /obj/item/healthanalyzer/no_medibot = 1, // no welding tool since we assume you already have one + ) + generate_items_inside(items_inside,src) diff --git a/modular_skyrat/modules/medical/code/medkit.dmi b/modular_skyrat/modules/medical/code/medkit.dmi new file mode 100644 index 000000000000000..451d8587d14693f Binary files /dev/null and b/modular_skyrat/modules/medical/code/medkit.dmi differ diff --git a/modular_skyrat/modules/medical/code/smartdarts.dm b/modular_skyrat/modules/medical/code/smartdarts.dm index 326f8382f415cdd..684db388d9f4166 100644 --- a/modular_skyrat/modules/medical/code/smartdarts.dm +++ b/modular_skyrat/modules/medical/code/smartdarts.dm @@ -74,6 +74,16 @@ harmful = FALSE projectile_type = /obj/projectile/bullet/dart/syringe/dart +//Handles loading smartdarts into regular syringeguns +/obj/item/ammo_casing/syringegun/newshot(alternative_ammo) + if(!loaded_projectile) + if(!isnull(alternative_ammo)) + loaded_projectile = new alternative_ammo(src, src) + harmful = FALSE + else + loaded_projectile = new projectile_type(src, src) + harmful = TRUE + /obj/projectile/bullet/dart/syringe/dart name = "SmartDart" damage = 0 diff --git a/modular_skyrat/modules/modular_items/lewd_items/code/lewd_chemistry/reagents/cum.dm b/modular_skyrat/modules/modular_items/lewd_items/code/lewd_chemistry/reagents/cum.dm index d531df13ac6f01e..1aec43a53a4a327 100644 --- a/modular_skyrat/modules/modular_items/lewd_items/code/lewd_chemistry/reagents/cum.dm +++ b/modular_skyrat/modules/modular_items/lewd_items/code/lewd_chemistry/reagents/cum.dm @@ -35,9 +35,3 @@ icon_state ="shotglasscream" name = "glass of cum" desc = "O-oh, my...~" - -/datum/chemical_reaction/cum - results = list(/datum/reagent/consumable/cum = 5) - required_reagents = list(/datum/reagent/blood = 2, /datum/reagent/consumable/milk = 2, /datum/reagent/consumable/salt = 1) // Iiiinteresting... - mix_message = "The mixture turns into a gooey, musky white liquid..." - erp_reaction = TRUE diff --git a/modular_skyrat/modules/modular_items/lewd_items/code/lewd_machinery/lustwish.dm b/modular_skyrat/modules/modular_items/lewd_items/code/lewd_machinery/lustwish.dm index 29a0e99da5feaa7..5eb71d6d23e0f10 100644 --- a/modular_skyrat/modules/modular_items/lewd_items/code/lewd_machinery/lustwish.dm +++ b/modular_skyrat/modules/modular_items/lewd_items/code/lewd_machinery/lustwish.dm @@ -9,7 +9,7 @@ ///Has the discount card been used on the vending machine? var/card_used = FALSE product_ads = "Try me!;Kinky!;Lewd and fun!;Hey you, yeah you... wanna take a look at my collection?;Come on, take a look!;Remember, always adhere to Nanotrasen corporate policy!;Don't forget to use protection!" - vend_reply = "Enjoy!;We're glad to satisfy your desires!" + vend_reply = "We're glad to satisfy your desires!" //STUFF SOLD HERE// product_categories = list( diff --git a/modular_skyrat/modules/modular_reagents/code/reagents/medicine.dm b/modular_skyrat/modules/modular_reagents/code/reagents/medicine.dm index d84de0741892a81..627ccd1897aeffa 100644 --- a/modular_skyrat/modules/modular_reagents/code/reagents/medicine.dm +++ b/modular_skyrat/modules/modular_reagents/code/reagents/medicine.dm @@ -7,17 +7,17 @@ overdose_threshold = 20 ph = 6.09 chemical_flags = REAGENT_CAN_BE_SYNTHESIZED - addiction_types = list(/datum/addiction/opioids = 20) + metabolized_traits = list(TRAIT_ANALGESIA) inverse_chem_val = 0.55 inverse_chem = /datum/reagent/inverse/lidocaine + metabolized_traits = list(TRAIT_ANALGESIA) + /datum/reagent/medicine/lidocaine/on_mob_metabolize(mob/living/metabolizer) . = ..() - ADD_TRAIT(metabolizer, TRAIT_NUMBED, REF(src)) metabolizer.throw_alert("numbed", /atom/movable/screen/alert/numbed) /datum/reagent/medicine/lidocaine/on_mob_end_metabolize(mob/living/metabolizer) - REMOVE_TRAIT(metabolizer, TRAIT_NUMBED, REF(src)) metabolizer.clear_alert("numbed") return ..() diff --git a/modular_skyrat/modules/modular_weapons/code/company_and_or_faction_based/trappiste_fabriek/gunsets.dm b/modular_skyrat/modules/modular_weapons/code/company_and_or_faction_based/trappiste_fabriek/gunsets.dm index 8c96bc5a563d681..8343254013d06ba 100644 --- a/modular_skyrat/modules/modular_weapons/code/company_and_or_faction_based/trappiste_fabriek/gunsets.dm +++ b/modular_skyrat/modules/modular_weapons/code/company_and_or_faction_based/trappiste_fabriek/gunsets.dm @@ -25,6 +25,12 @@ weapon_to_spawn = /obj/item/gun/ballistic/automatic/pistol/sol/no_mag extra_to_spawn = /obj/item/ammo_box/magazine/c35sol_pistol +/obj/item/storage/toolbox/guncase/skyrat/pistol/trappiste_small_case/eland + name = "Trappiste 'Eland' gunset" + + weapon_to_spawn = /obj/item/gun/ballistic/revolver/sol + extra_to_spawn = /obj/item/ammo_box/c35sol/incapacitator + // Gunset for the Skild heavy pistol /obj/item/storage/toolbox/guncase/skyrat/pistol/trappiste_small_case/skild diff --git a/modular_skyrat/modules/mounted_machine_gun/code/mounted_machine_gun.dm b/modular_skyrat/modules/mounted_machine_gun/code/mounted_machine_gun.dm index a2d01ca064b17d2..d631246666c9928 100644 --- a/modular_skyrat/modules/mounted_machine_gun/code/mounted_machine_gun.dm +++ b/modular_skyrat/modules/mounted_machine_gun/code/mounted_machine_gun.dm @@ -15,6 +15,7 @@ buckle_lying = 0 SET_BASE_PIXEL(-8, -8) layer = ABOVE_MOB_LAYER + plane = ABOVE_GAME_PLANE /// The extra range that this turret gives regarding viewrange. var/view_range = 2.5 /// Sound to play when overheated @@ -163,6 +164,7 @@ register_user(user_to_buckle) layer = ABOVE_MOB_LAYER + plane = ABOVE_GAME_PLANE setDir(SOUTH) playsound(src,'sound/mecha/mechmove01.ogg', 50, TRUE) set_anchored(TRUE) @@ -421,6 +423,7 @@ user.pixel_y = -8 if(EAST) layer = ABOVE_MOB_LAYER + plane = ABOVE_GAME_PLANE user.pixel_x = -22 user.pixel_y = 0 if(SOUTHEAST) @@ -430,6 +433,7 @@ user.pixel_y = 14 if(SOUTH) layer = ABOVE_MOB_LAYER + plane = ABOVE_GAME_PLANE user.pixel_x = 0 user.pixel_y = 22 if(SOUTHWEST) @@ -439,6 +443,7 @@ user.pixel_y = 14 if(WEST) layer = ABOVE_MOB_LAYER + plane = ABOVE_GAME_PLANE user.pixel_x = 22 user.pixel_y = 0 if(NORTHWEST) diff --git a/modular_skyrat/modules/primitive_cooking_additions/code/cookware.dm b/modular_skyrat/modules/primitive_cooking_additions/code/cookware.dm index 6b90c469c1a2b59..aa96e10b062267e 100644 --- a/modular_skyrat/modules/primitive_cooking_additions/code/cookware.dm +++ b/modular_skyrat/modules/primitive_cooking_additions/code/cookware.dm @@ -1,53 +1,33 @@ /obj/item/reagent_containers/cup/soup_pot/material icon = 'modular_skyrat/modules/primitive_cooking_additions/icons/cookware.dmi' - custom_materials = null // We're going to apply custom materials when this baby is actually made material_flags = MATERIAL_EFFECTS | MATERIAL_ADD_PREFIX | MATERIAL_COLOR | MATERIAL_AFFECT_STATISTICS // A few random preset types as well /obj/item/reagent_containers/cup/soup_pot/material/fake_copper - -/obj/item/reagent_containers/cup/soup_pot/material/fake_copper/Initialize(mapload) - . = ..() - set_custom_materials(list(GET_MATERIAL_REF(/datum/material/copporcitite) = SHEET_MATERIAL_AMOUNT)) + custom_materials = list(/datum/material/copporcitite=SHEET_MATERIAL_AMOUNT) /obj/item/reagent_containers/cup/soup_pot/material/fake_brass - -/obj/item/reagent_containers/cup/soup_pot/material/fake_brass/Initialize(mapload) - . = ..() - set_custom_materials(list(GET_MATERIAL_REF(/datum/material/brussite) = SHEET_MATERIAL_AMOUNT)) + custom_materials = list(/datum/material/brussite=SHEET_MATERIAL_AMOUNT) /obj/item/reagent_containers/cup/soup_pot/material/fake_tin - -/obj/item/reagent_containers/cup/soup_pot/material/fake_tin/Initialize(mapload) - . = ..() - set_custom_materials(list(GET_MATERIAL_REF(/datum/material/tinumium) = SHEET_MATERIAL_AMOUNT)) + custom_materials = list(/datum/material/tinumium=SHEET_MATERIAL_AMOUNT) // Oven Trays /obj/item/plate/oven_tray/material desc = "Time to bake hardtack!" icon = 'modular_skyrat/modules/primitive_cooking_additions/icons/cookware.dmi' - custom_materials = null // We're going to apply custom materials when this baby is actually made material_flags = MATERIAL_EFFECTS | MATERIAL_ADD_PREFIX | MATERIAL_COLOR | MATERIAL_AFFECT_STATISTICS fragile = FALSE // A few random preset types as well /obj/item/plate/oven_tray/material/fake_copper - -/obj/item/plate/oven_tray/material/fake_copper/Initialize(mapload) - . = ..() - set_custom_materials(list(GET_MATERIAL_REF(/datum/material/copporcitite) = SHEET_MATERIAL_AMOUNT)) + custom_materials = list(/datum/material/copporcitite=SHEET_MATERIAL_AMOUNT) /obj/item/plate/oven_tray/material/fake_brass - -/obj/item/plate/oven_tray/material/fake_brass/Initialize(mapload) - . = ..() - set_custom_materials(list(GET_MATERIAL_REF(/datum/material/brussite) = SHEET_MATERIAL_AMOUNT)) + custom_materials = list(/datum/material/brussite=SHEET_MATERIAL_AMOUNT) /obj/item/plate/oven_tray/material/fake_tin - -/obj/item/plate/oven_tray/material/fake_tin/Initialize(mapload) - . = ..() - set_custom_materials(list(GET_MATERIAL_REF(/datum/material/tinumium) = SHEET_MATERIAL_AMOUNT)) + custom_materials = list(/datum/material/tinumium=SHEET_MATERIAL_AMOUNT) diff --git a/modular_skyrat/modules/primitive_production/code/glassblowing.dm b/modular_skyrat/modules/primitive_production/code/glassblowing.dm index 8dcc4f3cd3a8c6c..ed7b4a31ff860d5 100644 --- a/modular_skyrat/modules/primitive_production/code/glassblowing.dm +++ b/modular_skyrat/modules/primitive_production/code/glassblowing.dm @@ -41,37 +41,24 @@ desc = "A glass bowl that is capable of carrying things." icon = 'modular_skyrat/modules/primitive_production/icons/prim_fun.dmi' icon_state = "glass_bowl" - custom_materials = null + custom_materials = list(/datum/material/glass=SHEET_MATERIAL_AMOUNT) material_flags = MATERIAL_EFFECTS | MATERIAL_COLOR -/obj/item/reagent_containers/cup/bowl/blowing_glass/Initialize(mapload) - . = ..() - set_custom_materials(list(GET_MATERIAL_REF(/datum/material/glass) = SHEET_MATERIAL_AMOUNT)) - /obj/item/reagent_containers/cup/beaker/large/blowing_glass name = "glass cup" desc = "A glass cup that is capable of carrying liquids." icon = 'modular_skyrat/modules/primitive_production/icons/prim_fun.dmi' icon_state = "glass_cup" - custom_materials = null material_flags = MATERIAL_EFFECTS | MATERIAL_COLOR -/obj/item/reagent_containers/cup/beaker/large/blowing_glass/Initialize(mapload) - . = ..() - set_custom_materials(list(GET_MATERIAL_REF(/datum/material/glass) = SHEET_MATERIAL_AMOUNT)) - /obj/item/plate/blowing_glass name = "glass plate" desc = "A glass plate that is capable of carrying things." icon = 'modular_skyrat/modules/primitive_production/icons/prim_fun.dmi' icon_state = "glass_plate" - custom_materials = null + custom_materials = list(/datum/material/glass=SHEET_MATERIAL_AMOUNT) material_flags = MATERIAL_EFFECTS | MATERIAL_COLOR -/obj/item/plate/blowing_glass/Initialize(mapload) - . = ..() - set_custom_materials(list(GET_MATERIAL_REF(/datum/material/glass) = SHEET_MATERIAL_AMOUNT)) - /obj/item/glassblowing/molten_glass name = "molten glass" desc = "A glob of molten glass, ready to be shaped into art." 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 8fcdd735f121424..d2c91ae704d963b 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 @@ -168,6 +168,7 @@ message_admins("[key_name_admin(patient)] has used the Self-Actualization Device, and changed the name of their character. \ Original Name: [original_name], New Name: [patient.dna.real_name]. \ This may be a false positive from changing from a humanized monkey into a character, so be careful.") + SSquirks.AssignQuirks(patient, patient.client) playsound(src, 'sound/machines/microwave/microwave-end.ogg', 100, FALSE) open_machine() diff --git a/modular_skyrat/modules/synths/code/bodyparts/silicon_alt_brains.dm b/modular_skyrat/modules/synths/code/bodyparts/silicon_alt_brains.dm index 35ed52874b3e8a7..c9719cde0518154 100644 --- a/modular_skyrat/modules/synths/code/bodyparts/silicon_alt_brains.dm +++ b/modular_skyrat/modules/synths/code/bodyparts/silicon_alt_brains.dm @@ -42,7 +42,7 @@ if(!mmi || !new_mmi || new_mmi == mmi.type) return - new_mmi = new new_mmi() + new_mmi = new new_mmi(autoping = FALSE) // Probably shitcode, but silicon code is spaghetti as fuck. new_mmi.brain = new /obj/item/organ/internal/brain(new_mmi) diff --git a/modular_skyrat/modules/teshari/code/birdman_food.dm b/modular_skyrat/modules/teshari/code/birdman_food.dm index aba9342a0a5ec32..2466f5ed80dd035 100644 --- a/modular_skyrat/modules/teshari/code/birdman_food.dm +++ b/modular_skyrat/modules/teshari/code/birdman_food.dm @@ -64,7 +64,7 @@ icon_state = "chicken_patty" /datum/food_processor_process/meat/chicken - blacklist = list(/obj/item/food/meat/slab/chicken) + blacklist = list(/obj/item/food/meat/slab/chicken/human) /datum/food_processor_process/meat/chicken/human input = /obj/item/food/meat/slab/chicken/human diff --git a/modular_skyrat/modules/xenos_skyrat_redo/code/base_skyrat_xeno.dm b/modular_skyrat/modules/xenos_skyrat_redo/code/base_skyrat_xeno.dm index c4297e8babdbdce..a4b57732f689a10 100644 --- a/modular_skyrat/modules/xenos_skyrat_redo/code/base_skyrat_xeno.dm +++ b/modular_skyrat/modules/xenos_skyrat_redo/code/base_skyrat_xeno.dm @@ -7,6 +7,7 @@ base_pixel_x = -16 //All of the xeno sprites are 64x64, and we want them to be level with the tile they are on, much like oversized quirk users mob_size = MOB_SIZE_LARGE layer = LARGE_MOB_LAYER //above most mobs, but below speechbubbles + plane = ABOVE_GAME_PLANE maptext_height = 64 maptext_width = 64 pressure_resistance = 200 diff --git a/sound/attributions.txt b/sound/attributions.txt index 82486a5735da087..c81aa3e664b67ab 100644 --- a/sound/attributions.txt +++ b/sound/attributions.txt @@ -117,6 +117,9 @@ https://freesound.org/people/humanoide9000/sounds/330293/ reel1.ogg, reel2.ogg, reel3.ogg, reel4.ogg and reel5.ogg adapted from pixabay. Free for use under the Pixabay Content License (https://pixabay.com/service/license-summary/): https://pixabay.com/sound-effects/reel-78063/ +rattle1.ogg, rattle2.ogg and rattle3.ogg adapted from pixabay. Free for use under the Pixabay Content License (https://pixabay.com/service/license-summary/): +https://pixabay.com/sound-effects/chain-6073/ + throw.ogg, throwhard.ogg and throwsoft.ogg (Royalty-Free and Copyright-Free) are adapted from Jam FX, SmartSound FX and Epic Stock Media in : https://uppbeat.io/sfx/whoosh-swift-cut/7727/23617 https://uppbeat.io/sfx/whoosh-air-punch/114/1168 diff --git a/sound/effects/footstep/moffstep01.ogg b/sound/effects/footstep/moffstep01.ogg new file mode 100644 index 000000000000000..6350cb057bf0b31 Binary files /dev/null and b/sound/effects/footstep/moffstep01.ogg differ diff --git a/sound/items/rattle1.ogg b/sound/items/rattle1.ogg new file mode 100644 index 000000000000000..71c4110fafe46c3 Binary files /dev/null and b/sound/items/rattle1.ogg differ diff --git a/sound/items/rattle2.ogg b/sound/items/rattle2.ogg new file mode 100644 index 000000000000000..30f0e2d85ea935f Binary files /dev/null and b/sound/items/rattle2.ogg differ diff --git a/sound/items/rattle3.ogg b/sound/items/rattle3.ogg new file mode 100644 index 000000000000000..ef1cfc6bf6b6fcb Binary files /dev/null and b/sound/items/rattle3.ogg differ diff --git a/tgstation.dme b/tgstation.dme index f1cbe95e7c58d1f..f03bcbf5c1fcb69 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -337,7 +337,6 @@ #include "code\__DEFINES\dcs\signals\signals_radiation.dm" #include "code\__DEFINES\dcs\signals\signals_reagent.dm" #include "code\__DEFINES\dcs\signals\signals_restaurant.dm" -#include "code\__DEFINES\dcs\signals\signals_saboteur.dm" #include "code\__DEFINES\dcs\signals\signals_scangate.dm" #include "code\__DEFINES\dcs\signals\signals_screentips.dm" #include "code\__DEFINES\dcs\signals\signals_spatial_grid.dm" @@ -723,7 +722,6 @@ #include "code\controllers\subsystem\disease.dm" #include "code\controllers\subsystem\early_assets.dm" #include "code\controllers\subsystem\economy.dm" -#include "code\controllers\subsystem\eigenstate.dm" #include "code\controllers\subsystem\events.dm" #include "code\controllers\subsystem\explosions.dm" #include "code\controllers\subsystem\fluids.dm" @@ -819,6 +817,7 @@ #include "code\controllers\subsystem\persistence\custom_outfits.dm" #include "code\controllers\subsystem\persistence\engravings.dm" #include "code\controllers\subsystem\persistence\photo_albums.dm" +#include "code\controllers\subsystem\persistence\piggy_banks.dm" #include "code\controllers\subsystem\persistence\recipes.dm" #include "code\controllers\subsystem\persistence\scars.dm" #include "code\controllers\subsystem\persistence\tattoos.dm" @@ -860,6 +859,7 @@ #include "code\datums\dna.dm" #include "code\datums\dog_fashion.dm" #include "code\datums\ductnet.dm" +#include "code\datums\eigenstate.dm" #include "code\datums\emotes.dm" #include "code\datums\ert.dm" #include "code\datums\hailer_phrase.dm" @@ -1100,7 +1100,6 @@ #include "code\datums\components\areabound.dm" #include "code\datums\components\armor_plate.dm" #include "code\datums\components\atmos_reaction_recorder.dm" -#include "code\datums\components\attached_sticker.dm" #include "code\datums\components\aura_healing.dm" #include "code\datums\components\bakeable.dm" #include "code\datums\components\basic_inhands.dm" @@ -1283,6 +1282,7 @@ #include "code\datums\components\squeak.dm" #include "code\datums\components\stationloving.dm" #include "code\datums\components\stationstuck.dm" +#include "code\datums\components\sticker.dm" #include "code\datums\components\storm_hating.dm" #include "code\datums\components\strong_pull.dm" #include "code\datums\components\subtype_picker.dm" @@ -1462,6 +1462,7 @@ #include "code\datums\elements\bugkiller_reagent.dm" #include "code\datums\elements\bump_click.dm" #include "code\datums\elements\can_barricade.dm" +#include "code\datums\elements\can_shatter.dm" #include "code\datums\elements\caseless.dm" #include "code\datums\elements\chemical_transfer.dm" #include "code\datums\elements\chewable.dm" @@ -1516,6 +1517,7 @@ #include "code\datums\elements\hostile_machine.dm" #include "code\datums\elements\human_biter.dm" #include "code\datums\elements\immerse.dm" +#include "code\datums\elements\inverted_movement.dm" #include "code\datums\elements\item_fov.dm" #include "code\datums\elements\item_scaling.dm" #include "code\datums\elements\kneecapping.dm" @@ -1555,7 +1557,6 @@ #include "code\datums\elements\rust.dm" #include "code\datums\elements\selfknockback.dm" #include "code\datums\elements\series.dm" -#include "code\datums\elements\shatters_when_thrown.dm" #include "code\datums\elements\sideway_movement.dm" #include "code\datums\elements\simple_flying.dm" #include "code\datums\elements\skill_reward.dm" @@ -1565,7 +1566,6 @@ #include "code\datums\elements\spooky.dm" #include "code\datums\elements\squish.dm" #include "code\datums\elements\squish_sound.dm" -#include "code\datums\elements\sticker.dm" #include "code\datums\elements\strippable.dm" #include "code\datums\elements\structure_repair.dm" #include "code\datums\elements\swabbable.dm" @@ -1867,10 +1867,11 @@ #include "code\datums\status_effects\song_effects.dm" #include "code\datums\status_effects\stacking_effect.dm" #include "code\datums\status_effects\wound_effects.dm" -#include "code\datums\status_effects\buffs\food_haste.dm" -#include "code\datums\status_effects\buffs\food_traits.dm" #include "code\datums\status_effects\buffs\stop_drop_roll.dm" #include "code\datums\status_effects\buffs\stun_absorption.dm" +#include "code\datums\status_effects\buffs\food\chilling.dm" +#include "code\datums\status_effects\buffs\food\food_traits.dm" +#include "code\datums\status_effects\buffs\food\haste.dm" #include "code\datums\status_effects\debuffs\blindness.dm" #include "code\datums\status_effects\debuffs\choke.dm" #include "code\datums\status_effects\debuffs\confusion.dm" @@ -1929,6 +1930,7 @@ #include "code\datums\wires\airlock.dm" #include "code\datums\wires\apc.dm" #include "code\datums\wires\autolathe.dm" +#include "code\datums\wires\collar_bomb.dm" #include "code\datums\wires\conveyor.dm" #include "code\datums\wires\ecto_sniffer.dm" #include "code\datums\wires\emitter.dm" @@ -2206,6 +2208,7 @@ #include "code\game\objects\effects\info.dm" #include "code\game\objects\effects\landmarks.dm" #include "code\game\objects\effects\lighting.dm" +#include "code\game\objects\effects\material_insert.dm" #include "code\game\objects\effects\mines.dm" #include "code\game\objects\effects\misc.dm" #include "code\game\objects\effects\overlays.dm" @@ -2309,6 +2312,7 @@ #include "code\game\objects\items\botpad_remote.dm" #include "code\game\objects\items\boxcutter.dm" #include "code\game\objects\items\broom.dm" +#include "code\game\objects\items\busts_and_figurines.dm" #include "code\game\objects\items\cardboard_cutouts.dm" #include "code\game\objects\items\cards_ids.dm" #include "code\game\objects\items\chainsaw.dm" @@ -2363,6 +2367,7 @@ #include "code\game\objects\items\paint.dm" #include "code\game\objects\items\paiwire.dm" #include "code\game\objects\items\pet_carrier.dm" +#include "code\game\objects\items\piggy_bank.dm" #include "code\game\objects\items\pillow.dm" #include "code\game\objects\items\pinpointer.dm" #include "code\game\objects\items\pitchfork.dm" @@ -2381,7 +2386,7 @@ #include "code\game\objects\items\signs.dm" #include "code\game\objects\items\skub.dm" #include "code\game\objects\items\spear.dm" -#include "code\game\objects\items\sticker.dm" +#include "code\game\objects\items\stickers.dm" #include "code\game\objects\items\surgery_tray.dm" #include "code\game\objects\items\syndie_spraycan.dm" #include "code\game\objects\items\tail_pin.dm" @@ -3818,6 +3823,7 @@ #include "code\modules\clothing\masks\muzzle.dm" #include "code\modules\clothing\masks\surgical.dm" #include "code\modules\clothing\neck\_neck.dm" +#include "code\modules\clothing\neck\collar_bomb.dm" #include "code\modules\clothing\outfits\ert.dm" #include "code\modules\clothing\outfits\event.dm" #include "code\modules\clothing\outfits\plasmaman.dm" @@ -3909,6 +3915,7 @@ #include "code\modules\deathmatch\deathmatch_lobby.dm" #include "code\modules\deathmatch\deathmatch_mapping.dm" #include "code\modules\deathmatch\deathmatch_maps.dm" +#include "code\modules\deathmatch\deathmatch_modifier.dm" #include "code\modules\detectivework\evidence.dm" #include "code\modules\detectivework\scanner.dm" #include "code\modules\discord\accountlink.dm" @@ -4349,6 +4356,7 @@ #include "code\modules\jobs\job_types\spawner\zombie.dm" #include "code\modules\jobs\job_types\station_trait\bridge_assistant.dm" #include "code\modules\jobs\job_types\station_trait\cargo_gorilla.dm" +#include "code\modules\jobs\job_types\station_trait\veteran_advisor.dm" #include "code\modules\keybindings\bindings_atom.dm" #include "code\modules\keybindings\bindings_client.dm" #include "code\modules\keybindings\focus.dm" @@ -5082,7 +5090,6 @@ #include "code\modules\mob\living\simple_animal\hostile\mining_mobs\curse_blob.dm" #include "code\modules\mob\living\simple_animal\hostile\mining_mobs\mining_mobs.dm" #include "code\modules\mob\living\simple_animal\hostile\mining_mobs\polarbear.dm" -#include "code\modules\mob\living\simple_animal\hostile\mining_mobs\wolf.dm" #include "code\modules\mob\living\simple_animal\hostile\mining_mobs\elites\elite.dm" #include "code\modules\mob\living\simple_animal\hostile\mining_mobs\elites\goliath_broodmother.dm" #include "code\modules\mob\living\simple_animal\hostile\mining_mobs\elites\herald.dm" @@ -5188,6 +5195,7 @@ #include "code\modules\modular_computers\file_system\programs\powermonitor.dm" #include "code\modules\modular_computers\file_system\programs\radar.dm" #include "code\modules\modular_computers\file_system\programs\records.dm" +#include "code\modules\modular_computers\file_system\programs\restock_tracker.dm" #include "code\modules\modular_computers\file_system\programs\robocontrol.dm" #include "code\modules\modular_computers\file_system\programs\robotact.dm" #include "code\modules\modular_computers\file_system\programs\secureye.dm" @@ -5462,12 +5470,12 @@ #include "code\modules\projectiles\projectile\special\floral.dm" #include "code\modules\projectiles\projectile\special\gravity.dm" #include "code\modules\projectiles\projectile\special\ion.dm" -#include "code\modules\projectiles\projectile\special\lightbreaker.dm" #include "code\modules\projectiles\projectile\special\meteor.dm" #include "code\modules\projectiles\projectile\special\mindflayer.dm" #include "code\modules\projectiles\projectile\special\neurotoxin.dm" #include "code\modules\projectiles\projectile\special\plasma.dm" #include "code\modules\projectiles\projectile\special\rocket.dm" +#include "code\modules\projectiles\projectile\special\saboteur.dm" #include "code\modules\projectiles\projectile\special\temperature.dm" #include "code\modules\projectiles\projectile\special\wormhole.dm" #include "code\modules\reagents\chem_splash.dm" @@ -5764,6 +5772,7 @@ #include "code\modules\spells\spell_types\shapeshift\_shape_status.dm" #include "code\modules\spells\spell_types\shapeshift\_shapeshift.dm" #include "code\modules\spells\spell_types\shapeshift\dragon.dm" +#include "code\modules\spells\spell_types\shapeshift\gorilla.dm" #include "code\modules\spells\spell_types\shapeshift\polar_bear.dm" #include "code\modules\spells\spell_types\shapeshift\shapechange.dm" #include "code\modules\spells\spell_types\teleport\_teleport.dm" @@ -6029,6 +6038,7 @@ #include "code\modules\vending\engineering.dm" #include "code\modules\vending\engivend.dm" #include "code\modules\vending\games.dm" +#include "code\modules\vending\hotdog.dm" #include "code\modules\vending\liberation.dm" #include "code\modules\vending\liberation_toy.dm" #include "code\modules\vending\magivend.dm" @@ -6527,6 +6537,7 @@ #include "modular_skyrat\master_files\code\modules\reagents\medicine_reagents\medicine_reagents.dm" #include "modular_skyrat\master_files\code\modules\reagents\withdrawal\generic_addictions.dm" #include "modular_skyrat\master_files\code\modules\religion\religious_sects.dm" +#include "modular_skyrat\master_files\code\modules\research\designs\AI_module_designs.dm" #include "modular_skyrat\master_files\code\modules\research\designs\biogenerator_designs.dm" #include "modular_skyrat\master_files\code\modules\research\designs\limbgrower_designs.dm" #include "modular_skyrat\master_files\code\modules\research\designs\mechfabricator_designs.dm" @@ -6770,6 +6781,7 @@ #include "modular_skyrat\modules\blueshield\code\closet.dm" #include "modular_skyrat\modules\blueshield\code\clothing.dm" #include "modular_skyrat\modules\blueshield\code\encryptionkey.dm" +#include "modular_skyrat\modules\blueshield\code\energy_resholver.dm" #include "modular_skyrat\modules\blueshield\code\landmarks.dm" #include "modular_skyrat\modules\blueshield\code\medkit.dm" #include "modular_skyrat\modules\blueshield\code\devices\crew.dm" diff --git a/tgui/packages/tgui-dev-server/util.js b/tgui/packages/tgui-dev-server/util.js index 79190fe189a4af6..13fbef3b21b70a2 100644 --- a/tgui/packages/tgui-dev-server/util.js +++ b/tgui/packages/tgui-dev-server/util.js @@ -20,6 +20,7 @@ export const resolveGlob = (...sections) => { const unsafePaths = globPkg.sync(path.resolve(...sections), { strict: false, silent: true, + windowsPathsNoEscape: true, }); const safePaths = []; for (let path of unsafePaths) { diff --git a/tgui/packages/tgui/components/Collapsible.tsx b/tgui/packages/tgui/components/Collapsible.tsx index b470ed5ce6ddfb5..9f5f944b0ec0454 100644 --- a/tgui/packages/tgui/components/Collapsible.tsx +++ b/tgui/packages/tgui/components/Collapsible.tsx @@ -13,11 +13,12 @@ type Props = Partial<{ buttons: ReactNode; open: boolean; title: ReactNode; + icon: string; }> & BoxProps; export function Collapsible(props: Props) { - const { children, color, title, buttons, ...rest } = props; + const { children, color, title, buttons, icon, ...rest } = props; const [open, setOpen] = useState(props.open); return ( @@ -27,7 +28,7 @@ export function Collapsible(props: Props) { + + )} + + Repeats Left: + + act('set_repeat_amount', { + amount: value, + }) + } + /> + + + {!!can_switch_instrument && ( + + Instrument Using + + instrument.name, + )} + onSelected={(value) => + act('change_instrument', { + new_instrument: instrument_id_by_name(value), + }) + } + /> + + + )} + + + + Playback Settings: + + + act('set_note_shift', { + amount: value, + }) + } + /> + keys / {octaves} octaves + + + Mode: + + + act('set_sustain_mode', { + new_mode: value, + }) + } + /> + + + + {sustain_mode_button}: + + act('edit_sustain_mode', { + amount: value, + }) + } + /> + + + + + + Status: + {instrument_ready ? ( + Ready + ) : ( + + {' '} + Instrument Definition Error! + + )} + + + Volume: + + act('set_volume', { + amount: value, + }) + } + /> + + + Volume Dropoff Threshold: + + act('set_dropoff_volume', { + amount: value, + }) + } + /> + + + + + + + + ); +}; + +const EditingSettings = (props) => { + const { act, data } = useBackend(); + const { bpm, lines } = data; + + return ( +
+ + + + + + Tempo:{' '} + {' '} + {bpm} BPM{' '} + + + + {lines.map((line, index) => ( + + Line {index}: + + + {line.line_text} + + ))} + + + + +
+ ); +}; + +const HelpSection = (props) => { + const { data } = useBackend(); + const { max_line_chars, max_lines } = data; + + return ( +
+ + Lines are a series of chords, separated by commas (,), each with notes + separated by hyphens (-). +
+ Every note in a chord will play together, with chord timed by the tempo. +
+ Notes are played by the names of the note, and optionally, the + accidental, and/or the octave number. +
+ By default, every note is natural and in octave 3. Defining otherwise is + remembered for each note. +
+ Example: C,D,E,F,G,A,B will play a C major scale. +
+ After a note has an accidental placed, it will be remembered:{' '} + C,C4,C,C3 is C3,C4,C4,C3 +
+ Chords can be played simply by seperating each note with a hyphon:{' '} + A-C#,Cn-E,E-G#,Gn-B +
A pause may be denoted by an empty chord: C,E,,C,G +
+ To make a chord be a different time, end it with /x, where the chord + length will be length +
+ defined by tempo / x: C,G/2,E/4 +
+ Combined, an example is: E-E4/4,F#/2,G#/8,B/8,E3-E4/4 +
+ Lines may be up to {max_line_chars} characters. +
A song may only contain up to {max_lines} lines. +
+
+
+ ); +}; diff --git a/tgui/packages/tgui/interfaces/MassSpec.jsx b/tgui/packages/tgui/interfaces/MassSpec.jsx deleted file mode 100644 index 29d7fb8269dc375..000000000000000 --- a/tgui/packages/tgui/interfaces/MassSpec.jsx +++ /dev/null @@ -1,389 +0,0 @@ -import { round } from 'common/math'; - -import { useBackend } from '../backend'; -import { - Box, - Button, - Dimmer, - Icon, - Section, - Slider, - Table, -} from '../components'; -import { Window } from '../layouts'; - -export const MassSpec = (props) => { - const { act, data } = useBackend(); - const { - processing, - lowerRange, - upperRange, - graphUpperRange, - graphLowerRange, - eta, - beaker1CurrentVolume, - beaker2CurrentVolume, - beaker1MaxVolume, - beaker2MaxVolume, - peakHeight, - beaker1, - beaker2, - beaker1Contents = [], - beaker2Contents = [], - } = data; - - const centerValue = (lowerRange + upperRange) / 2; - - return ( - - - {!!processing && ( - - - {' Purifying... ' + round(eta) + 's'} - - )} -
act('activate')} - /> - } - > - {(beaker1Contents.length && ( - - )) || Please insert an input beaker with reagents!} -
- -
- {!!beaker1MaxVolume && ( - - {beaker1CurrentVolume} / {beaker1MaxVolume} units - - )} -
-
- {!!beaker2MaxVolume && ( - - {beaker2CurrentVolume} / {beaker2MaxVolume} units - - )} -
-
-
- ); -}; - -const BeakerMassProfile = (props) => { - const { loaded, details, beaker = [] } = props; - - return ( - - {(!loaded && No beaker loaded.) || - (beaker.length === 0 && Beaker is empty.) || ( - - - - Reagent - - - Volume - - - Mass - - - Purity - - - Type - - {!!details && ( - - Results - - )} - - {beaker.map((reagent) => ( - - - {reagent.name} - - - {reagent.volume} - - - {reagent.mass} - - - {`${reagent.purity}%`} - - - ▮{reagent.type} - - {!!details && {reagent.log}} - - ))} -
- )} -
- ); -}; - -const MassSpectroscopy = (props) => { - const { act, data } = useBackend(); - const { - lowerRange, - centerValue, - upperRange, - graphUpperRange, - graphLowerRange, - maxAbsorbance, - reagentPeaks = [], - } = props; - - const deltaRange = graphUpperRange - graphLowerRange; - - const graphIncrement = deltaRange * 0.2; - - return ( - <> - - - - {/* x axis*/} - - Mass (g) - - - {graphLowerRange} - - - {round(graphLowerRange + graphIncrement, 1)} - - - {round(graphLowerRange + graphIncrement * 2, 1)} - - - {round(graphLowerRange + graphIncrement * 3, 1)} - - - {round(graphLowerRange + graphIncrement * 4, 1)} - - - {graphUpperRange} - - {/* y axis*/} - - {round(maxAbsorbance, 1)} - - - {round(maxAbsorbance * 0.8, 1)} - - - {round(maxAbsorbance * 0.6, 1)} - - - {round(maxAbsorbance * 0.4, 1)} - - - {round(maxAbsorbance * 0.2, 1)} - - - 0 - - - - - Absorbance (AU) - - - - {reagentPeaks.map((peak) => ( - // Triangle peak - - ))} - - - - - - - - round(value)} - width={(centerValue / graphUpperRange) * 400 + 'px'} - value={lowerRange} - minValue={graphLowerRange} - maxValue={centerValue} - color={'invisible'} - onDrag={(e, value) => - act('leftSlider', { - value: value, - }) - } - > - {' '} - - round(value)} - step={graphUpperRange / 400} - width={400 - (centerValue / graphUpperRange) * 400 + 'px'} - value={upperRange} - minValue={centerValue} - maxValue={graphUpperRange} - color={'invisible'} - onDrag={(e, value) => - act('rightSlider', { - value: value, - }) - } - > - {' '} - - - round(value)} - width={400 + 'px'} - minValue={graphLowerRange + 1} - maxValue={graphUpperRange - 1} - color={'invisible'} - onDrag={(e, value) => - act('centerSlider', { - value: value, - }) - } - > - {' '} - - - - - ); -}; diff --git a/tgui/packages/tgui/interfaces/MassSpec.tsx b/tgui/packages/tgui/interfaces/MassSpec.tsx new file mode 100644 index 000000000000000..672157ad8d011d5 --- /dev/null +++ b/tgui/packages/tgui/interfaces/MassSpec.tsx @@ -0,0 +1,456 @@ +import { round } from 'common/math'; +import { BooleanLike } from 'common/react'; + +import { useBackend } from '../backend'; +import { + Box, + Button, + Dimmer, + Icon, + Section, + Slider, + Table, +} from '../components'; +import { Window } from '../layouts'; + +type Reagent = { + name: string; + volume: number; + mass: number; + purity: number; + type: string; + log: string; +}; + +type Beaker = { + currentVolume: number; + maxVolume: number; + contents: Reagent[]; +}; + +type Data = { + lowerRange: number; + upperRange: number; + processing: BooleanLike; + eta: number; + graphUpperRange: number; + peakHeight: number; + beaker1: Beaker; + beaker2: Beaker; +}; + +const GRAPH_MAX_WIDTH = 1060; +const GRAPH_MAX_HEIGHT = 250; + +export const MassSpec = (props) => { + const { act, data } = useBackend(); + const { + processing, + lowerRange, + upperRange, + graphUpperRange, + eta, + peakHeight, + beaker1, + beaker2, + } = data; + + const centerValue = (lowerRange + upperRange) / 2; + const beaker_1_has_contents = beaker1?.contents?.length > 0; + + return ( + + + {!!processing && ( + + + {' Purifying... ' + round(eta, 0) + 's'} + + )} +
act('activate')} + > + Start + + } + > + {(beaker_1_has_contents && ( + + )) || Please insert an input beaker with reagents!} +
+ +
+ { + + {beaker1.currentVolume} / {beaker1.maxVolume} units + + } + + + ) + } + > + + {!!beaker_1_has_contents && ( + {'Eta of selection: ' + round(eta, 0) + ' seconds'} + )} +
+
+ { + + {beaker2.currentVolume} / {beaker2.maxVolume} units + + } + + + ) + } + > + +
+
+
+ ); +}; + +type ProfileProps = { + lowerRange: number; + upperRange: number; + beaker: Beaker; +}; + +const BeakerMassProfile = (props: ProfileProps) => { + const { lowerRange, upperRange, beaker } = props; + + return ( + + {(!beaker && No beaker loaded.) || + (beaker.contents.length === 0 && ( + Beaker is empty. + )) || ( + + + + Reagent + + + Mass + + + Volume + + + Purity + + + Type + + + Status + + + {beaker.contents.map((reagent) => { + const selected = + reagent.mass >= lowerRange && reagent.mass <= upperRange; + const color = reagent.type === 'Inverted' ? '#b60046' : '#3cf096'; + + return ( + + + {reagent.name} + + + {reagent.mass} + + + {reagent.volume} + + + {`${reagent.purity}%`} + + + ▮{reagent.type} + + {{reagent.log}} + + ); + })} +
+ )} +
+ ); +}; + +type SpectroscopyProps = { + lowerRange: number; + centerValue: number; + upperRange: number; + graphUpperRange: number; + maxAbsorbance: number; + reagentPeaks: Reagent[]; +}; + +const MassSpectroscopy = (props: SpectroscopyProps) => { + const { act } = useBackend(); + const { + lowerRange, + centerValue, + upperRange, + graphUpperRange, + maxAbsorbance, + reagentPeaks = [], + } = props; + + const graphLowerRange = 0; + const deltaRange = graphUpperRange - graphLowerRange; + const graphIncrement = deltaRange * 0.2; + + const base_line = GRAPH_MAX_HEIGHT * 0.85; + const base_width = GRAPH_MAX_WIDTH - 123; + const x_scale = base_width / GRAPH_MAX_WIDTH; + const y_scale = base_line / GRAPH_MAX_HEIGHT; + + return ( + + + {/* x axis*/} + + + Mass (G) + + + {graphLowerRange} + + + {round(graphLowerRange + graphIncrement, 1)} + + + {round(graphLowerRange + graphIncrement * 2, 1)} + + + {round(graphLowerRange + graphIncrement * 3, 1)} + + + {round(graphLowerRange + graphIncrement * 4, 1)} + + + {graphUpperRange} + + + + + {/* y axis*/} + + + 0 + + + {round(maxAbsorbance * 0.2, 1)} + + + {round(maxAbsorbance * 0.4, 1)} + + + {round(maxAbsorbance * 0.6, 1)} + + + {round(maxAbsorbance * 0.8, 1)} + + + {round(maxAbsorbance, 1)} + + + + Absorbance (AU) + + + + {/* Graph */} + + {reagentPeaks.map((peak) => ( + <> + {/* Triangle peak */} + + + {/* Background */} + + + ))} + + + + {/* Sliders */} + round(value, 2)} + width={(centerValue / graphUpperRange) * base_width + 'px'} + value={lowerRange} + minValue={graphLowerRange} + maxValue={centerValue} + color={'invisible'} + onDrag={(e, value) => + act('leftSlider', { + value: value, + }) + } + /> + round(value, 2)} + step={graphUpperRange / base_width} + width={base_width - (centerValue / graphUpperRange) * base_width + 'px'} + value={upperRange} + minValue={centerValue} + maxValue={graphUpperRange} + color={'invisible'} + onDrag={(e, value) => + act('rightSlider', { + value: value, + }) + } + /> + round(value, 2)} + width={base_width + 'px'} + minValue={graphLowerRange + 1} + maxValue={graphUpperRange - 1} + color={'invisible'} + onDrag={(e, value) => + act('centerSlider', { + value: value, + }) + } + /> + + ); +}; diff --git a/tgui/packages/tgui/interfaces/MatMarket.tsx b/tgui/packages/tgui/interfaces/MatMarket.tsx index 41b25dedb00216c..1f6d69c8d69e3da 100644 --- a/tgui/packages/tgui/interfaces/MatMarket.tsx +++ b/tgui/packages/tgui/interfaces/MatMarket.tsx @@ -1,14 +1,23 @@ +import { sortBy } from 'common/collections'; import { BooleanLike } from 'common/react'; import { toTitleCase } from 'common/string'; import { useBackend } from '../backend'; -import { Button, Modal, Section, Stack } from '../components'; +import { + Button, + Collapsible, + Modal, + NoticeBox, + Section, + Stack, +} from '../components'; import { formatMoney } from '../format'; import { Window } from '../layouts'; type Material = { name: string; quantity: number; + rarity: number; trend: string; price: number; threshold: number; @@ -24,6 +33,7 @@ type Data = { materials: Material[]; catastrophe: BooleanLike; CARGO_CRATE_VALUE: number; + updateTime: number; }; export const MatMarket = (props) => { @@ -66,24 +76,35 @@ export const MatMarket = (props) => { ) } > - Buy orders for material sheets placed here will be ordered on the next - cargo shipment. -

- To sell materials, please insert sheets or similar stacks of - materials. All minerals sold on the market directly are subject to an - 20% market fee. To prevent market manipulation, all registered traders - can buy a total of 10 full stacks of materials at a time. -

- All new purchases will include the cost of the shipped crate, - which may be recycled afterwards. + + + Buy orders for material sheets placed here will be ordered on the + next cargo shipment. +

+ To sell materials, please insert sheets or similar stacks of + materials. All minerals sold on the market directly are subject to + an 20% market fee. To prevent market manipulation, all registered + traders can buy a total of 10 full stacks of materials at a time. +

+ All new purchases will include the cost of the shipped crate, + which may be recycled afterwards. +
+
- + Current Credit Balance: {formatMoney(creditBalance)} cr. - + Current Order Cost: {formatMoney(orderBalance)} cr. + 150 ? 'green' : '#ad7526'} + > + {Math.round(data.updateTime / 10)} seconds until next + update +
- {materials.map((material, i) => ( -
- - - - - {toTitleCase(material.name)} - - - - Trading at {formatMoney(material.price)} cr. - - {material.price < material.threshold ? ( - - Material price critical! -
Trading temporarily suspended. + {sortBy((tempmat: Material) => tempmat.rarity)(materials).map( + (material, i) => ( +
+ + + + + {toTitleCase(material.name)} - ) : ( - - {material.quantity || 'Zero'} sheets of{' '} - {material.name} trading.{' '} - {material.requested || 'Zero'} sheets ordered. + + + Trading at {formatMoney(material.price)} cr. - )} + {material.price < material.threshold ? ( + + Material price critical! +
Trading temporarily suspended. +
+ ) : ( + + {material.quantity || 'Zero'} sheets of{' '} + {material.name} trading.{' '} + {material.requested || 'Zero'} sheets ordered. + + )} - + {toTitleCase(material.name)} is trending{' '} + {material.trend}. + +
+
+ + - - - - - - {material.requested > 0 && ( - x {material.requested} - )} -
-
- ))} + Buy 1 + + + + + +
+ {material.requested > 0 && ( + x {material.requested} + )} +
+
+ ), + )} ); diff --git a/tgui/packages/tgui/interfaces/MatrixMathTester.tsx b/tgui/packages/tgui/interfaces/MatrixMathTester.tsx index 1f67fd3f3eb2701..6ba7bce637704ef 100644 --- a/tgui/packages/tgui/interfaces/MatrixMathTester.tsx +++ b/tgui/packages/tgui/interfaces/MatrixMathTester.tsx @@ -9,6 +9,8 @@ const MatrixMathTesterInput = (props: { value: number; varName: string }) => { const { act } = useBackend(); return ( toFixed(value, 3)} @@ -111,6 +113,8 @@ export const MatrixMathTester = (props) => { toFixed(value, 2)} @@ -120,6 +124,8 @@ export const MatrixMathTester = (props) => { toFixed(value, 2)} @@ -142,6 +148,8 @@ export const MatrixMathTester = (props) => { toFixed(value, 0)} @@ -151,6 +159,8 @@ export const MatrixMathTester = (props) => { toFixed(value, 0)} @@ -171,6 +181,8 @@ export const MatrixMathTester = (props) => { toFixed(value, 3)} @@ -180,6 +192,8 @@ export const MatrixMathTester = (props) => { toFixed(value, 3)} diff --git a/tgui/packages/tgui/interfaces/Mecha/ModulesPane.tsx b/tgui/packages/tgui/interfaces/Mecha/ModulesPane.tsx index 99b0fd4b7a78f9e..f8f6af31f3e322e 100644 --- a/tgui/packages/tgui/interfaces/Mecha/ModulesPane.tsx +++ b/tgui/packages/tgui/interfaces/Mecha/ModulesPane.tsx @@ -547,7 +547,7 @@ const SnowflakeRadio = (props) => { { minValue={tank_pump_pressure_min} maxValue={tank_pump_pressure_max} step={10} - format={(value) => Math.round(value)} + format={(value) => `${Math.round(value)}`} onChange={(e, value) => act('equip_act', { ref: ref, diff --git a/tgui/packages/tgui/interfaces/Newscaster.jsx b/tgui/packages/tgui/interfaces/Newscaster.jsx index b3a30eb2bdd85d3..fc91fc9c89d46ae 100644 --- a/tgui/packages/tgui/interfaces/Newscaster.jsx +++ b/tgui/packages/tgui/interfaces/Newscaster.jsx @@ -447,6 +447,7 @@ const NewscasterChannelBox = (props) => {